C Multidimensional Character Array Initialization - c

I'm fairly new to C and I'm trying to wrap my head around the initialization of a multidimensional character array, for my assignment I'm asked to read from a file and store the text in an array,
I have to read input for 5 fictitious people and store some information about them, so I realized that my array will look something like:
char input[5][];
What I am confused about is the second parameter, I'm not sure what to set it too. There are 9 fields of information which I will be storing about these people, and I can't seem to find an answer to if I should set this second number to the amount of fields, or how large it should be. ie,
char input[5][9];
or
char input[5][256];
Also, if it's the latter, is there a practice of how larger I should set it to, or just pick a number? Thanks!

I suggest you take the following approach: instead of making an array of char to store the information about these persons, you should make a struct person, which would have some info variable with predefined lenght
struct person {
char name[50];
char address[50];
char phone_number[15];
};
or, if you want, you can make these char pointers (such like char *name, char *address), and then you can malloc() the desired amount of memory to each variable as you want (also, don't forget to free the memory after you use it).
Then, in your main, you could make an array of persons, such as struct person[5];, and manipulate them as you want.
edit: Also note that, as Pankrates commented, when you define a size for your array you must make sure that the input will not exceed the lenght of the array, otherwise you'll be writing stuff on memory that does not belong to you, which causes undefined behavior.

To figure this you should try to learn about the input. If you are absolutely sure there will be only 9 fields(of single char data) for 5 people, then you should set it to char input[5][9].
If you think there could be more fields of information than 9 in the future, then you could go for a higher value like char input[5][256]. However this would waste a lot of space if the data for fields are sparse. This is static assignment of memory
So the third option when you are unsure about the number of fields for each person, is to assign memory dynamically like--
char* input[5];
input[0] = malloc(sizeof(char) * 100); // space of 100 chars
Here in the last case, the memory is given at runtime instead of compile time. You can also get the size from user input and use it for assign memory for fields.
char* input[5];
int size = 0;
scanf("%d",&size);
input[0] = malloc(sizeof(char) * size);
Further more, if you need to store fields, where each field takes more than one character then you should create a structure.
struct person
{ char name[30]; // memory could be assigned dynamically or statically
char field1[30];
char field2[30];
...
};

Related

How to use flexible array members in nested C structs?

Related: flexible array member in a nested struct
I am trying to parse some data into a struct. The data contains information organized as follows:
struct unit {
struct unit_A {
// 28 bytes each
// dependency r6scA 1
char dr6scA1_tagclass[4];
uint32_t dr6scA1_tagnamepointer;
uint32_t dr6scA1_tagnamestringlength;
uint32_t dr6scA1_tagid;
// 12 bytes of 0x00
}A;
// A strings
struct unit_B {
// 48 bytes each
// dependency r6scB 1
char dr6scB1_tagclass[4];
uint32_t dr6scB1_tagnamepointer;
uint32_t dr6scB1_tagnamestringlength;
uint32_t dr6scB1_tagid;
// 32 bytes of 0x00
}B;
// B strings
// unit strings
}unit_container;
You can ignore the weird nomenclature.
My line comments // A strings, // B strings and // unit strings each contain null-terminated C strings, the numbers of which coincides with however many unit_A, unit_B, and unit struct entries there are in the data. So like if there are 5 entries of A in unit_container, then there would be 5 C strings in the location where it says // A strings.
Since I cannot use flexible array members at these locations, how should I interpret what are essentially an unknown number of variable-length C strings at these locations in the data?
For example, the data at these locations could be:
"The first entry is here.\0Second entry\0Another!\0Fourth.\0This 5th entry is the bestest entry evah by any reasonable standards.\0"
...which I expect I should interpret as:
char unit_A_strings[]
...but this is not possible. What are my options?
Thank you for your consideration.
EDIT:
I think the most attractive option so far is:
char** unit_A_strings; to point to an array of char strings.
If I do:
char unit_A_strings[1]; to define a char array of fixed size of 1 char, then I must abandon sizeof(unit) and such, or hassle with memory allocation sizes, even though it is most accurate to the kind of data present. The same situation occurs if I do char * unit_A_strings[1];.
Another question: What would be the difference between using char *unit_A_strings; and char** unit_A_strings;?
Conclusion:
The main problem is that structs are intended for fixed-size information and what I am needing is a variable-sized information memory region. So I can't legitimately store the data into the struct -- at least not as the struct. This means that any other interpretation would be alright, and it seems to me that char** is the best available option for this struct situation.
I think it can using the char** instead (Or you can write some structure to wrapper it).
for example, you can write a help function to decode you stream.
char** decodeMyStream(uint_8* stream, unsigned int* numberOfCString)
{
*numberOfCString = decodeNumberOfCString(stream);
char** cstrings = malloc((*numberOfCString) * sizeof(char*));
unsigned int start = 0;
for (unsigned int i = 0; i < *numberOfCString; ++i)
{
usigned int len = calculateIthStringLength(stream, start)
cstrings[i] = malloc((len) * sizeof(char));
memcpy(cstrings[i], stream + start, len);
start += len
}
return cstrings;
}
it just no thinking example code, you can think out more better algorithms.
I think the closest you're going to get is by providing an array of strings:
char *AStrings[] = { "The first entry is here.",
"Second entry",
"Another!",
"Fourth.",
"This 5th entry is the bestest entry evah by any reasonable standards.",
NULL
};
Note two things:
AStrings is an array of pointers-to-strings - it will be 6 (see 2. below) consecutive pointers that point to the actual strings, NOT the 'compound' string you used in your example.
I ended AStrings with a NULL pointer, to resolve the "when do I finish?" question.
So you can "fall off the end" of A and start looking at locations as pointers - but be careful! The compiler may put in all sorts of padding between one variable and the next, mucking up any assumptions about where they are relative to each other in memory - including reordering them!
Edit
Oh! I just had a thought. Another data representation that may help is essentially what you did. I've 'prettied' it up a bit:
char AString[] = "The first entry is here.\0"
"Second entry\0"
"Another!\0"
"Fourth.\0"
"This 5th entry is the bestest entry evah by any reasonable standards.\0";
The C compiler will automatically concatenate two 'adjacent' strings as though they were one string - with no NUL character between them. I put them in specifically above.
The C compiler will automatically put a '\0' at the end of any string - at the semicolon (;) in the above example. That means that the string actually ends with two NUL characters, not one.
You can use that fact to keep track of where you are while parsing the string 'array' - assuming that every desired value has a (sub)string of more than zero length! As soon as you encounter a zero-length (sub)string, you know you've reached the end of the string 'array'.
I call these kind of strings ASCIIZZ strings (ASCIIZ strings with a second NUL at the end of all of them).

How should I declare strings within C structs?

Hello I am new to this site, and I require some help with understanding what would be considered the "norm" while coding structures in C that require a string. Basically I am wondering which of the following ways would be considered the "industry standard" while using structures in C to keep track of ALL of the memory the structure requires:
1) Fixed Size String:
typedef struct
{
int damage;
char name[40];
} Item;
I can now get the size using sizeof(Item)
2) Character Array Pointer
typedef struct
{
int damage;
char *name;
} Item;
I know I can store the size of name using a second variable, but is there another way?
i) is there any other advantage to using the fixed size (1)
char name[40];
versus doing the following and using a pointer to a char array (2)?
char *name;
and if so, what is the advantage?
ii) Also, is the string using a pointer to a char array (2) going to be stored sequentially and immediately after the structure (immediately after the pointer to the string) or will it be stored somewhere else in memory?
iii) I wish to know how one can find the length of a char * string variable (without using a size_t, or integer value to store the length)
There are basically 3 common conventions for strings. All three are found in the wild, both for in-memory representation and storage/transmission.
Fixed size. Access is very efficient, but if the actual length varies you both waste space and need one of the below methods to determine the end of the "real" content.
Length prefixed. Extra space is included in the dynamically allocation, to hold the length. From the pointer you can find both the character content and the length immediately preceding it. Example: BSTR Sometimes the length is encoded to be more space efficient for short strings. Example: ASN-1
Terminated. The string extends until the first occurrence of the termination character (typically NUL), and the content cannot contain that character. Variations made the termination two NUL in sequence, to allow individual NUL characters to exist in the string, which is then often treated as a packed list of strings. Other variations use an encoding such as byte stuffing (UTF-8 would also work) to guarantee that there exists some code reserved for termination that can't ever appear in the encoded version of the content.
In the third case, there's a function such as strlen to search for the terminator and find the length.
Both cases which use pointers can point to data immediately following the fixed portion of the structure, if you carefully allocate it that way. If you want to force this, then use a flexible array on the end of your structure (no pointer needed). Like this:
typedef struct
{
int damage;
char name[]; // terminated
} Item;
or
typedef struct
{
int damage;
int length_of_name;
char name[];
} Item;
1) is there any other advantage to using the fixed size (1)
char name[40];
versus doing the following and using a pointer to a char array (2)?
char *name;
and if so, what is the advantage?
With your array declared as char name[40]; space for name is already allocated and you are free to copy information into name from name[0] through name[39]. However, in the case of char *name;, it is simply a character pointer and can be used to point to an existing string in memory, but, on its own, cannot be used to copy information to until you allocate memory to hold that information. So say you have a 30 character string you want to copy to name declared as char *name;, you must first allocate with malloc 30 characters plus an additional character to hold the null-terminating character:
char *name;
name = malloc (sizeof (char) * (30 + 1));
Then you are free to copy information to/from name. An advantage of dynamically allocating is that you can realloc memory for name if the information you are storing in name grows. beyond 30 characters. An additional requirement after allocating memory for name, you are responsible for freeing the memory you have allocated when it is no longer needed. That's a rough outline of the pros/cons/requirements for using one as opposed to the other.
If you know the maximum length of the string you need, then you can use a character array. It does mean though that you will be using more memory than you'd typically use with dynamically allocated character arrays. Also, take a look at CString if you are using C++. You can find the length of the character array using strlen. In case of static allocation I believe it will be a part of the variable. Dynamic can be anywhere on the heap.

How do I use an array variable inside an array of structures?

I'm trying to grasp the concept of arrays of structures and came up with a problem. Hopefully you can help me out.
Okay, so, the problem I'm facing is how to declare and use (i.e. accept & display values) of an array variable within an array of structures?
This sample code may visually help you to understand my problem:
#include<stdio.h>
struct node{
int roll;
char name[10];
int grades[5]; // Accepts 5 grades for each student
};
int main()
{
struct node student[3];
/*Accept and display values for structure members here*/
return 0;
}
I know there's a similar example here.
But I don't understand line 4 in the accepted answer's main() section, where memory is allocated using malloc() :
list[ip].inputs[inp]= (char*)malloc(25);
I'm getting confused between the 25 bytes allocated here and the 10 defined in char* inputs[10];
What exactly is happening here? And how do you solve the problem I mentioned above?
There's an extra * in the example you quote. The malloc is needed only because of that, in your example inputs is an array of 10 pointers to char while here name is a buffer holding 10 chars. You don't need any malloc in your code.
Your structure looks like this in memory (assuming 4-bytes ints):
Your student array from main looks like:
As you see, fields are laid out one after another. Thus, to read the name of the first student you have to write into student[0].name (using strncpy to ensure that there's no overflow). To change the third letter of the name of the second student you'll use student[1].name[2].
You can safely use it like this:
strcpy(student[1].name, "Yu Hao");
student[1].grades[1] = 95;
printf("student 1 name: %s\n", student[1].name);
printf("student1 grades1:%d\n", student[1].grades[1]);
The example you linked uses malloc because the struct has some pointers, and pointers have to point to somewhere valid before using. That's not the case in your example.
Note that using strcpy can lead to disaster when you copy a string longer than 10, if that's to consider, use strncpy instead.
To answer the question related to the referred post.
First, hope you have basic knowledge about pointers in C.
A pointer is indeed a memory address for short.
For details I recomend you this booklet (a very excellent introduction about arrays and poiners).
In that piece of codes, the inputs is defined as char* inputs[10];.
It's an array of pointers.
So each elment in that array should be an address.
The argument 25 in the malloc invokation is not necessary (you can also specify 40 or 50 to meet your requirement).
The only thing you should guarantee is that each element in the array is an address (that's what malloc returns).
The 10 specifies array dimension, i.e. you can store 10 addresses in total in inputs or say, you can initialize the array by invoking malloc ten times like:
struct a;
for (int i = 0; i < 10; i++) {
a.inputs[i] = (char *) malloc(25);
}
Back to your own problem.
In your case, the symbol name identifies the address to the storage.
No need for you to malloc new storage.

function with a struct array pointer as an argument, C language

typedef struct {
char manufacturer[SIZE];
char model[SIZE];
int size;
int id;
int qty;
double cost;
double price;
} tv;
void firstSix(tv *tvarr[]);
void firstSix(tv *tvarr[])
{
(*tvarr[0]).manufacturer = "Vizio";
}
I am making an inventory program. It consists of an array of structs that will store information about different televisions. In my program I am required to hardcode six entries into the array, so I am trying to make a function that will take a struct array pointer argument. In the above code, I included the struct declaration, the function prototype and function definition that I am trying to make. Everything is placed before and after main in the respective order. I don't understand why Visual Studio is highlighting the first parenthesis in the code inside the function definition and saying "expression must be a modifiable lvalue". I don't understand what it is that I am doing wrong. Please help.
You cannot assign an array like that. You need to do
strcpy ((*tvarr[0]).manufacturer, "Vizio");
Make sure that you don't go out of bounds when copying the string into the array.
You can either check the size of the string in advance or use strncpy which will limit the maximum number of characters to be copied.
An array is not a modifiable l-value. So basically you cannot have it on the left hand side of an assignment.
Or may be you also might want to define manufacture as char *manufacture and then dynamically allocate the string.
manufacturer = strdup ("Vizio"); //manufacturer is char *
Or depending on the length first allocate the buffer
manufacturer = malloc (sizeof (char) * needed_bytes);
Whenever you dynamically allocate the buffer, whenever you have finished working with it always remember to free it free (manufacturer).
I think you want to do something like
strncpy((tvarr[0])->manufacturer, "Vizio", SIZE - 1);
Kevin has it; you can't assign a string to a pointer, you must copy the data to the array. I suggest strncpy to keep from running off the end of the allocated space.

Reading and Writing Structures [C]

IMPORTANT EDIT:
Sorry everyone, i made a big mistake in the structure.
char *name; is meant to be outside of the structure, written to the file after the structure.
This way, you read the structure, find out the size of the name, then read in the string. Also explains why there is no need for a null terminator.
However, i feel somewhere, my actual question has been answered. If someone would like to edit their responses so i can choose one which is the best fitting i'd appreciate it.
Again, the question I was asking is "If you read in a structure, are you also reading in the data it holds, or do you need to access it some other way".
Sorry for the confusion
For an assignment, I've been tasked with a program which writes and reads structures to a disk (using fread and fwrite).
I'm having trouble grasping the concept.
Lets say we have this structure:
typedef struct {
short nameLength;
char* name;
}attendenceList;
attendenceList names;
now assume we give it this data:
names.name = "John Doe\0";
names.nameLength = strlen(names.name); /*potentially -1?*/
and then we use fwrite... given a file pointer fp.
fwrite(&names,sizeof(names),1,fp);
now we close the file, and open it later to read in the structure.
the question is this: when we read in the structure, are we also reading in the variables it stores?
Can we then now do something like:
if(names.nameLength < 10)
{
...
}
Or do we have to fread something more then just the structure, or assign them somehow?
Assuming the fread is:
fread(&names,sizeof(names),1,fp);
Also assuming we've defined the structure in our current function, as above.
Thanks for the help!
You have a problem here:
fwrite(&names,sizeof(names),1,fp);
Since attendenceList saves the name as a char * this will just write out the pointer, not the actual text. When you read that back in, the memory the pointer is referencing will most likely have something else in it.
You have two choices:
Put a character array (char names[MAXSIZE]) in attendenceList.
Don't write the raw data structure, but write the necessary fields.
You're writing the memory layout of the structure, which includes its members.
You'll get them back if you read the structure back in again - atleast if you do it on the same platform, with a program compiled with the same compiler and compiler settings.
Your name member is declared just as a char, so you can't store a string in it.
If name was a pointer like this:
typedef struct {
short nameLength;
char *name;
}attendenceList;
You really should not read/write the struct to a file. You will write the structure as it's laid out in memory, and that includes the value if the name pointer.
fwrite knows nothing about pointers inside your structure, it will not follow pointers and also write whatever they point to.
when you read the structure back again, you'll read in the address in the name pointer, and that might not point to anything sensible anymore.
If you declare name as an array, you'll be ok, as the array and its content is part of the structure.
typedef struct {
short nameLength;
char name[32];
}attendenceList;
As always, make sure you don't try to copy a string - including its nul terminator- to name that's larger than 32. And when you read it back again. set yourstruct.name[31] = 0; so you are sure the buffer is null terminated.
To write a structure, you'd do
attendenceList my_list;
//initialize my_list
if(fwrite(&my_list,sizeof my_list,1,f) != 1) {
//handle error
}
And to read it back again:
attendenceList my_list;
//initialize my_list
if(fread(&my_list,sizeof my_list,1,f) != 1) {
//handle error
}
}
I'm assuming you meant char* name instead of char name.
Also sizeof(name) will return 4 because you are getting the size of a char* not the length of the char array. So you should write strlen(name) not sizeof(name) inside your fwrite.
In your above example I would recommend storing the string exact size without the null termination. You don't need to store the string length as you can get that after.
If you are reading just a string from a file, and you wrote the exact size without the null termination. Then you need to manually null terminate your buffer after you read the data in.
So make sure you allocate at least the size of your data you are reading in plus 1.
Then you can set the last byte of that array to '\0'.
If you write a whole struct at a time to the buffer, you should be careful because of padding. The padding may not always be the same.
when we read in the structure, are we also reading in the variables it stores?
Yes you are, but the problem you have is that as I mentioned above you will be storing the pointer char* (4 bytes) and not the actual char array. I would recommend storing the struct elements individually.
You ask:
now we close the file, and open it later to read in the structure. the question is this: when we read in the structure, are we also reading in the variables it stores?
No. sizeof(names) is a constant value defined at compile time. It will be the same as
sizeof(short) + sizeof(void*) + some_amount_of_padding_to_align_things
it will NOT include the size of what names.name points to, it will only include the size of the pointer itself.
So you have two problems when writing this to a file.
you aren't actually writing the name string to the file
you are writing a pointer value to the file that will have no meaning when you read it back.
As your code is currently written, When you read back the names, names.name will point to somewhere, but it won't point to "John Doe\0".
What you need to do is to write the string pointed to by names.name instead of the pointer value.
What you need to do is sometimes called "flattening" the structure, You make a structure in memory that contains no pointers, but holds the same data as the structure you want to use, then you write the flattened structure to disk. This is one way to do that.
typedef struct {
short nameLength;
char name[1]; // this will be variable sized at runtime.
}attendenceListFlat;
int cbFlat = sizeof(attendenceListFlat) + strlen(names.name);
attendenceListFlat * pflat = malloc(cbFlat);
pflat->nameLength = names.nameLength;
strcpy(pflat->name, names.name);
fwrite(pflat, cbFlat, 1, fp);
The flattened structure ends with an array that has a minimum size of 1, but when we malloc, we add strlen(names.name) so we can treat that as an array of strlen(names.name)+1 size.
A few things.
Structures are just chunks of memory. It's just taking a bunch of bytes and drawing boundaries on them. Accessing structure elements is just a convenient way of getting a particular memory offset cast as a particular type of data
You are attempting to assign a string to a char type. This will not work. In C, strings are arrays of characters with a NULL byte at the end of them. The easiest way to get this to work is to set a side a fixed buffer for the name. When you create your structure you'll have to copy the name into the buffer (being very careful not to write more bytes than the buffer contains). You can then write/read the buffer from the file in one step.
struct attendanceList {
int namelen;
char name[256]; //fixed size buffer for name
}
Another way you could do it is by having the name be a pointer to a string. This makes what you're trying to do more complicated, because in order to write/read the struct to/from a file, you will have to take into account that the name is stored in a different place in memory. This means two writes and two reads (depending on how you do it) as well as correctly assigning the name pointer to wherever you read the data for the name.
struct attendanceList {
int namelen;
char* name; //the * means "this is a pointer to a char somewhere else in memory"
}
There's a third way you could do it, with a dynamically sized struct using a trick with a zero length array at the end of a struct. Once you know how long the name is, you allocate the correct amount (sizeof(struct attendanceList) + length of string). Then you have it in one contiguous buffer. You just need to remember that sizeof(struct attendanceList) is not the size you need to write/read. This might be a little confusing as a beginning. It is also kind of a hack that's not supported under all compilers.
struct attendanceList {
int namelen;
char name[0]; //this just allows easy access to the data following the struct. Be careful!
}

Resources