how can I change string in other function when I am using malloc?
in main:
char *myString;
changeString(myString);
changeString(char *myString){
myString = malloc((size) * sizeof(char));
myString[1] = 'a';
}
Thank you
Parameters in C are passed by value. So to modify a variable within a function, you'll have to pass the pointer to it. For example, int * to int, and char ** to char *.
void changeString(char **myString){
// free(*myString); // add when myString is allocated using malloc()
*myString = malloc(2);
(*myString)[0] = 'a';
(*myString)[1] = '\0';
}
Allocate memory in main, then pass a pointer to start of allocated memory to the function.
Also pass a variable containing the size of the allocated memory to the function, so that you can ensure that the new text does not overflow the allocated memory.
The modified string is available from main.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void changeString(char *stringptr, int sz);
int main(void)
{
const int a_sz = 16;
/* allocate memory for string & test successful allocation*/
char *myString = malloc(a_sz);
if (myString == NULL) {
printf("Out of memory!\n");
return(1);
}
/* put some initial characters into String */
strcpy(myString, "Nonsense");
/* print the original */
printf("Old text: %s\n", myString);
/* call function that will change the string */
changeString(myString, a_sz);
/* print out the modified string */
printf("New text: %s\n", myString);
/* free the memory allocated */
free(myString);
}
void changeString(char *stringptr, int sz)
{
/* text to copy into array */
char *tocopy = "Sense";
/* only copy text if it fits in allocated memory
including one byte for a null terminator */
if (strlen(tocopy) + 1 <= sz) {
strcpy(stringptr, tocopy);
}
}
Related
I am declaring a pointer to a character inside struct, and then taking input from user to store a string in that char pointer, but getting an error,please help
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct arr
{
char *str;
int len;
} s1;
int main()
{
scanf("%s", s1.str);
s1.len = strlen(s1.str);
printf("%d", s1.len);
}
A char* is not enough to store a string, as a char* points to a string.
You need memory space to store the string itself.
Example:
struct arr
{
char str[128]; // will store strings up to 127 bytes long, plus the ending nul byte.
int len;
} s1;
int main()
{
scanf("%127s", s1.str);
s1.len = strlen(s1.str);
printf("%d", s1.len);
}
Dynamic memory allocation
In main function :
s1 *p = (s1 *)malloc(sizeof(s1));
if ( p == NULL )
{
printf("Memory allocation failed \n")
exit (0);
}
p->str = (char*)malloc(sizeof(char)*256); // here 256 bytes allocated
if (p->str)
{
printf("Memory allocation failed \n")
exit (0);
}
Then use :
free(p)
To free the memory previously allocated.
I want to manually set each individual character for my pointer instead of typing out the string/having another array and then simply copying the values. This is homework, but I have it finished.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*function declarations */
void assignAlpha(char *pointer);
void assignNumeric(char *pointer);
int main()
{
char *cp;
assignAlpha(cp);
assignNumeric(cp);
}
void assignAlpha(char *pointer)
{
/* allocate space for a-z character string */
pointer = malloc(26*sizeof(char));
char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
strcpy(pointer, alphabet);
/*print the values*/
printf("%s\n", pointer);
/*free the memory allocated */
free(pointer);
}
void assignNumeric(char *pointer)
{
/* allocate space for the 0-9 character string*/
pointer = malloc(10*sizeof(char));
/* input values */
char alphaArray[10];
int currentChar = 30;
int i;
for(i = 0; i <10; i++)
{
alphaArray[i] = i + '0';
currentChar++;
}
/* copy string to pointer */
strcpy(pointer, alphaArray);
/* print out the results */
printf("%s\n", pointer);
/* free the memory allocated */
free(pointer);
}
What I have tried doing, but it seems to fail:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*function declarations */
void assignAlpha(char *pointer);
void assignNumeric(char *pointer);
int main()
{
char *cp;
assignAlpha(cp);
assignNumeric(cp);
}
void assignAlpha(char *pointer)
{
/* allocate space for a-z character string */
pointer = malloc(26*sizeof(char));
int i;
for (i=0; i < 26; i++)
{
pointer = i + 'a';
pointer++;
}
/*print the values*/
printf("%s\n", pointer);
/*free the memory allocated */
free(pointer);
}
I thought that if I go through each memmory address that I have allocated and set the value to the next character it would work, but I apparently was wrong. Like I said this was a homework assignment, but I could hand in what I have that works and be fine. Any guidance on how to do this (if its possible) would be appericated!
Edit: I get the following error compiling "Assignment makes pointer from integer without a cast"
When you assign to a pointer, you need to dereference it, like this:
*pointer = i + 'a';
Instead of:
pointer = i + 'a';
Otherwise, all you're doing is changing the value of the pointer itself, not the value of the memory location it is pointing to.
This explains your error: you're trying to assign the value i + 'a' (which is an integer) to a pointer type.
Another issue is that your malloc call needs to allocate 27 characters, not 26, because you also need a terminating NUL character.
Finally, when you go to print, your pointer has moved past the end of the string (because you've been incrementing it in your loop). The easiest way to fix this is to change pointer = i + 'a'; to pointer[i] = i + 'a'; and remove the pointer++
I want to write a function that can copy the content of a c-string to another c-string.
#include <stdio.h>
#include <string.h>
void copy(char*,char*);
int main(){
char* string = "hello";
char* destination;
copy(destination,string);
printf("Source: %s\nDestination: %s",string,destination);
system("pause");
return 0;
}
void copy(char* dest, char* src){
dest = malloc(strlen(src)*sizeof(char)); //Crashes
while (*src){
*dest++ = *src++;
}
}
Allocating the memory inside the function makes the program crash while allocating the memory before the function call works:
char* destination = malloc(strlen(string)*sizeof(char)); //works
The primary issue, that has been explained in several different ways, has to do with how you pass dest to copy(). When you pass a pointer to a function, e.g.:
void copy(char* dest, char* src) {
The function receives a copy of the pointer, which will point to the same address, but will have a different address of its own. So when you pass char *dest, the copy() function receives a copy of the dest pointer. When you then allocate dest in copy(), the caller main() has no idea what the address for dest is in copy() and no way of accessing the memory as returned by dest = malloc(strlen(src)*sizeof(char)); in copy().
Whenever you allocate memory in a function, if you are not returning the address for the newly allocated block of memory, you must pass the address of the pointer to the function (not a copy of the pointer). That way when you call malloc, you are assigning the return of malloc (the start address for the new block of memory) as the value of the pointer at the same address as in main().
If you remember nothing else, remember that rule: If you are allocating memory for a pointer you pass to the function, you must either (1) return the new address to the caller; or (2) pass the address of the pointer to the function for allocation.
Here is another example along similar lines with a few different approaches:
#include <stdio.h>
#include <stdlib.h>
void copy (char **dest, char *src);
int main (int argc, char **argv) {
char *str = argc > 1 ? argv[1] :
"A quick brown fox jumps over the lazy dog.";
char *dest = NULL;
copy (&dest, str);
printf ("\n str : %s\n dest : %s\n\n", str, dest);
free (dest); /* free allocated memory */
return 0;
}
void copy (char **dest, char *src)
{
if (!src) { /* validate src string */
fprintf (stderr, "%s() error: invalid string 'src'.\n",
__func__);
return;
}
size_t len = 0;
char *p = src;
for (;*p; p++, len++) {} /* strlen */
/* allocate and validate -- every time */
if (!(*dest = malloc (len * sizeof **dest + 1))) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n",
__func__);
exit (EXIT_FAILURE);
}
p = *dest; /* copy src to dest */
for (; *src; src++) *p++ = *src;
*p = 0; /* null-terminate */
}
Output
$ ./bin/copystr
str : A quick brown fox jumps over the lazy dog.
dest : A quick brown fox jumps over the lazy dog.
Note: if you are not using gcc then change __func__ to the function name.
In your main() function you are declaring a variable destination of type char * without initializing it. You then pass destination as an argument to your copy() function. It's important to understand what data is being passed to copy(). In this case, since destination has not been initialized, we don't know what is being passed to copy(). This is fine when you malloc() before the function call because, in that scenario, destination has been initialized. In particular, its value is some address in the heap that was returned by malloc().
As others have noted, you should also be careful to allocate 1 byte more than the src string length in order to allow space for the null-terminator.
The problem is that copy takes to addresses - the current value of destination and the value of source.
Then it overwrites the current value of destination with the result of malloc.
The copy then occurs, and the malloced memory gets lost.
Either return the value of destination from copy, rather than pass it in.
or use char ** and *.
char * copy( char* src){
char * dest = malloc( (1+strlen(src))*sizeof(char)); //Crashes
char * toReturn = dest;
while (*src){
*dest++ = *src++;
}
return toReturn;
}
or
void copy( char ** dest, char* src){
/* overwrite pointer value with the result of malloc */
char * toCopy;
(*dest) = malloc((1+strlen(src))*sizeof(char)); //Crashes
toCopy = *dest;
while (*src){
*toCopy++ = *src++;
}
}
like the title already states I would like to copy various strings into a two-dimensional array. Each string has a different size therefore I need to use memory reallocation. The code below should do this job, but somehow I cannot get it working.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char **str = NULL;
int str_num = 1;
// get string
char *str_new = "hey mate\0";
printf("%s\n",str_new);
// reallocation for str_new
str = realloc(str,str_num*sizeof(char));
str[str_num-1] = realloc(str,strlen(str_new));
// copy string to new space
strcpy(*str, str_new);
// displaying string
printf("%s\n",str[str_num-1]);
return EXIT_SUCCESS;
}
One problem is in the reallocation:
str = realloc(str,str_num*sizeof(char));
You only allocate space for a single byte and not for a pointer to char. This leds to undefined behavior.
Change to e.g.
str = realloc(str,str_num*sizeof(char*));
Another problem, and also a cause for undefined behavior is the actual string allocation:
str[str_num-1] = realloc(str,strlen(str_new));
Here you are reallocating str and not str[0]. And you don't alocate space for the string terminator.
For this don't use realloc at all, since you're only allocating this once you only need either malloc, or just use the strdup function to do both allocation and copying in one call:
str[str_num - 1] = strdup(str_new);
By the way, when using realloc never assign to the same pointer you're passing in as first argument, because if the realloc function fails it will return NULL and you will loose the original pointer. Instead assign to a temporary pointer, and if it's non-null then assign to the actual pointer.
char **str = malloc(sizeof(char *) * n); /* n= number of pointers */
Allocate memory for the pointer's first then allocate memory to individual pointer like
for(i=0;i<n;i++)
{
str[i] = malloc(sizeof(char) * 20);
/* copy your string to the allocated memory location here*/
}
Else you can have
char **str = NULL;
str = realloc(str,str_num * sizeof(char *));
I think you don't understand what realloc does, the code you posted is not right, that code should be written this way
char **str = NULL;
int str_num = 1;
// get string
char *str_new = "hey mate\0";
printf("%s\n",str_new);
/*
// reallocation for str_new
str = realloc(str, str_num * sizeof(char));
*/
/* allocate space for `str_num` pointers of char */
str = malloc(str_num * sizeof(char *));
if (str == NULL) /* check it worked */
return -1;
/* allocate space for the number of characters in str_new and
* the termination null byte
*/
str[str_num - 1] = malloc(1 + strlen(str_new));
if (str[str_num - 1] == NULL)
{
free(str);
return -1;
}
/*
* // copy string to new space
* strcpy(*str, str_new);
*/
/* use the same index since if str_num > 1 the above is wrong */
strcpy(str[str_num - 1], str_new);
// displaying string
printf("%s\n",str[str_num - 1]);
realloc should be used like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char **str = NULL;
int str_num;
// get string
char *str_new[2] = {"hey mate 1", "hey mate 2"};
for (str_num = 0 ; str_num < 2 ; ++str_num)
{
char **pointer;
printf("%s\n", str_new[str_num]);
/*
// reallocation for str_new
str = realloc(str, str_num * sizeof(char));
*/
/* re-allocate space for `str_num` pointers of char */
pointer = realloc(str, (1 + str_num) * sizeof(char *));
/*
* If you use
*
* str = realloc(str, str_num * sizeof(char *));
*
* you wont be able to free(str) on failure
*/
if (pointer == NULL)
{
int j;
/* on failure cleanup and return */
for (j = str_num - 1 ; j >= 0 ; --j)
free(str[j]);
free(str);
return -1;
}
str = pointer;
/* allocate space for the number of characters in str_new and
* the termination null byte
*/
str[str_num] = malloc(1 + strlen(str_new[str_num]));
if (str[str_num] == NULL)
{
free(str);
return -1;
}
/*
* // copy string to new space
* strcpy(*str, str_new);
*/
/* use the same index since if str_num > 1 the above is wrong */
strcpy(str[str_num], str_new[str_num]);
// displaying string
printf("%s\n",str[str_num]);
}
return EXIT_SUCCESS;
}
you should remember to free all the allocated memory.
Also you don't need to embed the '\0' in a string literal.
Beside correcting (as pointed in Joachim Pileborg's answer)
str = realloc(str,str_num*sizeof(char));
to
str = realloc(str,str_num*sizeof(*str));
you should note that, the pointer passed to realloc must be the pointer returned by any malloc family function or it points to NULL. You can do it as
str[str_num-1] = NULL;
str[str_num-1] = realloc(str[str_num-1], strlen(str_new)+1);
I have been writing C for approximately a week, so bear with me. I'm getting a segmentation fault error in the method assemble_url and I dont know why. Here is my code:
/** Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>
/** Definitions */
#define MAX_OPTIONS 32
#define MAX_ARGS 32
/** Command option */
typedef struct {
char *argname;
char *value;
} command_option;
/** Command */
typedef struct {
command_option options[MAX_OPTIONS];
} command_t;
/**
* Prints the arguments passed in in a hashmap format (key => value)
*/
void populate_command(command_t *cmd,int argc,char *argv[])
{
int i,j=0;
/** Check to see if we have arguments. If argc is equal to 1 than there are no arguments besides the filename */
if(argc>1)
{
/* Start at position 1, since argv[0] is the filename being called */
for(i=1;i<argc;i++)
{
/* Head of argv array */
char *arg = argv[i];
/* Create a copy of head for traversal. */
char *c = arg;
/* traverse the char array, ensuring we arent dealing with NULL values(c!==NULL) and NULL pointers(*c!=='\0') */
while(*c != '\0' && c != NULL)
{
/* Were only concerned with parsing the flags and obtaining the flag value. */
if(strchr("-",*c))
{
char *key = c; /* Key */
char *value = argv[i+1]; /* Value */
/* ensure we have a value existent for key */
if(strchr("-",*value))
{
/** user supplied a key with no value */
break;
}
command_option *option = &cmd->options[j];
option->argname = key;
option->value = value;
j++;
/* Debug dump */
printf("arg %d: %s -> %s\n",i,option->argname,option->value);
}/* end strchr */
/** Increment the traversal array */
c++;
}/* end while loop */
}/* end forloop */
}/* endif */
}/** end print_args */
/**
* Concatenates two strings and returns the resulting concatenated string
*/
char* concatstring(char *s1,char *s2)
{
/* Allocate memory for *result. We add 1 to account for the extra byte to store the null character. Strlen accounts for all
non-null bytes, so using strlen(s1) + strlen(s2) + 1 ensures that an overflow wont occur. An overflow occurs when
the number of bytes being used (in our example, is the addition of strlen for s1 and s2) is more than the number of bytes
allocated (in our example, the number of bytes allocated to *result)*/
char *result = malloc(strlen(s1)+strlen(s2)+1);
/*Copies the C string pointed by source(s1) into the array pointed by destination(result), including the terminating null character. */
strcpy(result,s1);
/* appends a copy of the source string(s2) to the destination string(result). The terminating null character in
destination is overwritten by the first character of source, and a null-character is included at
the end of the new string formed by the concatenation of both in destination.*/
strcat(result,s2);
/* return result */
return result;
} /** end concatstring */
char* assemble_url(command_t *cmd,char *str)
{
int i,opt_len = sizeof(&cmd->options);
for(i=0;i<opt_len;i++)
{
command_option *option = &cmd->options[i];
char *key = option->argname;
char *value = option->value;
if(i==0)
{
str = concatstring(str,key);
str = concatstring(str,"=");
str = concatstring(str,value);
}
else
{
str = concatstring(str,"&");
str = concatstring(str,key);
str = concatstring(str,"=");
str = concatstring(str,value);
}
}
return str;
}
What occurs in this program is the following:
1./ User types in program name and flag options,such as the following:
program -test a -test2 b
2./ The program parses the command and populates a command struct with options. Each option has a flag(argname) and value associated to it(value)
3./ The program then tries to create a URL with those option keys and values, such as http://url/?test=a&test2=b
The program compiles but I'm still new to pointers and references (I think & is called a reference), so maybe that is why the program errors.
Any help is greatly appreciated! Also, if you see any probems or better way to handle assemble_url, please also let me know (I dont think its being handled in the best way, but like I said, I'm extremely new to C programming)
Thanks!
This initialization
int opt_len = sizeof(&cmd->options);
will give you the byte-size of a pointer &cmd->options. This makes no sense in the context of what you are trying to do.
If you want to determine the number of elements in an array (assuming it hasn't decayed to pointer), the proper technique would be
int opt_len = sizeof cmd->options / sizeof *cmd->options;
In this case opt_len will be initialized with MAX_OPTIONS value (meaning that you can just use MAX_OPTIONS in its place).
You have massive memory leaks from concatstring. Each invocation allocates a new buffer but you never bother to free them, and you loose the pointers so no chance of ever freeing that memory again.
This is not the cause of the segfault.
Because you are concatenating more than two strings it would be best if you allocated memory for all concatenations at once.
#include <stdarg.h>
#include <string>
char* stringBuilder(int count, ...)
{
va_list ap, vacnt;
int j;
int len = 1;
char* buffer;
va_start(ap, count);
#ifdef va_copy
va_copy(vacnt,ap);
#else
vacnt = ap;
#endif
for(j=0; j<count; ++j){
len+=strlen(va_arg(vacnt, char*));
}
va_end(vacnt);
buffer = (char*) malloc(len * sizeof(char));
buffer[0]=0;
for (j=0;j<count;++j) {
strcat (buffer, va_arg(ap, char*));
}
va_end(ap);
return buffer;
}
You can use it as such:
char* x = stringBuilder(4,"hello", " ", "world", "\n");
printf(x);
free(x);
Also note that both key and value must be URL-Encoded for the purposes of your application