Before start, let me show you my code:
int main(int argc, char *argv[])
{
t_arbre *node;
char str[3][1];
&(*(str[0])) = strdup("1"); //lvalue required as left operand of assignment
str[1] = strdup("2"); //incompatible types when assigning to type ‘char[1]’ from type ‘char *’
str[2] = strdup("3");
if ((node = malloc(sizeof(t_arbre))) == NULL)
{
printf("Error: malloc in the main function failed\n");
return (-1);
}
create_node(node, str);
return (0);
}
So, as you can see, I'm currently working in C. And I'm trying to assign a (char*) to a (char[3][1]). Otherwise the compiler throw me for error:
incompatible types when assigning to type ‘char[1]’ from type ‘char *’
when I'm trying to assign by the following way:
str[2] = strdup("2");
I'm know that if I declare a string like this
char str[5];
and then try to assign it a string using for example strdup() function, it could trow me the same error. However in this case I know that I can "dereference" it like:
str[0]
Which will give me a (char) variable. And given I want it to store a string. I have to "transform" it into a (char*) by using the '&' charactere. Which will give me
&str[0]
In this case, it will work. because I have a pointer to the first character.
By doing so, I'll be able to copy a (char*) into a (char[]).
Otherwise, in the upper code I provide you, I want to copy a (char*) into a (char[3][1]) (Don't ask me why, it's a bit long to explain haha)
So as you can see, I tried my way to solve the error like
str[2] = strdup("2");
which throw me this error message
incompatible types when assigning to type ‘char[1]’ from type ‘char *’
And by this way
&(*(str[0])) = strdup("1"); //or &(*(str[0]))
which throw me this error message
lvalue required as left operand of assignment
Does anyone can tell me how can I copy a (char*) into a (char[][]) ?
Or is it just imposible to do what I want to do ?
I don't speak english very well, hopeing I used the right term.
Thank you :)
You can't assign to things that aren't intended for assignment, that's what "lvalue required as left operand of assignment" is telling you, because you're taking the address of something with &, which is essentially just a value, not somewhere you can store something (e.g. a variable), and then trying to assign to it.
A char* is not a char[], that's what the incompatible types error is about.
C arrays do not support assignment.
Don't forget that in C, arrays start at index 0, so the last valid index in an array of length 3 is 2 (e.g. arr[2]), not 3.
Use strcpy() instead to copy a string into an array:
char str[3][2]; // must allow space for the null terminator
strcpy(str[0], "1");
strcpy(str[1], "2");
strcpy(str[2], "3");
Or use an array of pointers and strdup():
char *str[3];
str[0] = strdup("1");
...
If you do that, don't forget to free them when you're done, because strdup() allocates memory, e.g.
// free one pointer from the array:
free(str[0]);
// or if you have allocated to every value in the array:
size_t arr_len = sizeof(str) / sizeof(*str);
for (size_t n = 0; n < arr_len; ++n)
free(str[n]);
strdup returns a pointer-to-a-char. If you want to store that pointer in an array, then you need an array of pointers, like this
char *str[3]; // an array of three pointer-to-char
str[0] = strdup("1");
str[1] = strdup("2");
str[2] = strdup("3");
for ( int i = 0; i < 3; i++ )
printf( "%s\n", str[i] );
If you want to copy the entire string content you can use strcpy, however note that it copies null terminated strings. It is needed to have place for the last null symbol. So, the length of string arrays must be at least 2 (char str[3][2]) to copy strings like "1".
Related
I'm trying to set the parameters of the structure below:
typedef struct thread_args_s {
int idx;
int role;
int fifo_desc;
char client_fifo_name[FIFO_NAME_MAX_LENGTH];
char msg[MSG_MAX_LENGTH];
} thread_args_t;
I've a problem assigning thread_args_t->client_fifo_name.
The client_fifo_name is given by a concatenation of the strings CLIENT_FIFO_NAME_SUFFIX + i, using sprintf().
In detail:
int i;
char* name;
for(i=0; i<THREAD_COUNT-1; i++){
thread_args_t* prod_args = malloc(sizeof(thread_args_t));
prod_args->idx = i;
prod_args->role = PROD_ROLE;
prod_args-> fifo_desc = server_fifo;
sprintf(name, "%s%d", CLIENT_FIFO_NAME_SUFFIX, i);
//How to assign the string "name" to prod_args->client_fifo_name?
prod_args->client_fifo_name = name;
[...]}
Compiling, the error is:
Incompatible types when assigning to type char[32] from type char*.
How can I fix it?
The types are incompatible because the left hand of the assignment is to exactly 32 characters, but the right hand of the assignment is a pointer. I'm guessing, but you probably want:
snprintf(prod_args->client_fifo_name,
FIFO_NAME_MAX_LENGTH,
"%s%d",
CLIENT_FIFO_NAME_SUFFIX, i);
The correct way to use name would be (here you have not allocated any memory to which the char* variable points to)
char *name = malloc(MAXLEN+1); Check the return value of malloc.
Or using an array
char name[MAXLEN+1];
After you did that - you will have to use strcpy to copy the content of the name to the designated array. Arrays are non-modifiable lvalue - assigning something to - it is error.
So after you make sure that destination has enough storage to store the string you are going to copy write
strcpy(prod_args->client_fifo_name , name);
To explain the error - here it finds the type mismatch in the line prod_args->client_fifo_name = name; here the left hand of assignment has type char [] and on the right it is char *. These mismatch of type in the assignment causes the error.
Also I just corrected the possible errors - you can omit allocating extra memory before copying to the actual one. You can directly use s(*)printf with the final target variable as buffer.
Incompatible types when assigning to type char[32] from type 'char*'
I've a problem assigning thread_args_t->client_fifo_name.
As prod_args->client_fifo_name in an array, it can not be assigned in C.
To assign a chracter array's elements, code may copy data with sprintf(), snprintf(), memcpy(), strcpy() or the like as answered by #Whilom Chime.
Code could assign each element of the array (a char) one at a time too, but let us avoid that.
snprintf() is a good choice, yet robust good also checks to see if data fits.
// sprintf(name, "%s%d", CLIENT_FIFO_NAME_SUFFIX, i);
// prod_args->client_fifo_name = name;
int count = snprintf(prod_args->client_fifo_name, sizeof prod_args->client_fifo_name,
"%s%d", CLIENT_FIFO_NAME_SUFFIX, i);
// Check for success
if (count < 0 || count >= sizeof prod_args->client_fifo_name) {
fprintf(stderr, "Not enough room or other error. Good-bye\n");
exit(EXIT_FAILURE);
}
I wish to split a "string" by the character ','.
The string holds a GPS NMEA encoded string, but that is of no matter.
My problem is that sometimes the parameter from the function that processes this char array is empty... Like nothing is in the array.
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
I also need to specify that I'm using mikroC for PIC.
Here is my code as of right now:
char* GPS_sateliti;
char CsatInView[] =
"$GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74";
GPS_sateliti = GrupeazaDupaVirgule(CsatInView, 2);
char* GrupeazaDupaVirgule( char deGasit[],int nrVirgule ){
int cVirgule = 1;
char* pch = strtok (deGasit,",");
while (pch != 0)
{
pch = strtok (0, ",");
cVirgule++;
if(nrVirgule == cVirgule){
break;
}
}
return pch;
}
The function that operates on the char array received as a parameter in debug mode, before entering the function the char array is fine, after entering it, it seems to be empty
It may be that I should receive a pointer to an array of chars??
Any sort of advice is welcome.
Thank you
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
You can't. A function parameter of an array type always decays as the corresponding pointer type.
There are two idiomatic solutions to this.
1. a sentinel:
The last value in the array is a special value that marks the end. This is done in C with strings. They always end with a \0 character, that is guaranteed not to occur inside the string. The function can search for that character to know where the data ends.
(Note: with this info I have to add I'm not sure what your problem is. If you pass an "empty string", as literally "", the \0 will be there, so you shouldn't have a problem)
2. explicitly passing the size:
instead of just
void foo(int bar[]);
you define a function
void foo(size_t barSize, int bar[]);
The caller knows the size of the array, so it can just pass it along.
With a pointer :
char* arr;
yourFunction(arr);
If you wish to initialize it before :
char* arr = malloc(51 * sizeof(char)); // Allocate a memory place of 50 because strings are null terminated in C
yourFunction(arr);
An other way to allocate memory to an array :
char* arr = calloc(50, sizeof(char)); // Allocate 50 memory place which size if the size of a char
With a string :
char arr[50];
char* ptr = arr;
yourFunction(ptr);
You have to know that it is impossible in C to know the size of an array when using pointer. The only thing you can do is to parse the size of the string as a parameter :
size_t size = 50;
char arr[size];
char* ptr = arr;
yourFunction(ptr, size);
If you wish to understand in detail how pointer works and how to iterate them, may be this post can help you. I think it is very interesting.
Globally, you iterate through an array via a pointer like this :
for ( int i = 0; i < size; i++)
printf("Current pointed value in the array : %c\n", ptr[i]); // or arr[i]
I guess you understand why giving the size of a pointed array as a parameter is important. Sometimes you can avoid using this parameter like this :
for ( int i = 0; i != '\0'; i++) // Because strings are null-terminated in C.
// Do something
I keep getting the following errors when i try to compile my code below. I searched online for what the errors meant but nothing seemed to fit my code. Please could someone tell me where im going wrong in malllocing a string below. I want to make 5 units in that array, and this is the first one.
Errors:
assignment4.c: In function ‘readFile’:
assignment4.c:42:19: warning: assignment makes integer from pointer without a cast [enabled by default]
assignment4.c:44:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
Code:
void readFile()
{
char * listofdetails;
listofdetails = malloc(sizeof(char)*40);
listofdetails[1] = "cars";
printf("%s \n", listofdetails[1]);
free(listofdetails);
}
Use strcpy (don't forget to #include <string.h>):
strcpy(listofdetails, "cars");
Also, "%s", expects a string, not a char, if you want to print a string
printf("%s \n", listofdetails);
is what you want.
If you want to print the first character in the string:
printf("%c \n", listofdetails[0]);
But if you want a list of details (as the name suggests), you need to reserve space for the list of n string (char **), and for each string (char *):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char *strdup(const char *);
int main(void)
{
char **listofdetails = malloc(sizeof(*listofdetails) * 40);
if (listofdetails == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
listofdetails[0] = strdup("cars");
if (listofdetails[0] == NULL) {
perror("strdup");
exit(EXIT_FAILURE);
}
printf("%s\n", listofdetails[0]);
free(listofdetails[0]);
free(listofdetails);
return 0;
}
Note that strdup is not part of the standard (but is available on many implementations).
Finally, if those strings are known at compile time you don't need to use malloc at all:
const char *listofdetails[] = {
"cars",
"trucks",
"motorcycles",
/* etc */
};
The two lines
char * listofdetails;
listofdetails = malloc(sizeof(char)*40);
can be written as
char * listofdetails = malloc(40);
(sizeof(char) is defined to be 1). Still you should not use magic numbers as 40 directly in the code but use aptly named constant
#define STRING_LENGTH 40
The line
listofdetails[1] = "cars";
is wrong, since the left side is the second character location in the list of details, and you try to assign a string character to it. Use
strcpy(listofdetails, "cars");
and the same problem in the line
printf("%s \n", listofdetails[1]);
Use
printf("%s \n", listofdetails);
instead.
listofdetails[1] is char(or int) type. %s expects a char * type. The fix:
printf("%s \n", listofdetails);
If you want to print out listofdetails[1], then use %c:
printf("%c \n", listofdetails[1]);
listofdetails[1] = "cars"; tries to assign a char array to a char(or int).
Instead, you can do:
listofdetails = malloc(sizeof(char)*40);
strcpy(listofdetails, "cars");
It would appear that you want a list of strings, but you're declaration of listofdetails is only a single string.
Instead, you need to add another pointer, like so:
char **listofdetails = malloc(sizeof(char *) * 40);
Now you can use listofdetails as you intend. Please note, however, that in C, array indexes start at 0, not 1. So you probably want to use listofdetails[0] = "cars"; to set the first element of your array.
You are assigning a string to a single byte location.
listofdetails[1] = "cars"; // Problem
where listofdetails[1] indicates a single character in a character array.
You should not assign string like above. use strcpy-
strcpy(listofdetails,"cars");
Else you can assign like this also
char *listofdetails = "cars";
It does not require memory allocation.
Try the below changes-
void readFile()
{
char * listofdetails;
listofdetails = malloc(sizeof(char)*40);
strcpy(listofdetails,"cars");
printf("%s \n", listofdetails);
free(listofdetails);
}
Use string.h and stdlib.h header file also.
a char is a single character (e.g. 'a')
char* is a pointer. in your case you allocate 40 (single) characters (malloc) and assign the address of the first to listofdetails. use strcpy, as Alter Mann wrote, to copy a string literal or any null-terminated sequence of chars to your listofdetails. to complete Alter Mann's example:
char * listofdetails;
listofdetails = malloc(sizeof(char)*40);
strcpy(listofdetails, "cars"); // make sure that the string on the right does not exceed 40 characters!
printf("%s\n", listofdetails); // will print "cars" on a single line
free(listofdetails);
example for array of strings:
char ** listofdetails;
listofdetails = malloc(sizeof(char*) * ARRAYSIZE);
listofdetails[0] = malloc(sizeof(char) * STRBUFFERSIZE);
strcpy(listofdetails[0], "cars");
printf("%s\n", listofdetails[0]);
free(listofdetails[0]); // delete string
free(listofdetails); // delete string-array
assignment4.c:42:19: warning: assignment makes integer from pointer without a cast [enabled by default]
comes from the line
listofdetails[1] = "cars";
listofdetails is an expression of type char *; listofdetails[1] is an expression of type char, which is an integral type, and it evaluates to the second element of the array that listofdetails points to. "cars" is an expression of type char * (more on that later), and you can't assign pointer values to integers without a cast.
This boils down to what listofdetails is supposed to store. Is it suposed to store a single string? If so, then you would need to write
strcpy( listofdetails, "cars" );
in order to copy the contents of the string literal "cars" to the memory listofdetails points to.
If it's supposed to store a pointer to an existing string or string literal, then you would skip the malloc step altogether and simply write
char *listofdetails = "cars";
The string literal "cars" is stored as a 5-element array of char such that it is allocated when the program starts up and released when the program exits. An array expression will be converted ("decay") to a pointer expression unless it is the operand of the unary & or sizeof operators, or is a string literal being used to initialize another array in a declaration.
In the case above, "cars" isn't the operand of the sizeof or unary & operators, and it isn't being used to initialize an array of char, so it decays to a char *, and its value is the address of the first character in the string. So by the time this is done, listofdetails points to the string literal "cars".
If it's supposed to store a list of pointers to strings, then you would need to do the following:
char **listofdetails = malloc( sizeof *listofdetails * 40 ); // note extra level of indirection
This will allocate enough memory to store 40 pointers to char; since the type of listofdetails is char **, the type of listofdetails[1] will be char *, so the following lines will work as you intend:
listofdetails[1] = "cars";
printf("%s \n", listofdetails[i] );
Making that last change will fix
assignment4.c:44:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
which is complaining about
printf("%s \n", listofdetails[1] );
since as currently written, listofdetails[1] has type char, which is promoted to int since printf is a variadic function, and %s expects the corresponding argument to have type char *.
One more thing; in C, arrays are 0-origin, so you'd use the index 0 to access the first element of the list, and index 39 to access the last one.
I create a big 2d char array and want to assign strings to it.
int i;
char **word;
int start_size = 35000;
word=(char **) malloc(start_size*sizeof(char *));
for(i=0;i<start_size;i++)
word[i]=(char *) malloc(start_size*sizeof(char));
word[2][2] = "word";
how do I assign a string?
Explain me why this code doesn't work...
I am new to low level programming and C but experienced in high level programming
You cannot do string assignment in C.
You need to call a function, sepcifically strcpy() (prototype in <string.h>)
#include <string.h>
strcpy(word[2], "word");
word[2][2] = "word";
In the above statement, the string literal "word" is implicitly converted to a pointer to its first element which has type char * whereas word[2][2] has type char. This attempts to assign a pointer to a character. This explains the warning message you have stated -
assignment makes integer from pointer without a cast
You can use string literals only to initialize character arrays. What you need to do is use the standard function strcpy to copy the string literal. Also, you should not cast the result of malloc. Please read this - Do I cast the result of malloc? I suggest the following changes -
int i;
int start_size = 35000;
// do not cast the result of malloc
char **word = malloc(start_size * sizeof *word);
// check word for NULL in case malloc fails
// to allocate memory
for(i = 0; i < start_size; i++) {
// do not cast the result of malloc. Also, the
// the sizeof(char) is always 1, so you don't need
// to specify it, just the number of characters
word[i] = malloc(start_size);
// check word[i] for NULL in case malloc
// malloc fails to allocate memory
}
// copy the string literal "word" to the
// buffer pointed to by word[2]
strcpy(word[2], "word");
You have to decide if you want a list of strings or a 2D array of strings.
A list of string works like this:
char **word;
word = (char**)malloc(start_size*sizeof(char*));
word[2] = "word";
In this example word[2] would be the third string in the list and word[2][1] would be the second character in the third string.
If you want a 2D array of string you have to do this:
int i;
char ***word;
^^^ 3 stars
int start_size = 35000;
word = (char***)malloc(start_size*sizeof(char**));
^^^ 3 stars ^^^ 2 stars
for(i=0;i<start_size;i++)
word[i] = (char**) malloc(start_size*sizeof(char*));
^^^ 2 stars ^^^ 1 star
word[2][2] = "word"; // no it works!
Note that in C you do not need the casts before the malloc. So this would also work:
word = malloc(start_size*sizeof(char**));
im trying to copy a const char array to some place in the memory and point to it .
lets say im defining this var under the main prog :
char *p = NULL;
and sending it to a function with a string :
myFunc(&p, "Hello");
now i want that at the end of this function the pointer will point to the letter H but if i puts() it, it will print Hello .
here is what i tried to do :
void myFunc(char** ptr , const char strng[] ) {
*ptr=(char *) malloc(sizeof(strng));
char * tmp=*ptr;
int i=0;
while (1) {
*ptr[i]=strng[i];
if (strng[i]=='\0') break;
i++;
}
*ptr=tmp;
}
i know its a rubbish now, but i would like to understand how to do it right, my idea was to allocate the needed memory, copy a char and move forward with the pointer, etc..
also i tried to make the ptr argument byreferenec (like &ptr) but with no success due to a problem with the lvalue and rvalue .
the only thing is changeable for me is the function, and i would like not to use strings, but chars as this is and exercise .
thanks for any help in advance.
Just replace all the char* with std::string. Do that until you have a very specific reason to not use existing utilities, which is something you don't have as a beginner. None of the code above requires malloc() or raw pointers.
Some more notes:
const char strng[] as parameter is the same as const char* strng. The array syntax doesn't make it an array, it remains a pointer. I don't use this syntax in order to avoid this confusion.
Use static_cast or one of the other C++ casts not the C-style like (char*)malloc(..). The reason is that they are safer.
Check the return value of malloc(), it can return null. Also, you must call free() eventually, otherwise your application leaks memory.
Finally, the pointer does point to the 'H', which is just the first element of the string. Output *p instead of p to see this.
You code work as desired except
*ptr[i]=strng[i];
should be
(*ptr)[i]=strng[i];
Without the parens, it acts like `*(ptr[i])=strng[i];
2) Also
malloc(sizeof(strng));
s/b
malloc(strlen(strng)+1);
You may want to look at strdup(strng).
[edit per OP's request]
difference between *(ptr[i]) and (*ptr)[i]
// OP desired function
(*ptr)[i] = 'x';
// Dereference ptr, getting the address of a char *array.
// Assign 'x' to the i'th element of that char * array.
// OP post with the undesired function
*(ptr[i]) = 'x';
// This is like
char *q = ptr[i];
*q = 'x';
// This make sense _if_ ptr were an array of char *.
// Get the i'th char * from ptr and assign to q.
// Assign 'x' to to the location pointer to by q.
This is all the code needed...
nothing more...
void myFunc(char **pp, char * str){
*pp = str;
}
The only issue here is that "Hello" resides in read only section because it is a constant string... so you can't change "Hello" to something else...