In my project, I am asked to store my 2D array of words in a dynamic data structure, then use them in other functions for other purposes, but I am confused how should I do this. I do understand, how to name them separately like:
#include <stdio.h>
#include <stdlib.h>
typedef struct Names {
char *name[5];
} Names;
void func(Names y) {
printf("%s\n%s", y.name[0], y.name[1]);
}
int main()
{
Names y;
y.name[0] = "John";
y.name[1] = "Luke";
func(y);
return 0;
}
But what if I wanted to do this as a 2d array. So normally I would do char names[][10] = {"John", "Luke", etc..}; but how do I store that in a struct? I mean if I did
#include <stdio.h>
#include <stdlib.h>
typedef struct Names {
char *name[5][10];
} Names;
void func(Names y) {
printf("%s\n%s", y.name[0], y.name[1]);
}
int main()
{
Names y;
y.name[][10] = {"John", "Luke"};
func(y);
return 0;
}
That would just give errors and make no sense.
This is the official way to do it (see Nested initialization in: Struct and union initialization):
#include <stdio.h>
typedef struct Names {
const char *name[2][2];
} Names;
void func(Names* y) {
printf("%s, %s\n", y->name[0][0], y->name[0][1]);
printf("%s, %s\n", y->name[1][0], y->name[1][1]);
}
int main()
{
Names y = { .name={{"John", "Luke"}, {"Jack", "Jim"}}};
func(&y);
return 0;
}
Also the following works for backwords-compatibility reasons:
#include <stdio.h>
typedef struct Names {
const char *name[2][2];
} Names;
void func(Names* y) {
printf("%s, %s\n", y->name[0][0], y->name[0][1]);
printf("%s, %s\n", y->name[1][0], y->name[1][1]);
}
int main()
{
Names y = {"John", "Luke", "Jack", "Jim"};
func(&y);
return 0;
}
The above is managing string constants stored in const char pointers, for variable strings of up to 9 chars lentgh with a trailing zero-terminator, something like the following will be possible (I made compile-time constants for 5 and 9):
#include <stdio.h>
enum {
NAME_COUNT = 5,
NAME_LENGTH = 9
};
typedef struct Names {
char name[NAME_COUNT][NAME_LENGTH+1];
} Names;
void func(Names* y) {
for (int i=0; i<NAME_COUNT; ++i) {
printf("%s\n", y->name[i]);
}
}
int main()
{
Names y = { .name={"John", "Olivia", "Luke", "Mary", "Jane" }};
func(&y);
return 0;
}
I think what you may be missing is the fact that char *name[5]; is not really a 2d array of words, it's an array of 5 pointers to char, you then make the two first pointers of that array point to two string literals. In the second expression you have a 5 by 10 2d array of pointers to char, each one of these pointer can also point to its own string literal, so naturally the expression:
y.name[][10] = {"John", "Luke"};
Is not correct for several reasons, the compiler needs to know both dimensions of the array to know to which pointer you want to assign the string literal, knowing this you'll note that the assigned expression makes little sense.
Example:
y.name[1][1] = "John";
Here you would assign the string literal "John" to the pointer located in the index [1][1] of the array of pointers.
Now, if you want an array of 5 words each one containing 10 characters, including the null byte you would simply use:
char name [5][10]
Note that in this configuration you can't simply assign the strings, you'll need to copy them using somenthing like strcpy.
strcpy(y.name[0], "John");
Related
hello
I have a two-dimensional array of the string type, but I need to store a number and a string, how could I do this in c language?
#include <stdio.h>
#include <string.h>
#define A 10
#define B 10
string sales[A][B];
int main(void)
{
string product = "A";
int age = 20;
sales[0][1] = {'product', age};
printf("Sales: %s\n", sales[0][1]);
}
Thank You
Use a struct to store a number and a string.
#include <stdio.h>
#include <string.h>
#define A 10
#define B 10
typedef char *string;
struct {
string product;
int age
} sales[A][B];
int main(void)
{
string product = "A";
int age = 20;
sales[0][1].product = product;
sales[0][1].age = age;
printf("Sales: %s\n", sales[0][1].product);
}
string is not a type in C, maybe you are refering to CS50, and in that case it's just a typedef of char*.
In C you can't have an array of different types, the next best thing I can think of is for you to use a structure where you can store both values associated with each other:
typedef struct { // structure to hold data
char product[128]; // char array instead of pointer
int age;
}Sales;
Sales sales[A][B]; // structure array declaration
int main(void)
{
char product[] = "A";
int age = 20;
sales[0][1].age = age;
strcpy(sales[0][1].product, product); // here copying the data instead of pointer
printf("Sales: %s - %d\n", sales[0][1].product, sales[0][1].age);
}
You could use pointers instead of char arrays like Barmar did, and that's a good solution for this particular example, but be aware that pointers can become dangling if the lifetime of the data they point to expires.
Why the content is not printed well (e.g. Segmentation Fault/NULL)? I'm passing the entire nested struct (i.e. the array list lp) to the main list. Any suggestion? I spent two days to understand what I wrong without success. I would to have an explanation about it.
#include <stdio.h>
#include <string.h>
struct list
{
char *a;
char *b;
} lp[10];
typedef struct
{
int k;
struct list thelist[2];
} palist;
int main()
{
lp[0].a = "One";
lp[0].b = "Two";
lp[1].a = "Three";
lp[1].b = "Four";
palist final_list = {10, *lp};
printf("%s, %s", final_list.thelist[1].a, final_list.thelist[1].b);
return 0;
}
What you have to understand is that on access, an array is converted to a pointer to the first element (subject to 4-exceptions not relevant here) C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
When you attempt to initialize thelist with *lp you are attempting to initialize an array of struct list from the first element in lp. Assuming you change the intialization from {10, *lp} to (10, lp) that still will not work because now lp is a pointer to the first element which you attempt to use to initialize an array.
In order to accommodate the array/pointer conversion, you need to declare thelist as a pointer not an array, e.g.
typedef struct
{
int k;
struct list *thelist;
} palist;
(You can initialize a pointer with a pointer and all will be well)
Now using the initializer {10, lp} will provide a pointer for the initialization of thelist and your assignment will work (but you must keep track of the number of elements that are valid -- final_list[2].... would invoke Undefined Behavior as the elements 2 and beyond are not initialized)
Your total code would be:
#include <stdio.h>
struct list
{
char *a;
char *b;
} lp[10];
typedef struct
{
int k;
struct list *thelist;
} palist;
int main(void) {
lp[0].a = "One";
lp[0].b = "Two";
lp[1].a = "Three";
lp[1].b = "Four";
palist final_list = {10, lp};
printf("%s, %s\n", final_list.thelist[1].a, final_list.thelist[1].b);
return 0;
}
There are many other ways to initialize or assign this list in the form with the array
typedef struct
{
int k;
struct list thelist[2];
} palist;
for example
palist final_list = {10, {lp[0], lp[1]}};
final_list = (palist){10, {lp[0], lp[1]}};
final_list = (palist){10,};
memcpy(final_list.thelist, lp, sizeof(final_list.thelist));
https://godbolt.org/z/fUjLtE
I have created an array of structure as a global variable. I initialised the array in a function and I could print out the elements of the structure from there. My problem is that I can't print out values of the array in another function( main() in my case) other than the one I used to initialise the array. Please how can I print those values? Thank you.
#include <stdio.h>
#include <stdlib.h>
/*
*
*/
typedef struct s{
char *value;
} S;
S list[2];
void function( ){
char val1[] = "val1";
char val2[] = "val2";
S v1 = {val1};
S v2 = {val2};
list[0] = v1;
list[1] = v2;
printf("%s\n", list[1].value); //prints val2
}
int main(int argc, char** argv) {
function();
printf("%s", list[1].value); //prints nonsense
return 0;
}
What I have tried :
I modified function() to take list as an argument( function (list)) and declared list in main() instead. It didn't work.
I modified function to return list (S* function()), it didn't work.
I used an array of integers ( instead of structure i.e. int list[2], declared it as a global variable and initialised it in function()) and everything worked fine, suggesting that the problem is from how I am accessing structure, but I just can't figure it out.
I searched the internet, but couldn't get a similar problem.
In your function function you assign an address of a local variable to your structure. After returning from function this address is no longer valid. You could either make it static or allocated it dynamically.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct s
{
char *value;
} S;
S list[2];
void function( )
{
char val1[] = "val1";
char val2[] = "val2";
//Note that you are creating a copy of "val1" here which can be avoided by changing it to char *val1 = "val1";
list[0].value = malloc(strlen(val1)+1); //allocate space for val1 + NUL-terminator
strcpy(list[0].value, val1); //copy string
list[1].value = malloc(strlen(val2)+1);
strcpy(list[1].value, val2);
//You could also use the function strdup which allocates memory and duplicates the string
//list[0].value = strdup(val1);
printf("%s\n", list[1].value); //prints val2
}
int main(int argc, char** argv)
{
function();
printf("%s", list[1].value);
free(list[0].value); //Don't forget to free.
free(list[1].value);
return 0;
}
If we compared integers we would assign one of them as the largest/smallest one.
However, when I try comparing more than two strings, I can't manage assaigment.
In my code "for loop" compares two of the strings. This is good method but I need to compare one of them to the others individually. (I can predict that I need to use two for loop, but also I can't implement) What is your suggestions?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct wordSorting
{
char name[15];
int i = 0;
};
int main()
{
wordSorting *wordElement = (wordSorting *)malloc(sizeof(wordSorting));
wordElement = (wordSorting *)malloc(sizeof(wordSorting));
printf("-- Enter three person name --\n\n");
for (wordElement->i = 0; wordElement->i < 3; wordElement->i++)
{
printf("Enter %d. person name: ", wordElement->i + 1);
scanf("%s", wordElement[wordElement->i].name);
}
printf("\n");
for (wordElement->i = 0; wordElement->i < 3; wordElement->i++)
{
if ((strcmp(wordElement[wordElement->i].name, wordElement[wordElement->i + 1].name))<0)
{
printf("%s", wordElement[wordElement->i].name);
}
}
}
First
typedef struct wordSorting
{
char name[15];
int i = 0;
};
Members of typedef/struct cannot be initied.
That is not the way to define a typedef, change it as:
typedef struct
{
char name[15];
int i;
}wordSorting;
Second:
wordElement = (wordSorting *)malloc(sizeof(wordSorting));
makes no sense. malloc returns void pointer, and you already init your variable at the first element in the first line of code.
And, as someone edited: do not cast malloc return, please.
Third, :
wordSorting *wordElement = (wordSorting *)malloc(sizeof(wordSorting));
wordElement = (wordSorting *)malloc(sizeof(wordSorting));
printf("-- Enter three person name --\n\n");
for (wordElement->i = 0; wordElement->i < 3; wordElement->i++)
{
printf("Enter %d. person name: ", wordElement->i + 1);
scanf("%s", wordElement[wordElement->i].name);
}
You are allocating space for one element, no array are defined then wordElement[wordElement->i].name is undefined Behaviour.
Finally
I don't know what compiler are you using, but gcc cannot compile such a bad code full of errors...
Suggestion.
What I think you need is to use array, but you must allocate the number of member you need, by:
wordSorting *wordElement = malloc(sizeof(wordSorting)*num_of_elements);
or simply, using a local array:
wordSorting wordElement[num_of_elements];
If I have defined this:
typedef char word[30];
typedef struct {
int num;
word group[30];
} paragraph;
And then in the body:
int
main(int argc, char **argv) {
paragraph p;
word w = "BLA";
return 0;
}
How do I assign w in the array p and then printf w in terms of p
I know this is wrong but e.g.:
p[][1] = w;
printf("%s", p[][1]);
Pleas help a noob out
Arrays are not assignable. Either initialize your array to the proper size and set each element as needed or store a pointer instead.
Assuming you really intend to use the flexible array member introduced in C99, you would need to write code like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char word[30];
typedef struct {
int num;
word group[];
} paragraph;
int main(void)
{
paragraph *p = malloc(sizeof(*p) + 1 * sizeof(word));
word w = "BLA";
strcpy(p->group[0], w);
printf("Word: %s\n", p->group[0]);
free(p);
return 0;
}
That's modestly tricky code. Avoid using flexible array members until you understand what all this is doing. Until then, make the group member of the paragraph into a word:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char word[30];
typedef struct {
int num;
word group;
} paragraph;
int main(void)
{
paragraph p;
word w = "BLA";
strcpy(p.group, w);
printf("Word: %s\n", p.group);
return 0;
}
The key point remains that you cannot directly assign arrays and need to use strcpy() or a relative with strings, and memmove() or perhaps memcpy() with other types. You can assign structures that contain arrays in general (though you can't do that with structures containing a flexible array member), but that's because you can do structure assignment and it is coincidental that the structure contains an array.
BUT for word group, if you put group[30], how does that affect the rest of the code?
Here's code that does as you ask:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char word[30];
typedef struct
{
int num;
word group[30];
} paragraph;
int main(void)
{
paragraph p;
word w = "BLA";
strcpy(p.group[0], w);
printf("Word: %s\n", p.group[0]);
return 0;
}
Under this structure, assuming sizeof(int) == 4, you would find that sizeof(paragraph) == 904 because you've declared an array of 30 words, and each word is an array of 30 characters. This structure would allow you to add multiple words to the paragraph (and most paragraphs that I write most certainly contain more than one word!). You still have to use strcpy() to copy the word from w to an element of p.group:
int main(void)
{
paragraph p;
word w = "BLA";
strcpy(p.group[0], w);
strcpy(p.group[1], "Porcupine");
strcpy(p.group[2], "Elephant");
p.num = 3;
printf("Word: %s\n", p.group[0]);
printf("Paragraph:");
for (int i = 0; i < p.num; i++)
printf(" %s", p.group[i]);
putchar('\n');
return 0;
}
While it isn't wrong to use a typedef like word, it isn't something I'd normally do. It can all too easily lead to more confusion than enlightenment. It could also lead to wasted memory if most of your words are significantly fewer than 29 characters long. (The onus is on you to ensure that you do not store words longer than 29 characters (plus the terminating null byte) in the p.group array elements.) OTOH, the overhead of memory allocation with 64-bit software could easily render the wasted space for a single word moot.