Chapter 7: Structure and Union
Structural Type Definitions and Structural Variables Description In practical problems, a set of data often has different data types. For example, in the student registration form, the name should be a character type; the student number can be integer or a character; the age should be integer; gender should be a character type; the score can be integer or real. It is obvious that this group of data cannot be stored in an array. Because the type and length of each element in the array must be consistent to compile the system processing. In order to solve this problem, another construction data type - "Structure" is given in the C language. It is equivalent to records in other advanced languages. "Structure" is a type of constructor, which is composed of several "members". Each member can be a basic data type or another constructive type. The structure is both a "constructed" data type, then defined it before explaining and use, that is, construct it. The function is defined before the function is explained and called the function. First, the definition of the structure defines a general form of a structure: Struct structure name {member table column}; member table consists of several members, each member is an integral part of the structure. For each member, it must also be described in the form: the type of type indicator member name; the name of the member name should meet the writing rules of the identifier. For example: struct stu {int Num; char name [20]; char sex; float score;}; in this structure definition, the structure is STU, which consists of four members. The first member is NUM, integer variable; the second member is Name, the character array; the third member is SEX, the character variable; the fourth member is Score, real variable. It should be noted that the semicolon after parentheses is indispensable. After the structure is defined, the variable will be performed. Any variable indicating that the structure STU is composed of the above four members. It can be seen that the structure is a complex data type, which is a collection of number of ordered variables that are fixed and type different. Second, the instructions of structural type variables The structural variables have the following three methods. The STU defined above is an example. 1. First define the structure and then explain the structural variable. Such as: struct stu {int num; char name [20]; char sex; float score;}; struct stu boy1, boy2; It is also possible to define a symbol constant to represent a structural type, for example: #define stu struct stustu {int Num; char name [20]; char sex; float score;}; stu boy1, boy2; 2. In defined structure Type of structural variables simultaneously. For example: struct stu {int Num; char name [20]; char sex; float score;} BOY1, BOY2; 3. Direct explanation of structural variables. For example: struct {int Num; char name [20]; char sex; float score;} BOY1, BOY2; third method and second method difference in the third method to save the structure name, directly give Structural variable. The BOY1, BOY2 variables illustrated in three methods have the structure shown in Fig. 7.1. When the BOY1, the BOY2 variable is the STU type, you can assign a value to each member of the two variables. In the above STU structure definition, all members are basic data types or array types. Members can also be a structure that constitutes a nested structure. For example, Figure 7.2 gives another data structure.
The following structure definition can be given as shown in Figure 7.2: struct date {Int Month; Int day; int year;} struct {int num; char name [20]; char sex; struct date birthday; float score;} boy1, boy2; first Define a structure Date, consist of three members of Month, Day (Day), Year (year). When the variable BOY1 and BOY2 are defined, the members BIRTHDAY are illustrated as the DATA structure type. Member names can be interfered with each other in the same name in other variables. The representation of structural variable members often use structural variables in the program, often use it as a whole. In addition to allowing the same type of structural variables to be assigned to each other, including assignment, input, output, calculation, etc., including assignment, input, output, calculation, etc. in addition to the same type of structural variables, including assignment, input, output, calculation, etc. The general form of the structural variable member is: structural variable name. Member name, such as: boy1.num, the first person's school number BOY2.SEX, the second person's gender, if the member itself is a structure, the minimum must be found step by step Level members can be used. For example: Boy1.birdHday.month, the first month of the first person can be used separately in the program, identical to ordinary variables. The assignment of structural variables has been described above, and the assignment of structural variables is assigned to each member. The input statement or assignment statement can be used. [Example 7.1] assigns the structural variable and outputs its value. Main () {struct stu {int Num; char * name; char sex; float score;} BOY1, BOY2; BOY1.NUM = 102; BOY1.NAME = "zhang ping"; printf ("Input Sex and score / n" ); scanf ("% c% f", & boy1.sex, & boy1.score; boy2 = boy1; printf ("number =% d / nname =% s / n", boy2.num, boy2.name; printf ("SEX =% C / NSCORE =% f / n", boy2.sex, boy2.score;} struct stu {int num; char * name; char sex; float score;} BOY1, BOY2; BOY1.NUM = 102; BOY1.NAME = "zhang ping"; Printf ("Input Sex and Score / N"); Scanf ("% C% F", & Boy1.sex, & boy1.score); BOY2 = BOY1; Printf ("Number = % d / nname =% s / n ", boy2.num, boy2.name); Printf (" SEX =% C / NSCORE =% F / N ", Boy2.SEX, BOY2.SCORE); assignment in this program The statement assigns two members for NUM and NAME, and Name is a string pointer variable. Dynamically entered the SEX and Score member values with the Scanf function, and then give BOY2 all members of BOY1. Finally, each member value of BOY2 is output separately. This example shows the assignment, input, and output of structural variables. Initialization of Structure Variable If the structural variable is a global variable or a static variable, it can be initialized to assign it. Initialization assignment cannot be initialized for local or automatic structural variables. [Example 7.2] External structural variable initialization.
Struct stu / * Define structure * / {int Num; char * name; char sex; float score;} BOY2, BOY1 = {102, "zhang ping", 'm', 78.5}; main () {BOY2 = BOY1; Printf ("Number =% D / NNAME =% S / N", Boy2.Num, Boy2.Name); Printf ("SEX =% C / NSCORE =% F / N", Boy2.SEX, Boy2.score; } struct stu {int Num; char * name; char sex; float score;} BOY2, BOY1 = {102, "zhang ping", 'm', 78.5}; main () {boy2 = BOY1; ......} This example In the middle, BOY2, BOY1 is defined as an external structural variable and the BOY1 is initialized. In the main function, the value of BOY1 is given to BOY2, and then output the value of BOY2 members with two PrintF statements. [Example 7.3] Static structural variable initialization. Main () {static struct stu / * Defines static structural variables * / {INT NUM; char * name; char sex; float score;} BOY2, BOY1 = {102, "zhang ping", 'm', 78.5}; boy2 = BOY1; Printf ("Number =% D / NNAME =% S / N", Boy2.Num, Boy2.Name); Printf ("SEX =% C / NSCORE =% F / N", Boy2.sex, BOY2. Score);} static struct stu {int Num; char * name; char sex; float score;} BOY2, BOY1 = {102, "zhang ping", 'm', 78.5}; this example is defined BOY1, BOY2 For static partial structural variables, it can also be assigned to initialization. Elements of the array of structures can also be structural types. It can therefore constitute a structural array. Each element of the structural array is a substructure variable having the same structural type. In practical applications, a population having the same data structure is often used in actual applications. Such as a class of student files, a wage watch of a workshop employee. The definition method of the structural array is similar to the structural variable, simply indicates that it is an array type. For example: struct stu {int Num; char * name; char sex; float score;} Boy [5] defines a structural array BOY1, a total of 5 elements, Boy [0] ~ Boy [4]. Each array element has a structural form of the Struct STU. For external structural arrays or static structural arrays can be initialized, for example: struct stu {int num; char * name; char sex; float score;} boy [5] = {{101, "li ping", "m", 45}, {102, "zhang ping", "m", 62.5}, {103, "he fang", "f", 92.5}, {104, "Cheng Ling", "F", 87}, {105 , "Wang Ming", "M", 58};} When the value is assigned to all elements, the array length may not be given. [Example 7.4] Calculate the average number of students and the number of people who do not have a profit.
Struct stu {int num; char sex; float score;} boy [5] = {101, "li ping", 'm', 45}, {102, "zhang ping", 'm', 62.5}, {103, "HE fang", 'f', 92.5}, {104, "Cheng Ling", 'F', 87}, {105, "Wang Ming", 'M', 58},}; Main () {Int i, c = 0; float ave, s = 0; for (i = 0; i <5; i ) {s = boy [i] .score; if (Boy [i] .score <60 ) C = 1;} Printf ("s =% f / n", s); AVE = S / 5; Printf ("Average =% f / ncount =% D / N", AVE, C);} This example A total of 5 elements in the program are defined in the program, and the initialization assignment is initialized. In the main function, use the for statement to accumulate the SCORE member value of each element in S, such as the value of the score is less than 60 (not grid), that is, the counter C plus 1, the cycle is completed, calculate the average score, and output the total class total points , The average division does not have the number of people. [Example 7.5] Established a classmate address book #include "stdio.h" #define num 3struct mem {char name [20]; char phone [10];}; main () {structure MEM man [Num]; int i; for (i = 0; I The storage space is allocated only when a variable is illustrated as this type of structure. Therefore, the above & stu is wrong, it is impossible to take a structural name of the first address. With a structural pointer variable, you can easily access the various members of the structural variable. The general form of its access is: (* structural pointer variable). Member name or: structural pointer variable -> member name, such as: (* pstu) .num or: pstu-> Num should pay attention to (* PSTU) Brand on both sides It is not a few, because the membership "." The priority is higher than "*". If you go to the bracket writing * pstu.num is equivalent to * (pstu.num), so that the meaning is completely wrong. The specific description and method of use of structural pointer variables will be described below. [Example 7.6] Struct Stu {Int Num; Char * Name; Char Sex; Float Score;} BOY1 = {102, "ZHANG Ping", 'M', 78.5}, * PSTU; Main () {PSTU = & BOY1; Printf ("Number =% D / NNAME =% S / N", BOY1.NUM, BOY1.NAME); Printf ("SEX =% C / NSCORE =% f / n / n", boy1.sex, boy1.score PRINTF ("Number =% D / NNAME =% S / N", (* PSTU) .Num, (* PSTU) .name); Printf ("SEX =% c / nscore =% f / n / N", (* PSTU). SEX, (* PSTU) .score; Printf ("Number =% D / NNAME =% S / N", PSTU-> Num, PSTU-> Name); Printf ("SEX =% C / NSCORE =% F / N / N ", PSTU-> SEX, PSTU-> score);} This program defines a structure STU that defines the STU type structure variable BOY1 and the initialization assignment, but also defines a point to STU Type structure pointer variable PSTU. In the main function, the PSTU is given the address of BOY1, so the PSTU points to BOY1. Then output all members of BOY1 in three forms in the printf statement. It can be seen from the operation results: structural variables. Member name (* Structural pointer variable). Member Name Structure Pointer Variables -> Member Name These three are fully equivalent to representing structural members. The structural array pointer variable structural pointer variable can point to an array of structures, and the value of the structural pointer variable is the first address of the entire structure array. The structural pointer variable can also point to an element of the structural array, and the value of the structural pointer variable is the first address of the array element of the structure. Set PS to point to the pointer variable of the structure array, the PS also points to the No. 0 element of the array of the structure, PS 1 points to the 1st element, PS i points to the I number. This is consistent with the case of a normal array. [Example 7.7] An array of structural arrays is output with a pointer variable. Struct Stu {Int Num; Char * Name; Char Sex; Float Score;} Boy [5] = {101, "Zhou Ping", 'M', 45}, {102, "ZHANG Ping", 'M, 62.5}, {103, "liou fang", 'f', 92.5}, {104, "Cheng Ling", 'F', 87}, {105, "Wang Ming", 'M, 58},}; Main () {struct stu * ps; printf ("no / tName / T / T / T / TSEX / TSCORE / T / N"); for (PS = Boy; PS In the main function, the structural pointer variable PS is defined, and the first address of the BOY is given to the PS point to the BOY array. Then use the PS to do the reference function AVE. Complete the calculation average score and statistics in the function AVE and output the result. Compared with the example 7.4, since the programs are all used by the pointer variables, the speed is faster and the program efficiency is higher. .topoic = Dynamic Storage Assignment In an array chapter, the length of the array is pre-defined and fixed throughout the program. Dynamic array types are not allowed in C language. For example: int N; scanf ("% d", & n); int a [n]; uses variables to represent the length, want to dynamically explain the size of the array, which is wrong. But in actual programming, this often occurs, ie the required memory space depends on the actual input data, and cannot be predetermined. For this problem, it is difficult to solve with an array approach. In order to solve the above problems, the C language provides some memory management functions, which can be dynamically allocated to memory space as needed, or the space that is no longer used, which provides means for efficiently utilizing memory resources. The commonly used memory management functions have the following: 1. Allocate memory space function Malloc call form: (Type Desifter *) Malloc (Size) Function: Assign a length of "size" byte in the memory dynamic storage area area. The return value of the function is the first address of the area. "Type Desorph" indicates what data types are used to use this area. (Type Design *) Indicates that the return value is forced to convert to the type pointer. "Size" is an unsigned number. For example: PC = (char *) malloc (100); indicates that the memory space allocated, forced to convert to the character array type, the return value of the function is a pointer to the array of characters, and imparts the pointer variable PC . 2. Allocate memory space function CallocCalloc is also used to assign memory space. Call Form: (Type Design *) Calloc (n, size) Function: Allocated the continuous area of the N block length "size" byte in the memory dynamic storage area. The return value of the function is the first address of the area. (Type Design *) is used for mandatory type conversion. The difference between the Calloc function and the Malloc function is only to allocate an N block area at a time. For example: ps = (struet stu *) Calloc (2, sizeof (struct stu)); SizeOf (Struct Stu) is a structural length of the STU. Therefore, the statement means that the 2-piece continuous zone is assigned according to the length of the STU, and forced to convert to the STU type, and the first address is given to the pointer variable PS. 3. Release the memory space function free call form: Free (Void * Ptr); Function: Release a memory space pointing to the PTR, PTR is an arbitrary type pointer variable, which pointing to the first address of the released area. The released area should be area assigned by the Malloc or Calloc function: [Example 7.9] Assign a zone to enter a student data. Main () {struct stu {int Num; char * name; char sex; float score;} * ps; ps = (struct stu *) malloc (Struct Stu); ps-> num = 102; ps-> Name = "zhang ping"; ps-> sex = 'm'; ps-> score = 62.5; printf ("number =% d / nname =% S / N", PS-> Num, PS-> Name); Printf ("SEX =% C / NSCORE =% F / N", PS-> SEX, PS-> Score; Free (PS);} In this case, the structure STU is defined to define the STU type pointer variable PS. Then allocate a STU large memory area and assign the first address to the PS to point to the area. Then, the PS is assigned to the pointer variables to each member, and each member value is output with the PrintF. Finally, use the Free function to release the memory space points to the PS. The entire program contains three steps of application for memory space, using memory space, and releases in memory space to realize dynamic allocation of storage space. The concept of the list is a dynamic allocation method in Example 7.9 to allocate memory space for a structure. Each time a piece of space can be used to store a student's data, we can call it a node. How many students should apply for how many memory spaces are applied, that is, how many nodes should be established. Of course, the above work can also be done with the structural arrays, but if you can't accurately grasp the number of students in advance, you will not be able to determine the array size. And when the student is resumed, the space occupied by the element cannot be released from the array. These issues can be solved well with dynamic storage. There is a student to allocate a node, there is no need to predetermine the accuracy of the students, a student's dropout, can delete the node, and release the storage space occupied by this node. Thereby saving valuable memory resources. On the other hand, the method of using an array must take up a continuous memory area. When dynamic allocation, each node can be discontinuous (continuous in the node). The connection between nodes can be implemented with a pointer. That is, a member item is defined in the node structure to store the first address of the next node, which is used to store the address of the address, often referred to as a pointer domain. The first address of the second node can be stored in the first node's pointer domain, and the first address of the third node is stored in the pointer domain of the second node, so that the last node is connected. . The last node is connected due to the subsequent junction, and its pointer domain can be 0. Such a connection method is referred to in the data structure as "linked list". Figure 7.3 is a schematic diagram of a linked list. In Figure 7.3, the 0th junction is called a head junction, which stores the first address of the first node, which has no data, just a pointer variable. Each of the following nodes is divided into two domains, one is a data domain, stores various actual data, such as student Num, Name Name, Gender SEX, and grades SCORE. Another domain is a pointer domain, and the first address of the next node is stored. Each node in the linked list is the same structural type. For example, a node that stores student number and grades should be the following structure: struct stu {int num; int score; struct stu * next;} The first two member items constitute the data field, the last member item NEXT constitutes the pointer domain, It is a pointer variable to the STU type structure. The basic operation of the linked list has the following main operations of the linked list; settled a list; 2. Structure lookup and output; 3. Insert a node; 4. Delete a node; following these operations. [Example 7.10] Establish a three node linked list to store students' data. For the sake of simplicity, we assume that only two student data structures are only two people and age. You can write a function Creat created to create a list. The procedure is as follows: #define null 0 # Define Type Struct Stu # define len sizeof (struct stu) structure stu {int num; int agent stu * next;}; type * creat (int N) {struct stu * head, * PF, * Pb; Int i; for (i = 0; i 2. The deleted point is not the first node. This situation can point the front spoint of the deleted point points to the rear node of the deleted point. PF-> Next = Pb-> Next. The process is shown in Figure 7.6. The function programming is as follows: Type * delete (INT NUM) {type * pf, * pb; if (head == null) / * such as empty table, output prompt information * / {printf ("/ nempty list! / N "); goto end;} PB = head; while (PB-> Num! = NUM && PB-> Next! = NULL) / * When not to delete the node, it is not the last node, Continue loop * / {PF = Pb; PB = Pb-> Next;} / * pf points to the current node, PB points down the next node * / if (Pb-> Num == Num) {IF (PB == Head If you find the deleted node, you find the deleted node, and the first node, the Head points to the second node, otherwise make the pointer to the node of the PF point down the next junction * / Else Pf-> Next = Pb-> Next; Free (PB); Printf ("THE NODE IS DELETED / N");} elseprintf ("The Node Not Been Foud! / N"); end: return head;} function There are two ginseng, and head is a pointer variable that points to the first node of the chain table, Num to delete the sideway. First determine if the linked list is empty, it is impossible to have an adjjopt point. If it is not empty, the PB pointer points to the first node of the list. After entering the While statement, look up one by one. After finding the deleted node, look at whether it is the first node, if it makes the head point to the second node (ie, delete the first node from the chain), otherwise, the front node of the deleted point is made ( PF refers to the rear node (referred to as the pointer domain) of the deleted node). If the end of the loop does not find the node to delete, the prompt information found "is output. Finally returns the HEAD value. [Example 7.13] Write a function and insert a node in the specified location in the list. Insert the node in the specified location of a linked list, requiring the list itself must be in a certain regular sequence. For example, in a student data linked list, you are required to insert a node in order. The pointer to which is tied is PI. Can be inserted in three different situations. 1. Original table is a blanket, just make the head point to the tie point. See Figure 7.7 (a) 2. The slot point value is minimized and should be inserted before the first node. In this case, the Head points to the plot point, the pointer domain of the plug point points to the original first node. That is: Pi-> Next = Pb; Head = Pi; see Figure 7.7 (b) 3. Insert in other locations, see Figure 7.7 (c). In this case, the pointer domain of the front node of the insertion position points points to the tie point, and the pointer domain of the plug point points points to the rear node of the insertion position. That is: pi-> next = Pb; pf-> next = pi; 4. Insert in the same surface, see Figure 7.7 (d). In this case, the original surface end node pointer domain points to the tie point, and is set to NULL by the interpolation point. That is: PB-> Next = Pi; pi-> next = null; type * INSERT (TYPE * HEAD, TYPE * PI) {TYPE * PF, * PB; PB = head; if (Head == Null) / * Empty Table Insert * / (Head = Pi; Pi-> Next = NULL;} else {while ((pi-> num> pb-> num) && (pb-> next! = Null) {pf = Pb; PB = PB-> Next;} / * find insertion position * / if (pi-> num <= pb-> num) {if (head == pb) Head = pi; / * Insert * / else before the first node PF-> Next = Pi; / * Insert * / pi-> next = Pb;} else {PB-> next = pi; pi-> next = null;} / * Insert * /} return Head;} This function has two shape parameters, and the Head pointing to the linked list, PI points to the tie point. The function is first determined if the linked list is empty, which makes the Head point to the tie point. Table is not available , Use the While statement loop to look up the insertion position. After finding it, it is again determined whether it is inserted before the first node. If the inserted node is greater than all nodes in the table, insert the end of the surface. This function returns a pointer to the head pointer of the linked list. When the inserted position is before the first node, the inserted new node is The first node of the linked list, the value of Head has changed, so it is necessary to return this pointer to the main adjustment function. [Example 7.14] Build the above, delete nodes, and insert the function organization, build one Output all the functions of all nodes, then call them with the main function. #define null 0 # Define Type Struct Stu # Define Len SizeOf (Struct Stu) Struct Stu {Int Num; Int Age; Struct Stu * Next;}; type * creat (int N) {struct stu * head, * pf, * Pb; Int i; for (i = 0; i (TYPE *) Malloc (LEN); Scanf ("% D% D", & pnum-> num, & pnum-> age); Head = INSERT (HEAD, PNUM); Print (HEAD);} In this example, the Print function Used to output each node data domain value in the linked list. The initial value of the function of the function of the function points to the first node of the linked list. In the While statement, after outputting the node value, the HEAD value is changed and pointing down the next junction. If the header pointer header header Head should be left, a pointer variable should be set, which gives it to it, and use it to replace HEAD. In the main function, n is the number of established nodes, NUM is a data domain value to be denied; Head is a head pointer to the linked list, and PNum is a pointer to the tie point. The significance of each line in the main function is: the sixth line input the number of nodes of the built-in list; the seventh line is adjusted to establish a lin list and return the head pointer to the head; the eighth line adjustment PRINT function outputs a list; the tenth line input Number of points; the eleventh line adjustment DELETE function deletes a node; the 12th line of print function outputs the list; the fourteenth line adjustment Malloc function assigns a node memory space and gives its address to PNUM; The fifteen line inputs the data domain value to be inserted; the sixteenth line adjustment insert function is inserted into the node referred to in PNUM; the seventeenth row again adjusts the Print function output Link list. From the results of the operation, first establish a linked list of 3 nodes, and output its value; delete 103 nuts, only 105, 108 junction; enter the 106 number data, insert into the rear chain table The node is 105, 106, 108. Joint "combination" is also a data structure for constructive types. In a "combination", a variety of different data types can be defined, one of the variables that are described as the "federation" type, allowing any of the data defined by the "United". This is not available in the previous data types. For example, defined a variable that can only be loaded into an integer data, defined as a real value can only be given to real data. There are many examples in practical problems. For example, in the school's teachers and students, fill in the following form: The "professional" of the name of the name of the age group can be divided into two types "teachers" and "students". A student of "unit" should fill in the class number, and the teachers should fill in a certain department of the department. The class can be expressed as an integer, and the teaching and research room can only use characters. Different types of data are required to fill in the "unit" variable, you must define "unit" as "union" containing two types of integer and character arrays. "Union" has some similarities between "structure". But both have different inherent. In the structure, each member has its own memory space, the total length of a structural variable is the sum of each member length. In the "United", each member share a memory space, and a combined variable is equal to the longest length in each member. It should be noted that this so-called sharing does not mean that multiple members are simultaneously loaded into a combined variable, but means that the combined variable can be given to any member value, but only one value can be assigned each time. The value is rushed away. As the "unit" variable described earlier, if it is defined as a combination of "class" or "teaching,", it allows the intersection (class) or a string (teaching and research room). Either give an integer value, or give a string, you cannot give it simultaneously. The definition of the federal type and a combined variable describes that a joint type must be defined to explain the variable as the federated type. 1. Union definitions define a general form of a joint type: UNION Joint Name {member table}; member table contains several members, the general form of members: Type indicator member name member name should meet the identifier . For example: Union Perdata {Int Class; Char Office [10];}; defines a joint type named PerData, which contains two members, one is intellectual, member named class; another is a character array, array name For office. After the joint definition, a combined variable description can be performed as a variable of the PerData type, and an integer Class or a character array office can be stored. Second, the combined variable describes the description of the combined variable and the description of the structural variables. There are three forms. That is, first defined, then explain; definitions simultaneously explain and directly explain. Take the PERDATA type as an example, explain as follows: Union Perdata {Int Class; Char OffICAE [10];}; Union PerData A, B; / * Description A, B is PerData type * / or can be described at the same time as: union perdata {int Class; char office [10];} a, b; or direct description is: union {int class; char office [10];} A, B variables are PerData types. Their memory assignment is shown in Figure 7-8. A, the length of the B variable should be equal to the longest length in the members of PerData, which is equal to the length of the Office array, a total of 10 bytes. As can be seen from the figure, if the B variables are given to the integer value, only two bytes are used, and 10 bytes can be used when applying the character array. The assignment of the combined variable and the assignment of the combined variable can only be done with a member of the variable. Members of the combined variable are represented as: a combined variable name. Member name, for example, a variable that is illustrated as a PerData type, can use A.CLASS A.Office not allow only combined variable name to assign values or other operations. The initialization assignment of the combined variable is also not allowed to assign only in the program. Also emphasized that a combined variable can only give a member value each time. In other words, the value of a combined variable is a member value of a joint committee. [Example 7.15] There is a form of teacher and student, and teachers have four names, age, occupations, and teaching and research. The students have four names, age, occupation, and class. Program input person data, then output it in a table.