Structured Data Objects (Structs)
array Recall our definition of an array: fixedcontiguousall of the same data type an array is a fixed number of contiguous storage elements all of the same data type. struct The abstract data type struct avoids one restriction: NEED NOT The elements be NEED NOT all be of the same data type. Structs (structured data objects) struct A struct : Consists of 2 or more component data types A component part may be either a simple data type intunsigned intfloatcharlongdouble (e.g., int, unsigned int, float, char, long, double, etc.) A pointer intfloatcharlongdouble (e.g., * int, * float, * char, * long, * double, etc.) Or another structured object struct (i.e., abstract type struct)
struct A struct corresponds to records in a database Assume we maintain a simple database of student information Attribute (Field) Data Type Student NameString (Allow for 30 characters) Student IDInteger (int) MajorString (Allow for 10 characters) Grade-Point Average float Real (float) Hours CompletedInteger (int) student This record (let’s call it student ): Consists of 5 (five) data elements Consists of 3 (three) different data types (Student Name, Student ID, Major, Grade-Point Average, Hours Completed) float (Strings (2), Integers (2), and a real (float))
Declaring Records (in other languages): COBOL: 01STUDENT 02 STUDENT-NAMEPIC X(30). 02 STUDENT-IDPIC 9(6). 02 MAJORPIC X(10). 02 GPAPIC 9V TOTAL-HOURSPIC 999. Pascal : typestudent = record student_name : array[1..30] of char; student_id : integer; major: array[1..10] of char; gpa: real;. total_hours : integer; end; SQL : create table student ( student_name char(30) not null, student_id integer not null, major char(10) default ‘CIS’, gpa decimal(4,2), total_hours smallint, primary key (student_id), check (gpa > 0) )
Declaring Records (in C): struct student { char student_name[31]; // Remember: we need 1-byte for ‘\0’ int student_id; char major[11]; // Remember: we need 1-byte for ‘\0’ float gpa; int total_hrs; }; struct student We have created a new data type: struct student struct student just as with basic data types, we can now associate variables (specific locations in RAM) with the data type struct student struct student just as with basic data types, whenever we declare a variable to be of type struct student, we are requesting a specific number of contiguous bytes of RAM storage. How many bytes of storage do we need for a struct? That depends on the struct
For our struct (struct student): ElementBytes char char student_name[31];31 int int student_id;2 char char major[11];11 float float gpa;4 int int total_hrs; struct student We need 50 bytes of contiguous RAM storage for our data type struct student How do we declare and use structs in a C program ??
The output would appear as:
How is this data stored in RAM?? struct As with ALL data types, the data type struct has a base address: activestruct student assume that variable active (of data type struct student) has the base address 7520 (and requiring 50 contiguous bytes, to 7569) 7520 M 7521 a 7522 n 7523 n 7524 i 7525 n 7526 g 7527, P 7530 e 7531 y 7532 t 7533 o 7534 n 7535 \ P 7554 a 7555 s 7556 s 7557 i 7558 n 7559 g 7560 \
How can the address of each element in the struct be calculated?? struct Just as we calculated the address of each element in an array, the address of each element in a struct is determined by adding the amount of storage required for each element and adding it to the base address. ElementStart addr.StorageNext Address student_name bytes = 7551 student_ID75512-bytes = 7553 major Or: = bytes = 7564 gpa75644-bytes Or: = = 7568 Or: = 7568 total_hrs bytes N/A Type char [31] int char [11] float int
BUT, if structs are equivalent to records in a database, how can a database consist of only one (1) record ??? structint floatchar We can have an array of struct, just as we can have an array of int, and array of float, an array of char (string), etc. struct Remember: a struct, while abstract, is simply a data type struct student { char student_name[20]; // names no longer than 19 characters float gpa; }; For the sake of simplicity, let’s assume the following record structure: How would this struct be set up as an array ???
Structs and pointers Rewrite the previous program so it appears as follows:
The output should be:
Consider the following code: #include struct student { char student_name[20]; float gpa; }; int main() { struct student active[5] = {{"Favre, Brett",3.26}, {"White, Reggie",1.34}, {"Smith, Bruce",3.78}, {"Smith, Emmitt", 2.05}, {"Rice, Jerry", 3.55}}; int i; for (i = 0; i < 5; i++) printf("Name: %15s gpa: %4.2f\n", active[i].student_name,active[i].gpa); return 0; }
The program, as entered, produces the output : Name: Favre, Brett gpa: 3.26 Name: White, Reggie gpa: 1.34 Name: Smith, Bruce gpa: 3.78 Name: Smith, Emmitt gpa: 2.05 Name: Rice, Jerry gpa: 3.55 How does this program work ?? What if we were searching for a specific name, …. Say, Bruce Smith ??? Consider the following C code
#include struct student { char student_name[20]; float gpa; }; int main() { struct student active[5] = {{"Favre, Brett",3.26}, {"White, Reggie",1.34}, {"Smith, Bruce",3.78}, {"Smith, Emmitt",2.05}, {"Rice, Jerry",3.55}}; int i = 0; char find[20] = "Smith, Bruce"; while((strcmp(active[i].student_name,find)!=0)&&(i<5)) i++; if (i >= 5) printf("The name is NOT on the list"); else printf("%s IS on the list (gpa = %4.2f)", active[i].student_name, active[i].gpa); return 0; }
structs structs and pointers structs structs, like any other data type, have base addresses, and can be accessed by referring to its address. Consider the following modification of our previous program: #include struct student { char name[18]; float gpa; }; int main() { struct student active[5] = {{"Favre, Brett",3.26}, {"White, Reggie",1.34}, {"Smith, Bruce",3.78}, {"Smith, Emmitt",2.05}, {"Rice, Jerry",3.55}}; struct student *record = active; printf(“%lu\n”, &record); while(record <= &active[4]) { printf(“%lu %20s %7.3f\n”, record, record->name, record->gpa); record++; { return 0; }
structs structs and pointers structs structs, like any other data type, have base addresses, and can be accessed by referring to its address. Consider the following modification of our previous program: #include struct student { char name[18]; float gpa; }; int main() { struct student active[5] = {{"Favre, Brett",3.26}, {"White, Reggie",1.34}, {"Smith, Bruce",3.78}, {"Smith, Emmitt",2.05}, {"Rice, Jerry",3.55}}; struct student *record = active; printf(“%lu\n”, &record); while(record <= &active[4]) { printf(“%lu %20s %7.3f\n”, record, record->name, record->gpa); record++; { return 0; }
The following output would be produced: Favre, Brett White, Reggie Smith, Bruce Smith, Emmitt Rice, Jerry3.550 Note: These addresses are not the TRUE addresses, and they may change with each run How does this program work ??
Let’s take it from the line: struct student * record = active; Our new data type struct student { char name[18]; float gpa; }; pointer to BASE The BASE address array of our arrayactive &active[0] The same as: &active[0] record active Meaning, the variable pointer record is now initialized to the BASE address of array active ( or, in or case, 86562) How would this appear in RAM??
86562 F a v r e 86567, B r e t t \ W h i t 86589, g i e record active&active[0] The contents of address record ( = active OR &active[0]) Points to R e g \ e Continue to R i c e 86654, J e r r y \ Located at
The next statement in the program: printf(“%lu\n”, &record); Prints the BASE ADDRESS of our structure NOT NOT the contents active (Which contains the base address of our array active) record Notice also that ALL pointers (e.g., record) require 4-bytes of storage We can now begin our loop: while(record <= &active[4]) record record CONTAINS the address Which is less than the base address of our 5th record (86650) Enter Loop
Now we simply print out the first record: printf(“%lu %20s %7.3f\n”, record, record->name, record->gpa); record The CONTENTS of record name Field: name (on 20 spaces) gpa Field: gpa (as f7.3) 86562Favre, Brett3.260 (*record).name An alternative statement is: (*record).name record->name Notice that the statement record->name is a REDIRECT: Go to the ADDRESS contained in record and find field name recordname i.e., record contains the address 86562, and name is at record->gpa The redirect record->gpa would yield the address 86580
The next statement:record++; record Increments the contents of record: Changed to: record The contents of record are increased by 22 Why are the contents increased by 22 and not 1 ??? record --;--record; Record is pointer to our data type struct student (Initialized as: struct student *record;) which requires 22-bytes of storage. Incrementing increases the value contained by 22. Decrementing it (i.e., record --; or --record; would decrease the value contained by 22)
Remember: int *integer_pointer;// contains an address to an integer float *float_pointer;// contains an address to a float double *double_pointer;// contains an address to a double IF:VariableLocated at Contains integer_pointer float_pointer double_pointer A pointer is an address in RAM which contains an address What type of data is at that address MUST be known in advance Then:StatementWill result in the new value integer_pointer++; float_pointer;22738 double_pointer--;71114
For the rest of the loop: record record value Output 86584White, Reggie Smith, Bruce Smith, Emmitt Rice, Jerry Greater than Stop
For the rest of the loop: record record value Output 86584White, Reggie Smith, Bruce Smith, Emmitt Rice, Jerry Greater than Stop
For the rest of the loop: record record value Output 86584White, Reggie Smith, Bruce Smith, Emmitt Rice, Jerry Greater than Stop