300 likes | 324 Vues
Learn how to declare database records using structs in various programming languages like C, COBOL, Pascal, SQL and see how to store and manipulate data efficiently.
E N D
Structured Data Objects (Structs)
Structs (structured data objects) Recall our definition of an array: • an array is a fixed number of contiguous storage elements allof the same data type. • The abstract data type struct avoids one restriction: • The elements be NEED NOT all be of the same data type. A struct: • Consists of 2 or more component data types • A component part may be either a simple data type (e.g., int, unsigned int, float, char, long, double, etc.) A pointer (e.g., * int, * float, * char, * long, * double, etc.) Or another structured object (i.e., abstract type struct)
A struct corresponds to records in a database • Assume we maintain a simple database of student information Attribute (Field) Data Type Student Name String (Allow for 30 characters) Student ID Integer (int) Major String (Allow for 10 characters) Grade-Point Average Real (float) Hours Completed Integer (int) This record (let’s call it student): • Consists of 5 (five) data elements (Student Name, Student ID, Major, Grade-Point Average, Hours Completed) • Consists of 3 (three) different data types (Strings (2), Integers (2), and a real (float))
Declaring Records (in other languages): COBOL: 01 STUDENT 02 STUDENT-NAMEPICX(30). 02 STUDENT-IDPIC9(6). 02 MAJORPICX(10). 02 GPAPIC9V99. 02 TOTAL-HOURSPIC999. 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 tablestudent ( student_namechar(30) not null, student_idintegernot null, majorchar(10) default ‘CIS’, gpa decimal(4,2), total_hourssmallint, primary key (student_id), check (gpa > 0) )
Declaring Records (in C): structstudent { charstudent_name[31]; // Remember: we need 1-byte for ‘\0’ intstudent_id; charmajor[11]; // Remember: we need 1-byte for ‘\0’ floatgpa; inttotal_hrs; }; We have created a new data type: struct student • just as with basic data types, we can now associate variables (specific locations in RAM) with the data type 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): Element Bytes charstudent_name[31]; 31 intstudent_id; 2 charmajor[11]; 11 floatgpa; 4 inttotal_hrs; 2 50 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 ??
7524 7520 7521 7523 7530 7531 7533 7522 7526 7532 7527 7528 7529 7525 y -- n g , P i e t M o n a -- \0 n g n i -- n -- -- s -- -- a s -- \0 P -- -- -- -- -- -- -- -- -- -- 7539 7564 7560 7542 7551 7548 7545 7546 7549 7541 7538 7543 7544 7537 7550 7535 7536 7554 7555 7559 7556 7558 7562 7553 7563 7540 7568 7534 7557 67 12345 7547 7561 7552 7569 7565 7567 7566 3.27 How is this data stored in RAM?? As with ALL data types, the data type struct has a base address: • assume that variable active (of data type struct student) has the base address 7520 (and requiring 50 contiguous bytes, to 7569)
How can the address of each element in the struct be calculated?? Just as we calculated the address of each element in an array, the address of each element in a structis determined by adding the amount of storage required for each element and adding it to the base address. Element Type Start addr. Storage Next Address char [31] student_name 7520 31-bytes 7520 + 31 = 7551 student_ID int 7551 2-bytes 7551 + 2 = 7553 Or: 7520 + 33 = 7553 major 7553 11-bytes 7553 + 11 = 7564 char [11] Or: 7520 + 44 = 7564 float gpa 7564 4-bytes 7564 + 4 = 7568 Or:7520 + 48= 7568 total_hrs int 7568 2-bytes N/A
BUT, if structs are equivalent to records in a database, how can a database consist of only one (1) record ??? 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. • Remember: a struct, while abstract, is simply a data type For the sake of simplicity, let’s assume the following record structure: struct student { char student_name[20]; // names no longer than 19 characters float gpa; }; How would this struct be set up as an array ???
Structs and pointers Rewrite the previous program so it appears as follows:
Consider the following code: #include <stdio.h> 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 <stdio.h> #include <string.h> 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 and pointers 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 <stdio.h> 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 and pointers 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 <stdio.h> 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: 86712 86562Favre, Brett3.260 86584White, Reggie1.340 86606Smith, Bruce3.780 86628Smith, Emmitt2.050 86650Rice, 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; The BASE address of our array active Our new data type pointer to The same as: &active[0] struct student { char name[18]; float gpa; }; 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??
86570 86571 86575 86576 86577 86566 86565 86567 86573 86568 86569 86572 86574 86653 86564 86563 86658 86667 86657 86656 86655 86654 86652 86660 86650 86659 86666 86562 86665 86651 86662 86664 86663 86661 e R W h i t -- e , g t i \0 e -- -- e -- -- -- -- -- -- -- r -- J F -- g t \0 \0 e -- y r r B -- -- R e i r a c v e , , 86712 86668 86580 86587 86586 86586 86588 86584 86579 86589 86602 86599 86598 86597 86591 86601 86596 86578 86595 86592 86594 86600 86590 86583 86715 86714 86671 86582 86670 86713 86581 86669 1.34 86562 3.26 3.55 86593 86605 86603 86604 The contents of address record ( = active OR &active[0]) Points to Located at Continue to
86712 86712 86714 86715 86715 86714 86713 86713 86562 86562 The next statement in the program: printf(“%lu\n”, &record); Prints the BASE ADDRESS of our structure NOT the contents (Which contains the base address of our array active) Notice also that ALL pointers (e.g., record) require 4-bytes of storage We can now begin our loop: record CONTAINS the address while(record <= &active[4]) 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); The CONTENTS of record Field: name(on 20 spaces) Field: gpa(as f7.3) 86562 Favre, Brett 3.260 Notice that the statement record->name is a REDIRECT: • Go to the ADDRESS contained in record and find field name • i.e., record contains the address 86562, and name is at 86562 • The redirect record->gpa would yield the address 86580 An alternative statement is: (*record).name
86712 86712 86714 86715 86715 86714 86713 86713 86584 86562 The next statement: record++; Increments the contents of record: Changed to: The contents of record are increased by 22 Why are the contents increased by 22 and not 1 ??? 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: • A pointer is an address in RAM which contains an address • What type of data is at that address MUST be known in advance 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: Variable Located at Contains integer_pointer 12345 46788 float_pointer 12349 22734 double_pointer 12353 71122 Then: Statement Will result in the new value integer_pointer++; 46790 ++float_pointer; 22738 double_pointer--; 71114
For the rest of the loop: recordvalue Output 86584 86584White, Reggie1.340 86606 86606Smith, Bruce3.780 86628 86628Smith, Emmitt2.050 86650 86650Rice, Jerry3.550 86672 Greater than Stop
For the rest of the loop: recordvalue Output 86584 86584White, Reggie1.340 86606 86606Smith, Bruce3.780 86628 86628Smith, Emmitt2.050 86650 86650Rice, Jerry3.550 86672 Greater than Stop
For the rest of the loop: recordvalue Output 86584 86584White, Reggie1.340 86606 86606Smith, Bruce3.780 86628 86628Smith, Emmitt2.050 86650 86650Rice, Jerry3.550 86672 Greater than Stop