typedef struct Symbol{
char varName[16];
} Symbol;
...............
Symbol *newSymbol = malloc(sizeof(Symbol));
const char space[2] = " ";
char *String = "Name Test";
//break off the first word from String and put it into name
char *name;
name = strtok(String,space);
//convert the char * to char[16]
char nameArray[16];
strcpy(nameArray,name);
//set newSymbol->varName to the newly created char[16]
newSymbol->varName = nameArray
I have a char * called String. In my actual program, it is read from a file using fgets, I am just calling it "Name Test" for the purposes of this example. I want to take the first word of the string and assign it as the varName in a Symbol. So what should happen is newSymbol->varName is set to "Name". Because strtok returns a char * but I need a char[16] for the struct, I must convert the char * to a char[16].
However, I get this error:
"Error: incompatible types when assigning to type 'char[16]' from type 'char*'
newSymbol -> varName = nameArray;
So, it seems like strcpy it not actually converting the char * to a char[16]. Even after declaring a char[16] and telling strcpy to put the contents of the char * into it, I still have a char * instead of a char[16]. I need to make it work without changing the struct, so that is not an option here.
How can I convert a char * into a char[16]?
You cannot assign the contents of an array using the regular assignment operator in C.
You can use strcpy for strings and memcpy/memset for other data types. (You could use memcpy/memset for strings too but strcpy is simpler)
Instead of
newSymbol -> varName = nameArray;
use
strcpy(newSymbol -> varName, nameArray);
So, it seems like strcpy it not actually converting the char* to a char[16].
No, the problem is that C does not provide for assigning to (whole) arrays. newSymbol->varName is an array of 16 char. You can assign to elements of that array, and you can copy into it with strcpy() or a similar function, but you cannot assign to the whole array.
In your particular code, I'd dispense with variable nameArray, changing this ...
strcpy(nameArray,name);
... to this:
strcpy(newSymbol->varName, name);
(Or perhaps to a similar usage of strncpy(), to protect from overrunning the array bounds.)
Related
The program is as follows
typedef struct Signal {
long int vr[4];
char name[4];
char Type;
char casuality[2];
};
and I wanted to use this structure in such way where for eg: for variable vr I am able to do vr[0]=1073741824 but for casuality if I assign casuality[0]="output" it is showing error as given above
void xmlRead()
{
struct FMU *fmu;
struct Signal *var;
struct Signal iname;
(*var).vr[0]=1073741824;
(*var).vr[1]=1073741825;
(*var).vr[2]=1073741826;
(*var).vr[3]=1073741827;
(iname).name[0]="Ball1_pos"; //Here it is showing the error//
}
In your case, "output" is a string literal, having type char [7] and casuality[0] is of type char.
Obviously, they are not compatible (one is an array, the other a simple char) and hence the error.
There are two ways to achieve what you want,
Change char casuality[2]; to char *casuality[2]; then the assignment will work fine (however, you can't modify a string literal).
Allocate an array long enough and use strcpy() to copy the content of the string literal into the array.
You are trying to assign a string literal (made of several chars), to the first location of an array of four chars (Signal.name[0]).
// a single char = a string literal, i.e., from const char* to char
(iname).name[0] = "Ball1_pos";
This is obviously incompatible in types.
Note that even if the string literal was short enough to be fit into the memory spanned by the variable name, you would need a function such as strcpy or memcpy to assign the value to that memory.
In particular, something like the following would work:
strcpy(iname.name, "abc")
(note that string literals are null terminated by the compiler and strcpy includes the \0)
To make things (hopefully) more clear for you, the following would be equivalent:
iname.name[0] = 'a'
iname.name[1] = 'b'
iname.name[2] = 'c'
iname.name[3] = '\0'
In a program I am writing I made a Tokenize struct that says:
TokenizerT *Tokenize(TokenizerT *str) {
TokenizerT *tok;
*tok->array = malloc(sizeof(TokenizerT));
char * arr = malloc(sizeof(50));
const char *s = str->input_strng;
int i = 0;
char *ds = malloc(strlen(s) + 1);
strcpy(ds, s);
*tok->array[i] = strtok(ds, " ");
while(*tok->array[i]) {
*tok->array[++i] = strtok(NULL, " ");
}
free(ds);
return tok;
}
where TokenizeT is defined as:
struct TokenizerT_ {
char * input_strng;
int count;
char **array[];
};
So what I am trying to do is create smaller tokens out of a large token that I already created. I had issues returning an array so I made array part of the TokenizerT struct so I can access it by doing tok->array. I am getting no errors when I build the program, but when I try to print the tokens I get issues.
TokenizerT *ans;
TokenizerT *a = Tokenize(tkstr);
char ** ab = a->array;
ans = TKCreate(ab[0]);
printf("%s", ans->input_strng);
TKCreate works because I use it to print argv but when i try to print ab it does not work. I figured it would be like argv so work as well. If someone can help me it would be greatl appreciated. Thank you.
Creating the Tokenizer
I'm going to go out on a limb, and guess that the intent of:
TokenizerT *tok;
*tok->array = malloc(sizeof(TokenizerT));
char * arr = malloc(sizeof(50));
was to dynamically allocate a single TokenizerT with the capacity to contain 49 strings and a NULL endmarker. arr is not used anywhere in the code, and tok is never given a value; it seems to make more sense if the values are each shifted one statement up, and corrected:
// Note: I use 'sizeof *tok' instead of naming the type because that's
// my style; it allows me to easily change the type of the variable
// being assigned to. I leave out the parentheses because
// that makes sure that I don't provide a type.
// Not everyone likes this convention, but it has worked pretty
// well for me over the years. If you prefer, you could just as
// well use sizeof(TokenizerT).
TokenizerT *tok = malloc(sizeof *tok);
// (See the third section of the answer for why this is not *tok->array)
tok->array = malloc(50 * sizeof *tok->array);
(tok->array is not a great name. I would have used tok->argv since you are apparently trying to produce an argument vector, and that's the conventional name for one. In that case, tok->count would probably be tok->argc, but I don't know what your intention for that member is since you never use it.)
Filling in the argument vector
strtok will overwrite (some) bytes in the character string it is given, so it is entirely correct to create a copy (here ds), and your code to do so is correct. But note that all of the pointers returned by strtok are pointers to character in the copy. So when you call free(ds), you free the storage occupied by all of those tokens, which means that your new freshly-created TokenizerT, which you are just about to return to an unsuspecting caller, is full of dangling pointers. So that will never do; you need to avoid freeing those strings until the argument vector is no longer needed.
But that leads to another problem: how will the string be freed? You don't save the value of ds, and it is possible that the first token returned by strtok does not start at the beginning of ds. (That will happen if the first character in the string is a space character.) And if you don't have a pointer to the very beginning of the allocated storage, you cannot free the storage.
The TokenizerT struct
char is a character (usually a byte). char* is a pointer to a character, which is usually (but not necessarily) a pointer to the beginning of a NUL-terminated string. char** is a pointer to a character pointer, which is usually (but not necessarily) the first character pointer in an array of character pointers.
So what is char** array[]? (Note the trailing []). "Obviously", it's an array of unspecified length of char**. Because the length of the array is not specified, it is an "incomplete type". Using an incomplete array type as the last element in a struct is allowed by modern C, but it requires you to know what you're doing. If you use sizeof(TokenizerT), you'll end up with the size of the struct without the incomplete type; that is, as though the size of the array had been 0 (although that's technically illegal).
At any rate, that wasn't what you wanted. What you wanted was a simple char**, which is the type of an argument vector. (It's not the same as char*[] but both of those pointers can be indexed by an integer i to return the ith string in the vector, so it's probably good enough.)
That's not all that's wrong with this code, but it's a good start at fixing it. Good luck.
I am confused about why I am getting an error while initializing a structure variable. I have found a few related threads on Stack Overflow, but they did not solve my problem. Can anyone explain what is causing the problem?
//I have used Dev-C++ compiler
//Getting an error 'b1' undeclared
struct book
{
char name ;
float price ;
int pages ;
};
struct book b1;
int main()
{
/* First i have tried following way to initialize the structure variable,
but compiler throws the error
b1 = {"John", 12.00, 18};
*/
//I have tried to initialize individually ....but still getting error...?
b1.name = "John";
b1.price = 12.3;
b1.pages = 23;
printf ( "\n%s %f %d", b1.name, b1.price, b1.pages );
system("pause");
return 0;
}
Problems
only one byte memory available for name field. use like char name[100]
use strcpy() instead of b1.name = "John";
You clearly want a string variable in your struct, but you declared it as char name; (a single character).
Instead, use a char pointer (const char *name), or a char array (char name[100]). In the latter case, you will have to use strcpy(b1.name, "John").
The problem is that you have declared name as a char. That means name will hold only a single char, not an entire string.
You can statically allocate name as an array of char:
char name [25] // or whatever length you think is appropriate
// remember to leave room for the NUL character
Then you will need to use strcpy() to copy the actual name into the structure.
Alternatively, you can declare name as a pointer to char:
char* name;
In this case, you can set the pointer to a string literal:
name = "John";
But in most real life situations, this is not an option, as you will be reading the name in from a file or standard input. So you will need to read it into a buffer, set the pointer to dynamically allocated memory on the heap (the string length of the buffer + 1 for the NUL), and then use strcpy().
You have to do some tweaks to your code in order to make it work.
char name; // only one byte is allocated.
Define char array to store strings in C.
char name[20]; //stores 20 characters
char *name; //Pointer variable. string size can vary at runtime.
Once you have created a object for your structure than you can feed data only using that object.
(i.e) object.element=something;
b1 = {"John", 12.00, 18}; // Not possible
The above initialization is possible only while defining objects.
struct book b1={"John", 12.00, 18}; //Possible
If char *name is defined inside struct, you can do the following.
struct book b1;
b1.name="John"; // Possible
b1.price=12.00; // Possible
b1.pages=18; // Possible
If you use char array char name[20] then you can do the following.
struct book b1;
strcpy(b1.name,"John"); // Possible
b1.price=12.00; // Possible
b1.pages=18; // Possible
I'm new to C and I am working with a struct array. I'm having trouble assigning values to it. here is my struct..
struct student{
char firstname[30];
char surname[30];
int streetNo;
char streetName[30];
char suburb[30];
char state[4];
int postCode;
char DOB[10];
int studentNo;
char gender;
char courseNo[4];
char active;
int WAM;
};
struct student person[1000];
here is me assigning a value to the struct
person[100].firstname = "dan";
and this is my error
assignment type mismatch: array[30] of char "=" pointer to char
You can only initialize array like that at the time of declaration only, else you need to use
strcpy(person[100].firstname,"dan");
you can't even do like that with a simple char array
char a[30];
a="dan";
the complier will tell :
incompatible types when assigning to type ‘char[30]’ from type ‘char *’
because "dan" is a string literal that is being held by a pointer which can't be assigned like this to an array.
Although you can initialize an array of characters from a string literal like this
char str[] = "dan";
you cannot assign a string literal to an array of characters the way you are trying to do.
You need to copy your string into the character array using one of the string copy functions:
strcpy(person[100].firstname, "dan");
If yo would like to copy "dan" into the first four elements and pad the remaining elements of firstname with zeros, use strncpy:
strncpy(person[100].firstname, "dan", 30);
It is worth pointing out that you could make firstname a pointer, and either allocate memory for your strings dynamically, or assign it directly:
struct student{
char *firstname;
char *surname;
/* and so on... */
};
student[100].firstname = "dan";
student[100].surname = "brown";
In C, a string like this is implemented using a character array. A character array is exactly what you have defined, but it is not possible to assign a string directly like this in C. You will have to use string functions for that. The function to use is strcpy(). You have to assign like:-
strcpy(person[100].firstname, "dan");
Arrays are not pointers, and this is one example of it.
Arrays cannot be assigned to, only array elements can be assigned to.
You could do
person[100].firstname[0] = 'd';
person[100].firstname[1] = 'a';
person[100].firstname[2] = 'n';
person[100].firstname[3] = '\0'; /* Pretty tedious... */
or, if you know that you don't copy more than 30 bytes,
strcpy (person[100].firstname, "dan");
An array name itself gives array base address.. And an array base address cannot be a left side value.
person[100].firstname =
gives you error since you are assigning some other value to array base address which is not allowed.
You can initialize
char stringArray[] = "some string";
but you can't assign value to already declared array
char stringArray[100];
stringArray = "some string"; <== error
You alternative is to use strcpy
strcpy(stringArray, "sometext");
The specific problem is that you are attempting to assign a string to an array of bytes.
What you need to do in that particular case is to copy the contents of the string you want into the array, like so:
strncpy(person[100].firstname, "dan", 30);
A more general problem is what you are doing is terrible. For student records like this, the only sensible thing to do is to use a proper database; in your case using SQLite is probably appropriate. Using a database for a simple learning exercise like so might seem like overkill, but it is experience that'll help you out a lot later.
You can strcpy() for assigning value to char array.
strcpy(person[100].firstname,"Dan");
You can't assign like this to an array. Even without a struct. That is
char name[10];
name = "ert";
is an error.
(You can do it only in initialization char name[10] = "ert";)
The correct way to do it is
strcpy(person[100].firstname, "dan");
Safer to use a variation of strcpy that requires a max size of string.
Why does the following code produce a compile-time error? I cannot seem to see why the types are mismatched.
typedef char f_string[MAX_CHARS+1] ; /* string for each field */
/*
* A parsed CSV line, with the number of fields and upto MAX_FIELDS themselves.
*/
typedef struct {
int nfields ; /* 0 => end of file */
f_string field[MAX_FIELDS] ; /* array of strings for fields */
} csv_line;
....
csv_line sut;
sut.field[0] = "Name, "; //Compile-time error.
Error being:
error: incompatible types in assignment
You are trying to assign a const char * to a char[], which is not quite the same thing. This would work if your f_string were defined as
typedef const char * f_string;
What you are looking for here is
strcpy ( sut.field[0], "Name, " );
Or use strncpy so that you can specify the size of the destination buffer ..
strncpy ( sut.field[0], "Name, ", MAX_CHARS )
That will keep you from overrunning your buffer.
You'll need to use something like:
strcpy( sut.field[0],"Name, ");
You can't assign strings like you tried other except as an initializater at declaration time.
the type of sut.field[0] is array-of-char of size MAX_CHARS+1 - you cannot assign a string pointer to an array of characters.
You'd either need to change the type of csv_line::field to a const char*, or just do a string copy of the literal "Name, " to the target array.
Note that both strcpy() and strncpy() alone are unsafe: the first might overflow your buffer, and the second might leave it without a NUL terminator. You must be aware of BOTH of these circumstances even if you "know" that your string in question won't ever overflow.
Use a helper function to do this safely:
char * strncopy(char *dst, const char *src, int dstsize)
{
strncpy(dst, src, dstsize-1);
dst[dstsize-1] = '\0';
return dst;
}
Then:
strncopy(sut.field[0], "Name, ", sizeof sut.field[0]);
sut.field[0] is a char[MAX_CHARS+1]
"Name, " is a const char*
Try this:
strcpy(sut.field[0], "Name, ");
The type of sut.field[0] is indeed char [MAX_CHARS+1]. However, most of the other answers have the type of "Name, " wrong - it is actually of type char [7] (use sizeof "Name, " for an easy demonstration of this).
Nonetheless, you still cannot directly assign a char [7] to a char [MAX_CHARS+1]. You cannot even directly assign a char [7] to another char [7] (initialisation is treated differently from assignment in this way).
The answer is probably just to use a coyping function - for example, if you are certain that MAX_CHARS >= 6, then you can just use strcpy(). If you cannot be sure about the length being correct, then you can use strncat() as as truncating string copy:
sut.field[0][0] = '\0';
strncat(sut.field[0], "Name, ", MAX_CHARS);
(Note that despite the name, strncpy() is not suitable for this, and in fact is very rarely the desired function at all).
It is worth pointing out, however, that you can indirectly assign arrays (of the same type) if they are wrapped up inside a struct. This means that the following will work (if you have a C99 compiler):
typedef struct { char s[MAX_CHARS+1] } f_string; /* string for each field */
csv_line sut;
sut.field[0] = (f_string){"Name, "};