Question:
C programming, array of structures with a nested structure having memory allocated dynamically with malloc?
anonymous
2013-07-03 20:25:15 UTC
I am a student new to programming, this summer I am taking a c programming course online and my instructor is out of the office until July 8th, 2013 and this assignment is due July 5th, 2013.

The assignment is the following:
Dynamic Memory Allocation

Create a structure to represent a new datatype called StudentInfo. Student info will contain three members, an integer called Id, an instance of a date structure called birthdate [you’ll need to create a date structure for this], and a third integer to store a phone number.

Inside of your program, ask the user how many students they need to enter records for. Once you have completed this, dynamically allocate enough memory to store the student records (basically, create an array of your structure, but use malloc to allocate the memory. Do not use the syntax “int values[5]” to create the array). Use a loop to prompt the user to enter the data for all of the student information.

Finally, create a loop that scans for and then prints out the ID number for the oldest student. You must construct your loop in such a way that it can handle more than three students.
*Hint: before trying to write the code for this, think about the problem. Draw it out. Make it with pseudo code. If you try to write the code to accomplish this without some sort of a plan, it will be significantly more difficult.

This is the first time I have had troubles with C, I feel like I missed a lecture or two, the videos I have are confusing and my books don't go into great detail on this.

Here is my code:

#include
#include

//define structure to store students birth date
struct date
{
int month;
int day;
int year;
};

//define structure to store student info and date structure for birth date
struct studentInfo
{
int iD;
struct date birthDate;
int phone;
};

int main (void)
{
//declare and initialize variables
int recNum = 0; //number of records
struct studentInfo * records = NULL; //struct pointer, array

//request user input and store in recNum for record amount
printf("\nHow many students do you need to enter records for?:");
scanf ("%d",&recNum);

//dynamically allocate memory
records = (struct studentInfo*)malloc((sizeof(struct studentInfo)*recNum));

//loop through records and request/store values from user
int count;
int studentNum=1;
for(count=0;count {
printf("Please enter the following for student number %d\n",studentNum);

//request and store student ID
printf("Student ID#:");
scanf ("%d",&records[count].iD);

//request and store student phone number
printf("Student phone# (numbers only, 10 digits):");
scanf ("%d",&records[count].phone);

//error checking, check if phone number is 10 digits
int phoneCount = 0;
int phoneCopy = records[count].phone;
while(phoneCopy != 0)
{
phoneCopy /= 10;
phoneCount++;
}
if (phoneCount != 10)
{
printf("The number you have entered is not 10 digits, please re-enter:");
scanf ("%d",&records[count].phone);
}

//request and store student birthdate
printf("Student birthday (mm/dd/yyyy):");
scanf("%d/%d/%d",&records[count].birthdate.month,&records[count].birthdate.day,&records[count].birthdate.year);


//test stuff
printf("Student number %d has an ID of %d and a phone number of %d\n",studentNum,records[count].iD,records[count].phone);
studentNum++;
}

return 0;
}


I'm getting a error that says struct studentInfo has no member named birthdate. I've tried different variations I have found out on the web and in my books, this is the second major snag I have ran into with the program. I really feel like I missed a lesson or something here, maybe I need to review pointers. Please help.

ps. I really don't now why I use the line below, I just thought I would use it after watching my instructors videos
struct studentInfo * records = NULL;
It doesn't make much sense to me. I'm not quite sure how declaring a pointer of type struct studentInfo magically lets us use records as an array???
Three answers:
McFate
2013-07-03 20:33:16 UTC
First of all, when I try your code (after putting back the parts that Yahoo truncated with ellipses) it compiles and runs for me. Here's my version of the scanf() statement (with extra spaces so Yahoo doesn't truncate it):



scanf( "%d/%d/%d",

&(records[ count ] .birthDate .month),

&(records[ count ] .birthDate .day),

&(records[ count ] .birthDate .year) );





Second, an array of Something is the same as a pointer to Something in C. You just have to be sure that however many elements you want in the array, you have that many times Something's size, of memory that you point to. For example:



int a; ("there's a variable named "a" which is an integer")

int *b = &a; ("there's a variable named "b" which is a pointer to an integer, and it is set to the address of "a"")



Now you have a pointer (b) that points to one integer (a). You could reference the content of "a" as either *b or b[0]. Those are exactly equivalent in C. You couldn't use b[1] because you don't have a second integer's worth of space. You could also do this:



int a[2]; ("there's a variable named "a" which is an array of TWO integers")

int *b = &(a[0]); ("there's a variable named "b" which is a pointer to an integer, and it is set to the address if the first integer in a)



Now you can access b[0] OR b[1] and they will be exactly the same as a[0] and a[1]. Even though "a" is an int-array and b is an int-pointer, they're exactly equivalent and can be used interchangeably. You can write "*b" or "*a" or "b[0]" or "a[0]" and all four of those are references to the exact same memory location.



Finally, when you declare a struct, you're really just giving the compiler instructions for how a bundle of data is accessed and how big it is. Once you've done that, you can make an array of it just as you can make an array of built-in types (like float or int), via the sizeof operator which gives the size in bytes of the type that follows.



If you want an array of 10 ints, you can do it like this:



int *myArray = (int *) malloc( 10 * sizeof (int) );



You ask for enough memory to store 10 ints, and set your pointer to the start of the list. Then myArray[0] would be the first however many bytes (typically 4 these days), and myArray[1] would be the next four bytes, and so forth, up to the 10th element myArray[9]. If you tried to use myArray[10] it might run off the end of the array into memory that's used for other things.



It works the same with structs. If you want an array of 10 "struct X" instances, then you'd make a "struct X *" pointer and set it to malloc( 10 * sizeof (struct X) );



@M
husoski
2013-07-03 20:49:54 UTC
The "birthdate" error is probably capitalization. It's declared as "birthDate" and case is important in C.



For allocation, the calloc() function (also in ) is nicer in many ways than malloc(). It takes the items size and item count as separate arguments, so there are cases where you don't need an extra set of parentheses. It also zeros the memory obtained, just like a static or global array declaration (and unlike an array that's a local variable).





As for the pointer vs. array, you'll find that there's a strong association between pointers and arrays in C. It's sometimes called the "array-pointer duality", and leads a few to (mistakenly) say that arrays and pointers are identical in C. They are merely very similar.



In C, every pointer is presumed to point to an array.



Every array is passed to functions as a pointer to its first element. In fact, nearly all uses of an array name in an expression will be implicitly converted to a pointer to the first element. In nearly every case (sizeof expressions are one exception) use of an array name a is equivalent to (&a[0]).



The array indexing operator a[x] is FORMALLY defined as *(a+x). So much so that if a is an array then a[1] means *(a+1). (Remember that a is not only an array, but a pointer its first element.)



The totally weird part about the above is, since a+1 and 1+a are both valid pointer expressions, then the formal definition makes 1[a] a valid alternative to a[1]. Programmers who have worked in C/C++ for decades will swear that's a lie. Try it on your favorite compiler before swearing at me, though.



Needless to say, you shouldn't use expressions like 1[a] if you want to make friends. (...and keep the ones you have! :^)
anonymous
2016-03-09 00:51:17 UTC
students.c:41:29: error: request for member ‘iD’ in something not a structure or union that is because you declared records as an int* should be struct studentInfo * records; #include #include //define structure to store students birth date struct date { int month; int day; int year; }; //define structure to store student info and date structure for birth date struct studentInfo { int iD; struct date birthDate; int phone; }; int main (void) { //declare and initialize variables int recNum = 0; //number of records //int * records = NULL; //integer pointer, array // bzzzt oops records is a student info struct NOT an integer struct studentInfo * records; //request user input and store in count for record amount printf("\nHow many students do you need to enter records for?:"); scanf ("%d",&recNum); //dynamically allocate memory records = malloc((sizeof(struct studentInfo)*recNum)); // cast not needed in C //loop through records and request/store values from user int count; int studentNum=1; for(count=0;count


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...