620 likes | 685 Views
Structures Etter Chapter 7. In engineering, we need to process or visualize data Some of you have done Matlab simulations and visualizations Sometimes we work with a single piece of data E.g. the temperature reading at this point in time. But usually we’d work with a large set of data.
E N D
StructuresEtter Chapter 7 • In engineering, we need to process or visualize data • Some of you have done Matlab simulations and visualizations • Sometimes we work with a single piece of data • E.g. the temperature reading at this point in time. • But usually we’d work with a large set of data. • E.g. the temperature reading every minute for the last 8 hours. • This works out to 480 pieces of data.
StructuresPages 327 to 332 • In Lecture 8, we solved this problem by using arrays. • BUT arrays can only store data of a single type! • E.g. you can’t store strings in this array: double mydata[1024];
Structures • Fortunately C gives us a way of representing related information of different types, in a “structure.” • E.g. hurricanes have names, intensities and categories. • Name: This is a string. • Intensity: Integer. • Category: Intger.
Structures struct hurricane { char name[10]; int year, category; }; • “name”, “year” and “category” are called “members” of the structure “hurricane” • This statement declares a new type! • IT DOES NOT DECLARE A NEW VARIABLE! This “;” is very important and often forgotten!
Self Help Questions • What are the differences between a “variable” and a “type”?
Answer • A “type” tells C what the variable is. E.g. “int” is a type. “double” is a type. After declaring our structure “hurricane”, “struct hurricane” is also a type! Types do not occupy memory and cannot store values. To declare a variable, we always use “type varname;”. So to declare an integer variable, we use “int xl;”. This tells C that “x1” is a variable of type “int”. Variables occupy memory and can be assigned values.
Structure Variables • To declare a new variable of the “hurricane” type, we do: struct hurricane h1; ? name h1 ? year ? category
Structure Variables • You can declare multiple variables of this type: struct hurricane h1, my_hurricane; ? name ? name h1 my_hurricane ? year ? year ? category ? category
Structure Variables • You can also initialize the members of a structure variable. struct hurricane h1 = {“Camille”, 1969, 5}; Camille name h1 1969 year 5 category
Structure Variables • Alternatively you can initialize the members using C statements: struct hurricane h1; h1.name = “Camille”; h1.year = 1969; h1.category = 5; • Notice how we used the “.” operator to access members of a structure variable!
Structure Example • We can use scanf or fscanf statements to write to structure variable members. • We can use printf or fprintf to read them. • We will now write a program that reads hurricane information from a file, and prints them out.
Structure Example #include <stdio.h> #define FILENAME "storms2.txt" struct hurricane { char name[10]; int year, category; };
Structure Example int main(void) { /* Declare variables */ struct hurricane h1; FILE *storms; storms = fopen(FILENAME, "r"); if(storms == NULL) printf("Error opening data file.\n");
Structure Example else { while(fscanf(storms, "%s %d %d", h1.name, &h1.year, &h1.category) == 3) { printf("Hurricane: %s\n", h1.name); printf("Year: %d, Category: %d\n", h1.year, h1.category); } fclose(storms); } /* else */ return 0; }
Self Help Questions • In the fscanf statement: fscanf(storms, "%s %d %d", h1.name, &h1.year, &h1.category) - h1.year and h1.category are both passed to fscanf with “&”, but not h1.name. Why?
ANSWERS • The “name” member of “hurricane” is defined as char name[10]; struct hurricane { char name[10]; int year, category; };
ANSWERS • This makes “name” an array of 10 characters. • In an array: • The name of the array is a pointer to the first item of the array. • “fscanf” expects pointers to the variable arguments. E.g.: fscanf(fptr, “%d”, &a); • This is so that fscanf can return the values read using these variables. • So we use “&” to get the address of the variable.
ANSWERS • Since “name” is already a pointer to the first item of the “name” array, there is no need to use “&”. We can just pass in “name” instead of “&name”. • Further question: What does &name give you?
Computations with Structures • We use the “.” operator to access individual members of a structure variable: h1.name=“Hazel”; • If we use the structure variable’s name without the “.” operator, then we are accessing the entire array.
Computations with Structures • You can do assignments with structures: • Given two structures “h1” and “h2”. • To make h2 equal to h1, just do: h2 = h1;
Computation with Structures • E.g. struct hurricane h1 ={“Hazel”, 1954, 4}, h2; ……… h2 = h1; Initially: ? name Hazel name h2 h1 ? year 1954 year ? category 4 category
Computation with Structures • E.g. • struct hurricane h1 ={“Hazel”, 1954, 4}, h2; • ……… • h2 = h1; After h2=h1: Hazel name Hazel name h2 h1 1954 year 1954 year 4 category 4 category
Computation with Structures • Other operations like “+”, “-”, “*”, “/”, “>”, “<“, “>=“, “==“ etc. can only be performed on individual structure variable members. E.g. h1.category += 1; /* Increment */
Computation Example • We will modify our hurricane program to print only the Category 5 hurricanes. • Can just do this by: if(h1.category == 5) /* Print hurricane data */
Computation Example #include <stdio.h> #define FILENAME "storms2.txt" struct hurricane { char name[10]; int year, category; };
Computation Example int main(void) { struct hurricane h1; FILE *storms; storms = fopen(FILENAME, "r"); if(storms == NULL) printf("Error opening data file.\n");
Computation Example else { printf("Category 5 hurricanes\n\n"); while(fscanf(storms, "%s %d %d", h1.name, &h1.year, &h1.category) == 3) if(h1.category == 5) printf("%s\n", h1.name); fclose(storms); } /* else */ }
Passing Structures to FunctionsPages 332 to 334 • Entire structures can be passed into functions. • Structures are passed by value: • Members of the actual arguments are copied into corresponding members of the formal parameters.
Passing Structures to Functions #include <stdio.h> struct hurricane { char name[10]; int year, category; }; void print_struct(struct hurricane my_h) { printf("INSIDE print_struct function\n"); printf("Contents of parameter my_h: %s, %d, %d\n", my_h.name, my_h.year, my_h.category); printf("Address of parameter my_h: %u\n\n", &my_h); } Formal parameter declaration for a structure.
Passing Structures to Functions Declaration for struct variable h1. int main(void) { struct hurricane h1 = {"Hazel", 1954, 4}; printf("\nContents of h1: %s, %d, %d\n", h1.name, h1.year, h1.category); printf("Address of h1: %u\n", &h1); printf("Passing h1 in as argument to print_struct\n\n"); print_struct(h1); } Structure variable is passed in just like any other variable.
Passing Structures by Reference. • Ordinarily, structures are passed by value. • This means that you cannot modify the members of a structure from within a function. • To be able to modify structure members, you must pass in a pointer to the argument, rather than the argument itself.
Passing Structures by ReferenceSelf Help Question • If: • int *ptr declares a pointer to int. • double *ptr declares a pointer to a double. • char *ptr declares a pointer to a char. • How do you: • Declare a pointer to a struct hurricane?
Passing Structures by Reference #include <stdio.h> #include <string.h> /* This program has a function that modifies a structure passed to it */ struct hurricane { char name[10]; int year, category; };
Passing Structures by Reference void modify_structure(struct hurricane *hur) { /* Modify the structure values */ strncpy(hur->name, "Grace", 10); hur->year=1972; hur->category = 5; } Pointer to a struct hurricane. When accessing structure members from a pointer, use “->” instead of “.”.
Passing Structures by Reference int main(void) { struct hurricane h1={"Audrey", 1957, 4}; printf("Contents of h1: %s %d %d\n", h1.name, h1.year, h1.category); printf("\nCalling modify_structure to change the contents of h1.\n\n"); modify_structure(&h1); printf("Contents of h1: %s %d %d\n\n", h1.name, h1.year, h1.category); } Pass in the address of h1, instead of h1 itself.
Passing Structures by Reference • One point to note: • When accessing members of a structure variable, we use the “.” operator. • E.g. struct hurricane my_hurricane; my_hurricane.year=1852;
Passing Structures by Reference • One point to note: • When accessing members of a pointer to a structure variable, we use the “->” operator. • E.g. • struct hurricane *ptr = &my_hurricane; • ptr->year=1952; • “ptr->year” is a shortcut for (*ptr).year;
Returning Structures from Functions. • A function can return whole structures. • To declare a function that returns an int, we do: int myfun1() { … } • To declare a function that returns a char, we do: char myfun2() { … }
Returning Structures from Functions. • To call these functions: char c; int num; num = myfun1(); c = myfun2();
Returning Structures from Functions. • Likewise, to declare a function that returns struct hurricane: struct hurrican myfun3(…) { … } • To call myfun3: struct hurricane my_h; my_h = myfun3();
Example #include <stdio.h> struct tsunami { int mo, da, yr, fatalities; double max_height; char location[20]; }; struct tsunami get_info(void);
Example t1 will temporarily store what the user keys in. struct tsunami get_info(void) { /* Declare variables */ struct tsunami t1; printf("Enter information for tsunami in the following order:\n"); printf("Enter month, day, year, number of deaths:\n"); scanf("%d %d %d %d", &t1.mo, &t1.da, &t1.yr, &t1.fatalities); printf("Enter location (<20 characters.):\n"); scanf("%s", t1.location); return t1; } t1 is returned here.
Example We declare a variable of type struct tsunami, the exact same type as the function get_info. int main(void) { struct tsunami my_t; my_t = get_info(); printf("\nThe information you entered:\n\n"); printf("Date (day/month/year): %d/%d/%d\n", my_t.da, my_t.mo, my_t.yr); printf("Location: %s\n", my_t.location); printf("Fatalities: %d\n\n", my_t.fatalities); return 0; } We call get_info just like any other function.
Arrays of Structures(Pages 334 to 336) • Refresher: • To declare an array of 20 ints: int my_array1[20]; • To declare an array of 20 doubles: double my_array2[20]; • To declare an array of 20 chars: char my_array3[20]; • Question: How do we declare an array of “struct hurricane”?
Array of Structures • Assuming we have already declared “struct hurricane”, do declare an array of 20 “struct hurricane”: struct hurricane my_array4[20];
? ? ? name year category ? ? ? ? ? ? ? ? ? … … … ? ? ? Array of Structures • This creates 20 “struct hurricane” variables, each with: • name • year • category • All values are un-initialized. 0 1 2 3 19
Array of Structures • Refresher: • To access individual ints in my_array1: • myarray1[2] = 5; • To access individual doubles in my_array2: • myarray2[5] = 3.1; • To access individual chars in my_array3: • myarray3[2] = ‘c’; • So: • How to we access individual struct variables?
Array of Structures Answer: my_array4[0].name = “Camille”; my_array4[0].year = 1969; my_array4[0].category = 5;
Example /* Program ch7_4.c */ #include <stdio.h> #define FILENAME "storms2.txt" struct hurricane { char name[10]; int year, category; }; void print_hurricane(struct hurricane h);
Example int main(void) { int max_category=0, k=0, npts; struct hurricane h[100]; FILE *storms; storms = fopen(FILENAME, "r"); if(storms == NULL) printf("Error opening data file.\n"); else { printf("Hurricanes with Maximum Category:\n");