how to assign a value to an array element in c language? - c

#include <malloc.h>
void main()
{
char **variable;
int count=0
variable=(char **)malloc(sizeof(char *)*100);
for(i=0;i<100;i++)
variable[i]=(char *)malloc(sizeof(char)*11);
scanf("%s",variable[count]);
}
Now I want to assign a value to the string present in variable[count]
for example: if variable[count] contains a string "abc" then i want to assign 20 to abc
and if i use printf("%d",abc) then it should print 20

Here
variable=(char **)malloc(sizeof(char)*100);
you want to allocate pointers, so specifiy the correct size of a pointer, that is char*, like so:
variable = malloc(100 * sizeof(char*));
or even better like this:
variable = malloc(100 * sizeof(*variable));
Btw: In C there is not need to cast the results of malloc/calloc/realloc, nor is it recommended.
Following the rules/advices above, this line
variable[i]=(char *)malloc(sizeof(char)*11);
should better look like this
variable[i] = malloc(11 * sizeof(*variable[i]));
Finally this call is dangerous:
scanf("%s",variable[count]);
as it tends to overflow variable[count], so make it save by telling scanf() how much so scan in as a maximum, by doing so:
scanf("%10s", variable[count]); /* Leave one (10=11-1) spare for the C-"string"'s 0-terminator. */
And it's
int main(void)

The type of variable is char **, then variable should point to a list of char *, not a list of char.
Therefore, variable=(char **)malloc(sizeof(char)*100); should be variable=(char **)malloc(sizeof(char *)*100);.
BTW, the type-casting before malloc() is unnecessary.
Now I want to assign a value to the string present in variable[count] for example: if variable[count] contains a string "abc" then i want to assign 20 to abc and if i use printf("%d",abc) then it should print 20
You want to treat the value of variable[count] to be a variable. Unfortunately, you cannot do that. C is a static programming language, which means you cannot create variable on run time, as you do in dynamic programming language.
But C is powerful enough to let you simulate this. You could create a look-up table, such as
typedef struct var {
char *name;
int val; /* or whatever type you want */
} var_t;
var_t variable[num_of_vars]; /* or whatever data structure that you can search */

Related

how to I copy structure char variable into another char array [duplicate]

This question already has answers here:
How can I correctly assign a new string value?
(4 answers)
Closed last year.
struct student
{
char name[50];
int rollno;
float marks;
};
int main()
{
char nam[50];
int i = 0, n=5;
struct student s1[n];
for(i=0;i<n;i++)
{
nam[i] = s1[i].name;
}
}
In given code, I am unable to copy s1[i].name in nam[i], I tried all the copy function but it's giving me error every time.
This ...
nam[i] = s1[i].name;
... does not make sense because name[i] is one char, whereas s1[i].name is an array of 50 chars. Moreover, your loop is over the number of elements of s1 (5), which is much less than the number of elements of nam or s1[i].name.
Supposing that you really do want s1 to be an array of struct student as opposed to just one struct, you probably want to use strcpy(). However, you might want or need to use memcpy() (or an element by element copy loop) depending on the nature of the contents of s1 and its elements and any artificial requirements on the exercise.
The strcpy() variation would look like this:
strcpy(nam, s1[i].name);
// do something with nam ...
That depends on the source array to contain a null-terminated string, which is not guaranteed to be the case in the demo program, which never puts any data in s1 or its elements.
Use strcpy() I have tried and it's working
Lots of little things working against you in this code, eg the following...
int i = 0, n=5;
struct student s1[n];
...creates a variable length array of struct student, preventing an initializer from being a viable path. But if for the sake of illustration you can live with a non-VLA version, then try this:
//Use a hard-coded to `5`, to create an array of 5 struct student, initialized as shown:
struct student s1[5] = {{"name1"1, 1.0},("name2",2,2.0},{"name3",3,3.0},{"name4",4,4.0},{"name5",5,5.0}};
Next, your current code: char nam[50]; creates a single uninitialized char array, sufficient for containing only 1 string with up to 49 characters, with a terminating \0. If you can, create it like this. (for the sake of learning to copy strings in a loop.)
char nam[5][50] = {{0}};//created 5 elements of null terminated char array elements,
Then you can do this in your loop:
for(i=0;i<n;i++)
{
strcpy(nam[i], s1[i]name);
}
By now (from comments and answers) you should already know that strings cannot be copied using the = operator like integers or floating numbers. String functions such as strcpy(), or sprintf() can be used to populate strings.

Set to NULL an array of structures on C

I wrote this C code to set to NULLan array of structures on C. Here it goes,
struct Worker
{
char name[50];
unsigned int salary;
};
int main()
{
int n;
struct Worker number[50];
for(n=0;n<50;n++)
{
number[n].name=NULL;
}
}
Compiler is giving this error: main.c:65:26: error: assignment to expression with array type.
In your struct, the field name is an array of 50 chars. Arrays are not pointers and you cannot change them; you can only change their contents.
Therefore, if you want to initialise the name field, you could make the name an empty string by making the first char a null terminator:
*number[n].name = '\0';
Note that you name will always hold 50 chars, but you are using only the chars up to the first terminator.
Because your array isn't a pointer, the following doesn't work, either:
number[0].name = "Tom";
You must fill the contents to the array, probably with strcpy from <string.h>:
strcpy(number[0].name, "Tom");
If you want to test whether a string is empty, test whether the first character is the null terminator:
if (*number[n].name == '\0') ... // string is empty
You can also initialise the array explicitly:
struct Worker number[50] = {
{"Alice", 3200},
{"Bob", 2700},
{"Charlotte", 3000}
};
This will give you 3 workers with names and a salary and 47 workers with empty strings as names and zero salary. You can, of course, fill them in later or reset the first three.
If you initialise the array with:
struct Worker number[50] = {{""}};
you'll get an array of all empty-named, all zero-salary workers that you can fill.
(That said, if your name member were a pointer like char *name;, you could say number[n].name = "Tom"; or number[n].name = NULL;. But that would mean that you'd have to handle all the memory that the pointer points to yourself, which is not easy.
The advantage of your array of 50 chars is that each worker has already 50 chars that you can use for their name. (Well, up to 49 plus a null terminator.) The disadvantage is that you waste memory on most names, because they are shorter and you are not flexible enough if you need a name that is longer. But before you have learned more about pointers and memory management, the array is the way to go. Just make sure that you don't exceed its limits.)
You can't set an array of characters to null like that; there's no point. Literally there's no pointer. Arrays aren't pointers; their memory is already allocated on the stack, so I can't redirect the array how you're trying to do it. You're trying to manually set the array's address.
If however your struct looked like this
struct Worker{
char *name;
unsigned int salary;
};
Then you would be able to set each worker's name to null.
If your interest is to zero out an array of characters, you could do this
int n, j;
struct Worker number[50];
for(n=0;n<50;n++)
for(j=0;j<50;j++)
number[n].name[j]=0;
But I have no idea why you'd want to do that. I'm assuming you may use strcpy to assign values to each worker's name, which takes care of the null terminating character for you.
Your name is array of 50 chars, if you want to clear it instead of:
num[n].name=NULL;
do:
memset(num[n].name, 0, 50);
You can set to NULL pointer not the array.
You can see if array is empty by examining each of arrays elem, like:
int i;
int non_empty = 0
for( i=0; i < sizeof(array)/sizeof(array[0]); ++i)
{
if(array[i] != 0)
{
non_empty = 1;
break;
}
}

Changing values in elements of an array of structs

I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}

Can I create an Array of Char pointers in C?

I am new to C, and things are different in C than in any other language I've learned. In my homework I want to create an array of chars which point to an array of chars, but rather than make a multidimensional char array, I figure I'd have more control and create char arrays and put each individual one into the indexes of the original char array:
char keywords[10];
keywords[0] = "float";
The above example is to clarify and a simple case. But my question is due to the research I've been doing, and I am confused about something. Normally this would work in other languages, but in C it would be:
char *keyword[10];
keywords[0] = "float";
But when I want to send it through a function, why is this necessary:
void function(char **keyword); //function prototype
Wouldn't just passing the array pointer be enough?
It looks like you're confused by the double stars in
void function(char ** keyword);
The double stars just means that this function expects you to pass a pointer to a pointer to a char. This syntax doesn't include any information about the fact that you are using an array, or that the char is actually the first char of many in a string. It's up to you as the programmer to know what kind of data structure this char ** actually points to.
For example, let's suppose the beginning of your array is stored at address 0x1000. The keyword argument to the function should have a value of 0x1000. If you dereference keyword, you get the first entry in the array, which is a char * that points to the first char in the string "float". If you dereference the char *, you get the char "f".
The (contrived) code for that would look like:
void function(char **keyword)
{
char * first_string = *keyword; // *keyword is equivalent to keyword[0]
char first_char = *first_string; // *first_string is equivalent to first_string[0]
}
There were two pointers in the example above. By adding an offset to the first pointer before dereferencing it, you can access different strings in the array. By adding an offset to the second pointer before dereferencing it, you can access different chars in the string.
char *keyword[10];
keyword is an array 10 of char *. In a value context, it converted to a pointer to a char *.
This conversion is a part of what Chris Torek calls "The Rule":
"As noted elsewhere, C has a very important rule about arrays and pointers. This rule -- The Rule -- says that, in a value context, an object of type ‘array of T’ becomes a value of type ‘pointer to T’, pointing to the first element of that array"
See here for more information: http://web.torek.net/torek/c/pa.html
The C-FAQ also has an entry on this array to pointer conversion:
Question 6.3: So what is meant by the "equivalence of pointers and arrays'' in C?
http://c-faq.com/aryptr/aryptrequiv.html
In C, you can't really pass array to a function. Instead, you pass a pointer to the beginning of the array. Since you have array of char*, the function will get a pointer to char*, which is char**.
If you want, you can write (in the prototype) char *keyword[] instead of char **keyword. The compiler will automatically convert it.
Also, in C you can dereference pointers like arrays, so you loose almost nothing with that "converting to pointer".
If you want to
void function(char **keyword);
Andy, think about that an array is just a pointer(to the beginning of the array), that's why you write:
void function(char **keyword);
Because you have create an array to char pointers.
If it's easier to understand try:
void function(char *keyword[]);
But it's more C standard to use the first one, though if you use a C++ compiler won't really matter.
Here is the answer.
#include<stdio.h>
int main(void)
{
char *CharPtr[3];
char a[4]="abc";
char b[4]="def";
char c[4]="ghi";
CharPtr[0]=a;
CharPtr[1]=b;
CharPtr[2]=c;
printf("\n content of CharPtr[0] =%s",CharPtr[0]);
printf("\n content of CharPtr[1] =%s",CharPtr[1]);
printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);
printf(" \n content of char a[4]=%s",a);
printf(" \n content of char b[4]=%s",b);
printf(" \n content of char c[4]=%s\n",c);
}
char *keywords[10] is an array of character pointers. So keywords[0], keywords[1].. and so on will have the addresses to different character arrays.
In printf you can use %s and keywords[0] to print the entire character array whose address(i.e. address of the first byte in the array) is stored at keywords[0].
While passing to a function, if you give *keywords, you are referring to the value at(address stored at keywords[0]) which is again an address. So, to get the value instead of address, you can add another *... Hope that clarifies a bit..
I am assuming that you are assigning your first string:
"float"
to the first index position of keyword[0]
char keyword[0] = "float";
which is the first index position of the array:
char keyword[10];
If the previous is the case, then in a sense, you are essentially creating a data structure that holds a data structure. The array of any type is the 'smallest' data structure of that type in C. Considering that in your example you are creating a character array, then you are actually utilizing the smallest data type (char=1bit) at each index position of the smallest built in data structure (the array).
With that said, if in your example, you are attempting to create an array of arrays; your character array
/* Hold ten characters total */
char keyword[10];
was designed to hold 10 characters. One at each index position (which you probably already know). So after declaring the array titled keyword, you then try to initialize the first index position of the array with another (the second) character array:
/* I believe this is what you had stated */
char keywords[0] = "float";
With the second character array having an index of 5 positions in size.
In order to achieve your desired goal, you would essentially be creating an array that basically emulates the effect of a data structure that 'holds' other data structures.
NOTE: If you had/have plans on trying to create a data structure that holds a data structure that holds a data structure. A.K.A. a triple nested data structure and in this case I think that would be a Matrix, WHICH I WOULDN'T RECOMMEND!
None the less, the matrix structure would be in the form of the first index position of keyword, being assigned the whole array of keywords, which would include all of the data stored in each index position of the keywords array. Then there would something probably like: keywords1, keywords2, ... keywords9,
which would essentially emulate the form of:
char *keyword[10] = {
char *keywords0[10] = {"float", etc, etc, etc.};
char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.};
and so
};
So basically from right to left, the keyword array, is an array of pointers that points to array of pointers that points to character arrays.
If that is what you are representing you would be better defining a custom data type of struct/record, and with in that custom structure you would want to define a subordinate or child level of structures. You could also pre-declare them then initialize them.
e.g.
typedef *nestedDataStructures {
struct keyWords[];
struct keyWords1[];
struct keyWords2[];
... and so on.
}; nestedDataStructures
Instead of adding ten structs to one custom structure I would break down into 3 or 4 (how ever many structures and use) and create a module in order to yield symmetrical layers of abstraction as you manipulate your data set.
None the less, you can not create the character array and potentially assign the other character array in the fashion that you did (or who knows maybe you can), but the way you would want to emulate the array that holds arrays, is to create a character pointer array up front, of X number index positions and then initialize then use the character arrays in the form of a strings declared with in the initialization of the original declaration.
So basically you could declare your whole array upfront, then with in your program design, either dereference each index position, use assignment, or print/write the index position.
Like for instance you could always do something like this:
/* Example of the program and declaration with out a function */
#include <stdio.h>
int main(){
/*
* A character pointer array that contains multiple
* character arrays.
*/
char *grewMe[2] = {"I want to ", "grow to be bigger"};
int w = 0;
for(; w < 2;) {
printf("%s", grewMe[w]);
++w;
}
printf(" :-)\n");
w = 0;
return 0;
}
// Output:
// I want to grow to be bigger :-)
Or something like this:
/* Example of program: function passed arguments
* of a pointer to the array of pointers
*/
#include <stdio.h>
void mygrowth(char *growMe[]);
int main(){
char *growMe[2] = {"I want to ", "grow to be bigger"};
mygrowth(growMe);
printf(" :-)\n");
return 0;
}
void mygrowth(char *growMe[])
{
int w = 0;
for (; w < 2;) {
printf("%s", growMe[w]);
++w;
}
}
The assignment of each index position as it's passed as an argument:
/*
* This program compiles, runs and outputs properly
* Example of a program with a function of
* arguments pnt2pnter
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
thoughtAsAFunction(iThink);
printf(":-)\n");
return 0;
}
void thoughtAsAFunction(char **iThink) {
int andy = 0;
for (; andy < 10;) {
char * pntThroughPnt = iThink[andy];
printf("%s", pntThroughPnt);
++andy;
}
andy = 0;
}
Or pass by reference, with an increment of the loop count variable:
/*
* This program compiles, runs, and outputs all of the character
* arrays.
*
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine, then I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
int andy = 0;
for (; andy < 10;) {
// pass by reference and increment.
thoughtAsAFunction(&iThink[andy]);
++andy;
}
printf(":-)\n");
andy = 0;
return 0;
}
void thoughtAsAFunction(char **iThink) {
char * pntThroughPnt = *iThink;
printf("%s", pntThroughPnt);
}
Keep in mind that this is the case if you declare the array of pointers (char *array[10];), and each pointer points to an array of characters.

Why can't I initialize an array of cstrings like this?

char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
Why does this return the error expected expression before ‘{’ token? The reason I want to initialize my array like this is so that I can change its contents like this later:
sXSongBuffer = {"New Song", "More Music From Me"};
You can't assign to arrays in C. C allows initializing arrays with values that are compile-time constants. If you want to change the values later, or set values that are not compile-time constants, you must assign to a particular index of the array manually.
So, your assignment to sXSongBuffer is disallowed in C. Moreover, since sXSongBuffer[0] to sXSongBuffer[19] are arrays too, you can't even say: sXSongBuffer[0] = "New Song";
Depending upon what you want, this may work for you:
/* declare sXSongBuffer as an array of pointers */
char *sXSongBuffer[30] = {
"Thriller",
"Don't Stop Till You Get Enough",
"Billy Jean",
NULL /* set the rest of the elements to NULL */
};
size_t i;
/* and then later in your code */
sXSongBuffer[0] = "New Song";
sXSongBuffer[1] = "More Music From Me";
for (i=2; i < sizeof sXSongBuffer; ++i)
sXSongBuffer[i] = NULL;
But the above only works if you know all your strings at compile time. If not, you will have to decide if you want "big-enough" arrays, or if you need dynamic memory for the strings and/or the number of strings. In both cases, you will want to use an equivalent of strcpy() to copy your strings.
Edit: To respond to the comment:
You're declaring an array of 30 char pointers with the first three elements pointing to buffers the size of the strings, ie the buff pointed to by sXSongBuffer[0] won't hold any string larger than "Thriller" and if he does sXSongBuffer[0] = malloc(32); He'll get a minor memory leek. Also, he'll have to malloc memory for each of the rest of the slots in the array. He should either use 2d char arrays like in the OP + a designated init, or malloc each buffer at run time and copy in the values. He'll also need to remember to free any memory he mallocs.
sXSongBuffer in char *sXSongBuffer[30]; is an array of size 30, with each element being a char *, a pointer to char. When I do:
char *sXSongBuffer[30];
each of those 30 pointers is uninitialized. When I do:
char *sXSongBuffer[30] = { "Thriller", ... };
I set the pointers to different read-only locations. There is nothing preventing me to then "re-point" the pointers somewhere else. It is as if I had:
char *data = "Hello";
printf("%s\n", data);
data = "Hello, world";
printf("%s\n", data);
In the above snippet, I assign data to "Hello" first, and then change it to point to a longer string later. The code I had above in my answer did nothing more than reassign sXSongBuffer[i] to something else later, and since sXSongBuffer[i] is a pointer, the assignment is OK. In particular, sXSongBuffer[0] is a char *, and can point to any valid location that has a char in it.
As I said later in my answer, if the strings aren't known at compile-time, this scheme doesn't work, and one has to either use arrays with "big enough" sizes, or dynamically allocate memory that's big enough.
C does not have general-purpose array literals. The {} list syntax only works when initializing, i.e. when assigning the value in the same statement that declares the variable.
You cannot just write
char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
You must either initialize array at once (but it will containt only 3 items):
char * sXSongBuffer[]= {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
Or either use stnrcpy on every item:
char sXSongBuffer[20][30];
strncpy(sXSongBuffer[0],"Thriller",29);
strncpy(sXSongBuffer[1],"Don't Stop Till You Get Enough",29);
strncpy(sXSongBuffer[2],"Billy Jean",29);
Take a look at Designated Initializers.
#include <stdio.h>
int main (void) {
char a[6][6] = { [2] = "foo", [4] = "bar" };
for (int i=0; i<6; ++i)
printf("%d == %s\n", i, a[i]);
return 0;
}
This is a c99 feature. Compile with:
gcc -W -std=c99 2dInit.c -o 2dInit
This outputs:
0 ==
1 ==
2 == foo
3 ==
4 == bar
5 ==
In your case you want to do:
char sXSongBuffer[20][30] = {
[0] = "Thriller",
[1] = "Don't Stop Till You Get Enough",
[2] = "Billy Jean"
};

Categories

Resources