Presentation is loading. Please wait.

Presentation is loading. Please wait.

 Complex data types  Structures  Defined types  Structures and functions  Structures and pointers.

Similar presentations


Presentation on theme: " Complex data types  Structures  Defined types  Structures and functions  Structures and pointers."— Presentation transcript:

1

2  Complex data types  Structures  Defined types  Structures and functions  Structures and pointers

3

4  Many programs require complex data to be represented  That cannot easily be represented using base type variables and arrays ▪ Base types are the defined C types like int, char, float, etc.  C allows structures to be defined and used in a program  A structure is a complex type that collects a number of variables, arrays or even other structures

5  Let’s assume that we want to represent student data for a small university  For each student we want to maintain  First name – a string  Last name – a string  Student number – an integer  GPA – a float this is a simplified version of what would be necessary, some of the complicating issues will be discussed later

6  If we wanted to maintain a list of a hundred students we could use four separate arrays  One for each of the four attributes ▪ First name, last name, student number, GPA  Referred to as parallel arrays  Whenever we want to retrieve student data we would use the same index in all arrays

7 index012...33...979899 id1101723456784864178924574444 index012...33...979899 firstBobKateSueDaveJoeEllaAnna index012...33...979899 lastWingSmithAbelDoddNgMossFrenc index012...33...979899 gpa3.003.502.753.752.254.003.50 Represents the student Dave Dodd

8  Maintaining parallel arrays can be hard  We must make consistent changes to all arrays ▪ If we delete an element from one, elements at the same index must be deleted from the others ▪ If we sort one array then all the other arrays must be sorted in the same way  Passing student data to functions is tedious ▪ A function to print student data needs four parameters  Or we can use structures

9 index012345678 id910172345678447548643459178924574444 index012345678 firstBobKateSueAlanDaveJoyJoeEllaAnna index012345678 lastWingSmithAbelFlimDoddShaeNgMossFrenc index012345678 gpa3.003.502.752.003.753.502.254.003.50 Sort index

10 index012345678 id110172345678447548643459178924574444 index012345678 firstBobKateSueAlanDaveJoyJoeEllaAnna index012345678 lastWingSmithAbelFlimDoddShaeNgMossFrenc index012345678 gpa3.003.502.752.003.753.502.254.003.50 Sort index index012345678 id178924573459444444754864567872349101 The data is now corrupt since the IDs do not match the students

11

12  A structure declaration is essentially the definition of a complex type struct student { int id; char first[MAXNAME]; char last[MAXNAME]; float gpa; }; struct student { int id; char first[MAXNAME]; char last[MAXNAME]; float gpa; }; keyword optional tag student variables the tag is optional but if we are going to declare the struct in one place and use it in another we need a tag

13  A structure declaration describes what data types are associated with a struct  It does not allocate space for any variables  Space is allocated when a variable is defined  struct student s1;  Instructs the compiler to reserve space for an int, two character arrays and a float ▪ The four components of s1 are allocated memory on the stack in sequence

14  A struct can be declared without a tag  If a variable is defined following the declaration struct { int id; char first[MAXNAME]; char last[MAXNAME]; float gpa; } s1;  This is really only useful for one-off structs

15  It is common for struct definitions to appear outside any function  So that they are available anywhere in the file  If a struct is defined inside a function it is only available in that function  Variables of a struct type are declared wherever they are needed  Just like any other variable

16  A structure can be initialized in much the same way as an array  Using a comma separated list of values enclosed in curly brackets struct student s1 = { 12345, “Bob”, “Smith”, 2.75 }; struct student s1 = { 12345, “Bob”, “Smith”, 2.75 };

17  Variables of a structure have to be accessed individually using the member operator (.)  To access a structure variable use the structure name and the variable name separated by a dot ▪ s1.id = 12345;  They can then be used like any variable of the same type ▪ And can be accessed, assigned new values, passed to functions and so on

18  Individual attributes of a structure can be initialized using dot notation  The initializers can be in any order struct student s2 = {.last = "Doe",.first = “Jane” }; struct student s2 = {.last = "Doe",.first = “Jane” };

19  We will look at an example that enters and prints student data  The student structure is declared  A student variable is defined  The user is requested to enter values for the structure attributes  The student data is printed

20 #include "stdio.h" const int MAXNAME = 10; // Student structure struct student { int id; char first[MAXNAME]; char last[MAXNAME]; float gpa; }; // Forward Declarations void printStudent(struct student st); #include "stdio.h" const int MAXNAME = 10; // Student structure struct student { int id; char first[MAXNAME]; char last[MAXNAME]; float gpa; }; // Forward Declarations void printStudent(struct student st); the student structure declares the student structure

21 int main() { struct student s1; printf("Enter ID: "); scanf("%d",&s1.id); while(getchar() != '\n'); printf("Enter first name: "); gets(s1.first); printf("Enter last name: "); gets(s1.last); printf("Enter GPA: "); scanf("%f",&s1.gpa); printStudent(s1); return 0; } int main() { struct student s1; printf("Enter ID: "); scanf("%d",&s1.id); while(getchar() != '\n'); printf("Enter first name: "); gets(s1.first); printf("Enter last name: "); gets(s1.last); printf("Enter GPA: "); scanf("%f",&s1.gpa); printStudent(s1); return 0; } note the important precedence here, as (&s1).id would make little sense note the important precedence here, as (&s1).id would make little sense the one and only student define a student variable and enter data clear the input buffer these variables are strings (char *) so we don’t need the address operator

22 void printStudent(struct student st) { printf("\n%d %s %s GPA = %.2f\n", st.id, st.first, st.last, st.gpa); } void printStudent(struct student st) { printf("\n%d %s %s GPA = %.2f\n", st.id, st.first, st.last, st.gpa); } passed by value and finally print the student data

23  Structures can be used as function parameters and arguments  In the same way as any other variable  Parameter passing is pass by value ▪ Structure variables are not pointers ▪ Unlike array variables  When a structure is passed to a function the parameter is a copy of the original  Even if the original structure contained arrays!

24  Declaring student variables with the keyword struct is somewhat verbose  It would be nicer if we could just declare a variable of type student  The typedef keyword allows a programmer to use their own name for a type  Somewhat similarly to #define  It can be used to name a struct

25  This allows student structures to be declared using just the type name student typedef struct { int id; char first[MAXNAME]; char last[MAXNAME]; float gpa; } student; typedef struct { int id; char first[MAXNAME]; char last[MAXNAME]; float gpa; } student; tag omitted an alias for the struct defined above

26  It is possible to create arrays of structures  They are declared like any other kind of array ▪ e.g. struct student class[100];  Individual elements are also accessed like any other array  struct attributes are accessed with dot notation  Let's say we want to find the first name of the student with index 15 ▪ class[15].first not class.first[15]...

27  Unlike arrays one structure can be assigned to another  Think of the assignment as copying the bits that represent the RH struct into the LH struct struct student s1 = {1234, "Peter", "Parker", 3.67}; struct student s2; s2 = s1; struct student s1 = {1234, "Peter", "Parker", 3.67}; struct student s2; s2 = s1; 1234Peter\0Parker 3.67 s1 s2 1234Peter\0Parker 3.67

28  Let’s make the example more complex  It isn’t realistic to just record GPA  GPA is calculated from the grades that a student receives for courses  Create a simple course structure  Department (like CMPT)  Number (like 130)  Grade (A+, A, and so on)

29 #include "stdio.h" const int MAXNAME = 10; const int MAXCOURSES = 20; const int DEPTLEN = 5; const int MAXFILENAME = 20; const int GRADELEN = 2; // Course structure typedef struct { char dept[DEPTLEN]; int number; char grade[GRADELEN]; }course; #include "stdio.h" const int MAXNAME = 10; const int MAXCOURSES = 20; const int DEPTLEN = 5; const int MAXFILENAME = 20; const int GRADELEN = 2; // Course structure typedef struct { char dept[DEPTLEN]; int number; char grade[GRADELEN]; }course; here is the course structure using typedef typedef struct { int id; char first[MAXNAME]; char last[MAXNAME]; course grades[MAXCOURSES]; int coursesTaken; } student; typedef struct { int id; char first[MAXNAME]; char last[MAXNAME]; course grades[MAXCOURSES]; int coursesTaken; } student; it’s an array of courses! it is perfectly OK to nest structures and to make arrays of structures

30 float gpa(student st) { float result= 0; for(int i=0; i < st.coursesTaken; i++){ if(strcmp(st.grades[i].grade, "A") == 0) result += 4; else if(strcmp(st.grades[i].grade, "B") == 0) result += 3; else if(strcmp(st.grades[i].grade, "C") == 0) result += 2; else if(strcmp(st.grades[i].grade, "D") == 0) result += 1; else result += 0; } return result / st.coursesTaken; } float gpa(student st) { float result= 0; for(int i=0; i < st.coursesTaken; i++){ if(strcmp(st.grades[i].grade, "A") == 0) result += 4; else if(strcmp(st.grades[i].grade, "B") == 0) result += 3; else if(strcmp(st.grades[i].grade, "C") == 0) result += 2; else if(strcmp(st.grades[i].grade, "D") == 0) result += 1; else result += 0; } return result / st.coursesTaken; } now we need a function to calculate GPA grades[i] is a course which contains a grade variable you can imagine that this would really include A+, A-,... its a string so can’t use ==

31 void printStudent(student st) { printf("\n%d %s %s\n", st.id, st.first, st.last); // Print list of courses taken for(int i=0; i < st.coursesTaken; i++){ printf("%-4s %d: %s\n", st.grades[i].dept, st.grades[i].number, st.grades[i].grade); } printf("GPA: %.2f\n", gpa(st)); } void printStudent(student st) { printf("\n%d %s %s\n", st.id, st.first, st.last); // Print list of courses taken for(int i=0; i < st.coursesTaken; i++){ printf("%-4s %d: %s\n", st.grades[i].dept, st.grades[i].number, st.grades[i].grade); } printf("GPA: %.2f\n", gpa(st)); } we also need a new function to print student data prints the result of calling the gpa function

32  At the moment we can calculate GPA and print student data  But, imagining this is part of a larger system, we need a way get data into the students  It would be useful to read student data from a file  This brings up some issues ▪ What will the file look like? ▪ How can we write a function to read data into a structure defined outside the function?

33  We need a format for the student files  The main thing is to make some rules and then ensure that they are followed  Let’s assume that a file contains the data for a single student  The first line contains the student’s ID and name  Subsequent lines contain courses and grades  The number of courses taken can be derived from the number of course lines

34 void readStudent(student* pst) { FILE* fp; int courses = 0; char fname[MAXFILENAME]; printf("Enter a file name: "); gets(fname); // Open file while((fp = fopen(fname, "r")) == NULL){ printf("Try again, q to quit: "); gets(fname); if(strcmp(fname, "q") == 0){ exit(1); } void readStudent(student* pst) { FILE* fp; int courses = 0; char fname[MAXFILENAME]; printf("Enter a file name: "); gets(fname); // Open file while((fp = fopen(fname, "r")) == NULL){ printf("Try again, q to quit: "); gets(fname); if(strcmp(fname, "q") == 0){ exit(1); } finally we will write a function to read student data from a file prompts user to enter an existing file name its a pointer because we need the address of the student we want to store data in

35 void readStudent(student* pst) { //... // Read student data fscanf(fp, "%d%s%s", &pst->id, pst->first, pst->last); while(fscanf(fp, "%s%d%s", pst->grades[courses].dept, &pst->grades[courses].number, pst->grades[courses].grade) == 3) { courses++; } pst->coursesTaken = courses; printf("courses = %d\n", courses); } void readStudent(student* pst) { //... // Read student data fscanf(fp, "%d%s%s", &pst->id, pst->first, pst->last); while(fscanf(fp, "%s%d%s", pst->grades[courses].dept, &pst->grades[courses].number, pst->grades[courses].grade) == 3) { courses++; } pst->coursesTaken = courses; printf("courses = %d\n", courses); } now read the data from the file sets number of courses expects an int, and two strings checks that three values were read accesses course attributes an int

36 int main() { student st1; readStudent(&st1); printStudent(st1); return 0; } int main() { student st1; readStudent(&st1); printStudent(st1); return 0; } here is the main function passing the address of the structure sample output

37  The file reading program is not very robust  It will read incorrect data from a file that is not in the right format ▪ Although it does illustrate the use of fscanf  One solution would be to check the number and types of values on each line  And reject the file if they were incorrect  This is hard to do with fscanf as it ignores whitespace

38  It is common to create pointers to structures  In the example this was done to change the variable passed to the read function's parameter  It also saves time and storage to pass structures to functions via pointers ▪ Particularly if the structure is large  Structures may also be function return values  Returning structures and passing structures as parameters was not allowed in older C compilers

39  Consider this  This fails to compile  Because the dot operator has precedence over the dereference operator ▪ The statement is therefore attempting to dereference an integer variable!  Here is a corrected version  This is ugly, and easy to get wrong  Therefore the equivalent -> operator was created *pst.id = 123; //pst is a student* (*pst).id = 123; pst->id = 123;

40  A structure can contain pointers to arrays or other structures  If this is desired, care must be taken to ensure that memory is allocated to such pointers  Otherwise data might be assigned to a pointer that has not been allocated storage  In short – be careful!

41  Since we've talked about it a lot here is a (not the) definition for the FILE struct typedef struct { char *fpos; //position of file pointer void *base; // Pointer to the base of the file unsigned short handle; // File handle short flags; // Flags short unget; // 1-byte buffer for ungetc unsigned long alloc; // Bytes allocated for the file unsigned short buffincrement; // Byte allocation } FILE; typedef struct { char *fpos; //position of file pointer void *base; // Pointer to the base of the file unsigned short handle; // File handle short flags; // Flags short unget; // 1-byte buffer for ungetc unsigned long alloc; // Bytes allocated for the file unsigned short buffincrement; // Byte allocation } FILE;


Download ppt " Complex data types  Structures  Defined types  Structures and functions  Structures and pointers."

Similar presentations


Ads by Google