Previous: 5. Problem Solving with Computers
Next: 7. Subprograms
6 Data Structures
Data elements processed by a computer are not limited to characters and numerals. In many applications, a computer may process more complicated data, e.g., customer records, student examination scores, images, and videos. In this chapter, we will discuss other data abstraction and their constructs in C programming language.
6.1 Various Views of an Entity
An entity is an object with certain attributes. For example, a person is an entity who has name, birth date, sex, weight, height, address, phone number, occupation, etc. In a computer, it is difficult, if it is not possible, to fully describe all attributes and features of a person. For a company, it is concerned a person's personnel data, such as name, identification number, employee number, birth date, address, phone, working department, salary, etc. For a police record, a person is recorded his name, identification number, birth date, weight, height, hair color, eye color, etc. For a school, it may be concerned student's name, identification number, department major, courses taken, and grades of those courses. Therefore, an entity may be viewed differently according to the role it plays in a problem.
A programming language usually provides various ways of data representation to represent different views of an entity. The other way around, a view of an entity may be represented in a program using different data representations. We will use an abstract entity called stack to explain the point.
A stack can be think of as a container that elements are inserted and removed in the last in first out order. Like a set of numbers, it has addition, subtraction, multiplication, and division operations applied to its elements. A stack is at the empty state initially. Its elements can be of a specific data type such as integers, floating point numbers, or student records. When elements are placed to a stack, the last element is called the top element. A stack has the following operations:
is_empty: check whether the stack is empty,
top: get the element at the top of the stack,
push: place an element to the top of the stack, and
pop: get the top element and remove the top element from the stack.
Stacks are considered as a data abstraction that specifies a conceptual entity that are used in many computer applications. To implement a data abstraction in a program, we need to represent that abstraction using some kind of data structures supported in a programming language. We will continue to introduce more data structures in C programming language.
C supports a number of structured data types: enumerated tags, structures, and unions. These data types are used to represent structural data in different ways.
Enumerated Tags
Enumeration is a way to define a list of named constants. The syntax of enumeration is:
enum identifier {enumeratorList} variable; |
where identifier is the name of an enumeration and it is optional and enumeratorList is a list of identifiers that may be assigned values. An enumeration should appears as variable declaration. Consider the following examples of enumeration:
1 2 3 4 |
enum weekday {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; enum month {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; enum escapes {Bell='\a', Tab='\t', Newline='\n'}; enum {red=2, green=4, blue=6, yellow, purple=2, orange}; |
Line 1 specifies a list of weekdays without assigned values. The default values are Sun is 0, Mon is 1, Tue is 2, Wed is 3, Thu is 4, Fri is 5, and Sat is 6. In Line 2, Jan is assigned to 1, and the subsequent names are assigned values as Feb to be 2, Mar to be 3, and, finally, Dec to 12. Line 3 shows that the values of an enumeration can be characters as well. Line 4 specifies integer values to a set of colors. The value of color yellow is 7 which is the integer following color blue. Color purple is assigned to 2 which has the same value of color red 2 and the value of color orange will be 3 which is the integer following 2.
It is possible to declared a variable of enumeration type. However, C programming language does not check whether the value of that variable is in the range of the enumerated tags. For example, in the following program segment, w1 and w2 are declared as two variables of enum weekday.
enum weekday {Sun, Mon, Tue, Wed, Thu, Fri, Sat} w1; enum weekday w2; w1 = Sat; w2 = 8; |
Variable w1 and w2 are simply treated as an integer variables. Variable w2 is assigned value 8 which is not in the value range of enum weekday. Variable w1 is assigned the value of Sat, 6.
Structures
Structure data types are used to represent a collection of elements of different data types. The syntax of structure is as below:
struct identifier {type fieldName1; type fieldName2; ¼} variable; |
where identifier is the name of a structure and it is optional. A structure may consists of as many fields as specified in the curly brackets. Also, variables can be declared as a struct type. For example, the following declaration declare structure date of three fields and variable birthday is declared of type struct date.
1 2 3 4 5 6 7 |
struct date {int day; int month; int year;} birthday; ¡@ birthday.day = 20; birthday.month = 10; birthday.year = 1998; |
Lines 5 to 7 show that the field of a structure is accessed through a variable of the structure following a '.' and a field name.
Structures can be used to define a new data type as well. Program student_average.c shows the usage of structure data type of representing a student's record including identification number, name, scores of six courses and the average score.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include <stdio.h> typedef struct { char id[10]; char first_name[20]; char last_name[20]; int score[6]; float average; } student; int main(void) { student stu; char *course[6] = {"C Programming for Engineering ", "Analytical Genometry and Calculus", "Mechanics ", "Mechanics Laboratory ", "General Chemistry ", "General Chemistry Laboratory " }; int creditHour[6] = {3, 3, 3, 1, 3, 1}; int i, totalScore, totalCreditHour; printf("Enter Student ID: "); scanf("%s", stu.id); printf("Enter Student Name (frist_name last_name): "); scanf("%s %s", stu.first_name, stu.last_name); printf("Enter Scores for all Courses\n"); for (i = 0; i < 6; i++) { printf("%s ", course[i]); scanf("%d", &stu.score[i]); } printf("\nStudent Id: %s Student Name: %s %s\n", stu.id, stu.first_name, stu.last_name); totalScore = 0; totalCreditHour = 0; printf("Course Name Score\n"); for (i = 0; i < 6; i++) { printf("%s: %d\n", course[i], stu.score[i]); totalScore += stu.score[i] * creditHour[i]; totalCreditHour += creditHour[i]; } stu.average = (float) totalScore / totalCreditHour; printf("Average: %5.2f\n", stu.average); return 0; } |
Lines 3 to 8 declare a new data type called student. Lines 12 to 17 specify the names of six courses. Line 18 specifies the number of credit hours of the six courses. The program reads student's id number and name, scores of six courses. Lines 21 to 29 read student's id, name, and score. The score report is then produced in the rest of the program. Lines 41 to 46 computes the average score. A sample output is given as below:
Enter Student ID:
D0565999 |
The memory space occupied by a structure can be tested using sizeof() function. For example, program size_of_student.c illustrates the size of struct student and how field elements are allocated in memory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <stdio.h>
|
The following output shows that an instance of struct student takes 60 bytes. The instance starts at addresss 0X22FF40. Field stu.id occupies 10 bytes, from 0X22FF40 to 0X22FF49 and stu.name occupies 20 bytes, from 0X22FF4A to 0X22FF5D. Field stu.score is an integer array of six elements, i.e., 24 bytes, and each integer takes four bytes. Since an integer data must start with the beginning of a word, two bytes of memory space, 0X22FF5E and 0X22FF5F, are not used. The starting address of stu.score[0] becomes 0X22FF60. Finally, stu.average is a floating number which takes four bytes from 0X22FF78 to 0X22FF7B. As a result, the memory space for student stu starts from address 0X22FF40 to 0X22FF7B, total of 60 bytes.
Size of student:
60 |
Structures can be nested, i.e., a structure inside another structure. In program nested_structure.c, student's name is further divided into last name and first name which is represented as a structure (Lines 5 to 8). Access to fields of a nested structure is through multiple dotted expression, e.g., stu.name.last and stu.name.first.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <stdio.h>
|
A sample run of the program is shown below:
Enter Student's Fisrt
Name: John |
Unions
Type union in C programming language is a data type to represent various data fields but sharing the same location. The syntax of union is similar to that of struct:
union identifier {type fieldName1; type fieldName2; ¼} variable; |
Consider program union_type.c. Vairable num is declared as a union number_union type of three fields num.integer_num, num.unsigned_num, and num.float_num of integer, unsigned, and float type, respectively. Initially, these fields are set to 0. Only num.integer.num is modified to -1 (Line 15).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <stdio.h> ¡@ return 0; } |
However, the output from Lines 16 to 18 show that num.unsigned_num and num.float_num are also modified because these three fields share the same location as indicated by the output from Lines 20 to 22.
integer: -1 |
The fields of a union type may be data types of various size. In program union_sizeof.c, union number_union has four fields, each of the fields is of type char, int, float, or double. Function sizeof() is called with an expression, i.e., a variable or a variable with field access.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <stdio.h> ¡@ return 0; } |
The output of Line 12 shows the size of union number_union is eight bytes which is the largest memory space required of each of the four fields, num.double_num.
size of num: 8 |
Previous: 5. Problem Solving with Computers
Next: 7. Subprograms