1. Overview
The C language allows users to specify a data structure composed of different types of data combined into a whole for referencing. The data combined into this whole are interrelated. Such a data structure is called a structure, which is equivalent to a record in other high-level languages.
The general form of declaring a structure type is as follows:
struct 结构体名
{成员列表};
The structure name is used as the marker of the structure type, also called the structure tag. Inside the braces are the members of the structure, which together form the structure. Each member should have a type declaration, for example:
Type name member name;
The member list can also be called the field list, and the first member is also called a field in the structure. Member naming rules are the same as variable naming rules.
struct student
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
2. Methods for Defining Structure Type Variables
What was specified earlier is only a structure type, which is like a model but contains no specific data, and the system does not allocate actual memory units for it. In order to use structure type data in a program, variables of the structure type should be defined and specific data stored in them. The following three methods can be used to define structure type variables.
(1) Declare the structure type first, then define variable names
As above, a structure type struct student has been defined, and it can be used to define variables. For example:
struct student{ //结构体类型名
...
...
...
}student1, student2 //结构体变量名
student1 and student2 are defined as variables of type struct student.
After defining structure variables, the system allocates memory units for them. For example, student1 and student2 each occupy 59 bytes in memory.
Note that the difference between defining a variable as a standard type (basic data type) and as a structure type is that the latter requires not only specifying the variable as a structure type, but also specifying a particular structure type (for example, struct student type), because many specific structure types can be defined. When defining a variable as an integer, you only need to specify it as int.
(2) Define variables while declaring the type
For example:
struct student
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}student1, student2;
Its effect is the same as the first method, that is, defining two struct student type variables student1 and student2. The general form of this definition is:
struct 结构体名
{
成员表列
}变量名表列;
(3) Directly define structure type variables
Its general form is:
struct
{
成员表列
}变量名表列;
That is, the structure name does not appear.
Regarding structure types, a few points should be explained:
- a. Type and variable are different concepts and should not be confused. You can only assign values to, access, or perform operations on variables, not on a type. At compile time, no space is allocated for types; space is allocated only for variables.
- b. Members (i.e., fields) of a structure can be used independently, and their role and status are equivalent to ordinary variables.
-
c. A member can also be a structure variable. For example:
struct date // 声明一个结构体类型 { int month; int day; int year; } struct student { int num; char name[20]; char sex; int age; struct date birthday; char addr[30]; }student1, student2;First declare a struct date type, which represents "date" and includes three members: month, day, year. Then when declaring the struct student type, specify the member birthday as type struct date.
- d. Member names can be the same as variable names in the program, but they do not represent the same object.
3. Referencing Structure Variables
(1) A structure variable cannot be input or output as a whole.
Only each member in a structure variable can be input or output separately. The way to reference a member of a structure variable is:
Struct variable name.member name
For example, student1.num represents the num member in the student1 variable, that is, the num item of student1. You can assign a value to a member of a variable. For example: student1.num = 10010;
.The dot is the member (component) operator. It has the highest precedence among all operators, so student1.num can be treated as a whole. The effect of the above assignment statement is to assign the integer 10010 to the member num of the student1 variable.
(2) If a member itself is a structure type, multiple member operators are needed to find the lowest-level member level by level. Only the lowest-level member can be assigned, accessed, or operated on.
For example: the members of structure variable student1 can be accessed like this:
student1.num student1.birthday.month
Note that student1.birthday cannot be used to access the member birthday in the student1 variable, because birthday itself is a structure variable.
((3) Members of a structure variable can perform various operations like ordinary variables (the operations allowed are determined by their type).
student2.score = student1.score; sum = student1.score + student2.score; student1.age ++; ++ student1.age;
Since.The . operator has the highest precedence, so student1.age++ performs a self-increment operation on student1.age, rather than first performing self-increment on age.
(4) You can reference the address of a member of a structure variable. You can also reference the address of a structure variable. For example:
scanf("%d", &student1.num);// 输入 student1.num 的值
printf("%o", &student1);// 输出 student1 的首地址
But you cannot use the following statement to read an entire structure variable, for example:
scanf("%d,%s,%c,%d,%f,%s", &student1);
The address of a structure variable is mainly used as a function parameter to pass the address of the structure.
4. Initialization of Structure Variables
Like variables of other types, structure variables can be given initial values at the time of definition.Example
5. Structure Arrays
A structure variable can store a set of data (such as a student's student number, name, grades, etc.). If there are 10 students' data to be processed in calculations, obviously an array should be used, which is a structure array. The difference between a structure array and the numeric arrays introduced before is that each array element is a structure type data, and they each include various member (component) items.
5.1 Defining Structure Arrays
Similar to defining structure variables, you only need to specify it as an array.
struct student
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
struct student stu[3];
The above defines an array stu whose elements are of type struct student, and the array has 3 elements. You can also directly define a structure array. For example:
struct student
{
int num;
....
}stu[3];
或
struct
{
int num;
...
}stu[3];
5.2 Initialization of Structure Arrays
Like other types of arrays, structure arrays can be initialized, for example:
struct student
{
int mum;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu[3] = {{10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"},
{10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"},
{10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"}};
When defining the array stu, the number of elements can be omitted, that is, written in the following form:
stu[] = {{...},{...},{...}};
At compile time, the system determines the number of array elements based on the number of structure constants given as initial values.
Of course, array initialization can also use the following form:
struct student
{
int num;
...
};
struct student stu[] = {{...},{...},{...}};
That is, first declare the structure type, then define the array as that structure type, and initialize when defining the array.
From the above, it can be seen that the general form of structure array initialization is to add after defining the array:
5.3 Application Example of Structure Arrays
The following example illustrates the definition and referencing of structure arrays.
Example
The running result is as follows:
LI Li Fun Zhang Zhang Fun Li Fun Zhang Li Li: 3 Zhang: 3 Fun: 3
6. Pointers to Structure Type Data
A pointer to a structure variable is the starting address of the memory segment occupied by that variable. A pointer variable can be set to point to a structure variable, in which case the value of the pointer variable is the starting address of the structure variable. A pointer variable can also be used to point to an element in a structure array.
6.1 Pointer to a Structure Variable
Application of a pointer to a structure variable:
Example
.num or stu
.name as a function actual argument to pass the actual argument value to the formal parameter. The usage is the same as using an ordinary variable as an actual argument, and it belongs to the pass-by-value method. It should be noted that the types of the actual parameter and the formal parameter must be consistent.
NO. :89101 name: Li Lin sex:M score:89.500000 NO. :89101 name: Li Lin sex:M score:89.500000
It can be seen that the output of the two printf statements is the same.
In C language, for convenience and intuitiveness, (*p).num can be replaced by p->num. It represents the member num in the structure variable *p (i.e., the structure variable pointed to by p). Similarly, (*p).name is equivalent to p->name.
That is, the following three forms are equivalent:
- a. structure variable.member name
- b. (*p).member name
- c. p-> member name
The output items of the last printf function above can be rewritten as:
printf("NO. :%ld\nname: %s\nsex:%c\nscore:%f\n",p->num, p->name, p->sex, p->score);
where->is called the arrow operator.
Analyze the following operators:
- p -> n gets the value of member n in the structure variable pointed to by p.
- p -> n ++ gets the value of member n in the structure variable pointed to by p, and after using the value, increments it by 1.
- ++p -> n gets the value of member n in the structure variable pointed to by p and increments it by 1 (increment first).
6.2 Pointer to a Structure Array
As introduced earlier, pointers and pointer variables can be used to point to arrays or array elements. Similarly, pointer variables can also be used to point to arrays of structures and their elements.
Application of a pointer to an array of structures.
Example
The running result is as follows:
No. name sex age 10101 Li Lin M 18 10102 Zhang Fun M 19 10103 Wang Min F 20
Note the following two points:
(1) If the initial value of p is stu, i.e., it points to the first element, then after p + 1, it points to the starting address of the next element. For example:
(++p) -> num first increments p by 1, then obtains the value of the num member in the element it points to (i.e., 10102).
(p++) ->num first obtains the value of p->num (i.e., 10101), then increments p by 1, pointing to stu
Note the difference between the above two.
(2) The program has defined the pointer p as a variable pointing to data of type struct student. It can only point to data of type struct student (the value of p is the starting address of an element of the stu array), and cannot point to a member within an element of the stu array (i.e., the address of p cannot be a member address). For example, the following is incorrect:
p = &stu[1].name
An error will occur at compile time. Never think that since p stores an address, any address can be assigned to it. If the address types are different, a forced type conversion can be used. For example:
p = (struct student *)&stu[1].name;
At this point, the starting address of the name member of the stu
6.3 Using Structure Variables and Pointers to Structures as Function Parameters
There are three methods for passing the value of a structure variable to another function:
- (1) Use a member of a structure variable as an argument. For example, use stu
- (2) Use a structure variable as a parameter. Older versions of the C system did not allow a structure variable to be used as an actual argument; ANSI C removed this restriction. However, when a structure variable is used as an actual argument, the pass-by-value method is adopted, and all the memory units occupied by the structure variable are passed to the formal parameter in sequence. The formal parameter must also be a structure variable of the same type. During the function call, the formal parameter also occupies memory units. This passing method has a large overhead in both space and time. If the structure is very large, the overhead is considerable. In addition, because the pass-by-value method is used, if the value of the formal parameter (also a structure variable) is changed during execution of the called function, that value cannot be returned to the calling function, which often causes inconvenience. Therefore, this method is generally used less.
- (3) Use a pointer to a structure variable (or array) as the actual argument, and pass the address of the structure variable (or array) to the formal parameter.
Using a structure variable as a function parameter.
Example
Change the above to use a pointer to a structure variable as the actual argument.
Example
7. Handling Linked Lists with Pointers
7.1 Linked List Overview
A linked list is a common and important data structure. It is a structure that performs dynamic storage allocation.
A linked list has a head pointer variable, which stores an address that points to an element. Each element in the linked list is called a node. Each node should include two parts: one is the actual data needed by the user, and the other is the address of the next node. It can be seen that the head pointer head points to the first element, and the first element points to the second element, ... until the last element. This element no longer points to other elements; it is called the tail of the list, and its address part contains a NULL (meaning an empty address), and the linked list ends here.
It can be seen that the elements in a linked list need not be stored contiguously in memory. To find a certain element, you must first find the previous element, and only then can you find the next element based on the address of the next element it provides. Without the head pointer head, the entire linked list cannot be accessed.
It can be seen that this kind of linked list data structure must be implemented using pointer variables. That is, a node should contain a pointer variable to store the address of the next node.
Earlier we introduced structure variables. Using them as nodes in a linked list is most suitable. A structure variable contains several members; these members can be numeric types, character types, array types, or pointer types. We use this pointer-type member to store the address of the next node. For example, we can design such a structure type:
struct student
{
int num;
float score;
struct student *next;
};
Among them, the members num and score are used to store useful data in the node (the data needed by the user). next is a pointer-type member, which points to data of type struct student (this is the structure type that contains next). A pointer-type member can point to structure data of other types, and can also point to data of the structure type in which it resides. Now next is a member of the struct student type, and it points to data of the struct student type. In this way, a linked list can be established.
Please note: merely defining a struct student type does not actually allocate storage space; memory units are allocated only when variables are defined.
7.2 Simple Linked List
The following example illustrates how to create and output a simple linked list:
Example
Running result:
99101 89.5 99103 90.0 99107 85.0
7.3 Functions Needed for Processing Dynamic Linked Lists
(1) malloc function
void *malloc(unsigned int size);
Its function is to allocate a contiguous space of length size in the dynamic storage area of memory. The value of this function (i.e., the return value) is a pointer to the starting address of the allocated space (base type void). If this function fails to execute successfully (for example, insufficient memory space), it returns the null pointer NULL.
(2) calloc function
void *calloc(unsigned n, unsigned size);
Its function is to allocate n contiguous spaces of length size in the dynamic storage area of memory. The function returns a pointer to the starting address of the allocated space; if the allocation is unsuccessful, it returns NULL. The calloc function can be used to allocate dynamic storage space for a one-dimensional array, where n is the number of array elements and each element has length size.
(3) free function
void free(void *p);
Its function is to release the memory area pointed to by p, so that this part of the memory area can be used by other variables. p is the value returned by the last call to the calloc or malloc function. The free function has no return value. Please note: the malloc and calloc functions provided by earlier C versions returned pointers to character data. The malloc and calloc functions provided by ANSI C are specified as void * type.
7.4 Creating a Dynamic Linked List
The so-called creating a dynamic linked list means building a linked list from scratch during program execution, that is, opening up nodes one by one, inputting data for each node, and establishing the front-to-back linking relationship.
Example
The following are various operations on the linked list
Print the linked list:
void printlist(struct student *head)
{
struct student *p;
p = head;
if(head != NULL)
{
do
{
printf("num=%d score=%5.2f\n", p->num, p->score);
p = p->next;
} while (p != NULL);
}
/* while(p -> next != NULL)
{
printf("num=%d score=%f\n", p->num, p->score);
p = p->next;
}*/
}Delete a node:struct student *delNode(struct student *head, int num)
{
printf("delNode.\n");
struct student *p1, *p2;
if(head == NULL)
{
printf("The List is NULL.\n");
}
else
{
p1 = head;
while(p1->next != NULL && p1->num != num)
{
p2 = p1;
p1 = p1->next;
}
if(p1->num == num)
{
if(p1 == head)
head = p1->next;
else
p2->next = p1->next;
}
else
printf("Can not find list num.\n");
}
return head;
}
Update a node:
struct student *update(struct student *head, int index, int num, float score)
{
printf("update.\n");
struct student *p;
if(head == NULL)
{
printf("The List is NULL.\n");
}
else
{
p = head;
while(p->next != NULL && p->num != index)
{
p = p->next;
}
if(p->num == index)
{
p->num = num;
p->score = score;
}
else
printf("Can not find list index.\n");
}
return head;
}
Add a node:
struct student *add(struct student *head, int index, int num, float score)
{
printf("add.\n");
struct student *p1, *p2, *p3;
if(head == NULL)
{
printf("The List is NULL.\n");
}
else
{
p1 = p2 = head;
while(p1->next != NULL && p1->num != index)
{
p1 = p1->next;
p2 = p1;
}
if(p1->num == index)
{
p3 = (struct student *)malloc(LEN);
p3->num = num;
p3->score = score;
if(p2->next == NULL)
{
p2->next = p3;
p3->next = NULL;
}
else
{
p3->next = p2->next;
p2->next = p3;
}
}
else
printf("Can not find list index.\n");
}
return head;
}
Original link: http://www.cnblogs.com/qkhhxkj/archive/2011/06/28/2091818.html
Reference book: The chapter on structure types in Mr. Tan Haoqiang's book *C Programming*.