Bootstrap

【C进阶】之结构体类型( struct)

1 结构体相关的概念

  1. C语言属于面向过程的一门语言,C语言开发工程师在编写代码时也要具有对象的思想,
    C语言表示对象的方式就是结构体类型。在C语言中通过结构体类型描述一个对象。

  2. 什么是对象?
    事件的万事万物都可以看出一个对象,通过编程语言抽象的描述一个对象。

  3. 如何描述一个对象?
    将一类对象具有共同的属性和行为剥离处理,非共性的东西剥离出去;
    比如人:姓名,年龄,身高,体重,性别,外貌, 吃喝拉撒睡。

    属性:对象的名词,形容词,量词 —> 抽象成代码:使用变量表示
    行为:对象的动词(可以干什么)—> 抽象成代码:使用函数表示

  4. 结构体的概念
    结构体属于C语言中的一个自定义的构造类型,关键字(struct)。
    将很多不同的数据类型封装成一个新的数据类型,这个数据类型就是结构体类型,
    结构体中的成员在内存空间中是连续的,并且每个成员都有其独立的内存空间。

  5. 声明一个结构体类型
    没有结构体的沟通类型,如何描述一个对象:

    char name[20];
    int age;
    char sex;
    int score;   ----> 只能描述一个对象,
    

    如果描述多个对象,在重新定义多次。

    如果描述多个对象,在重新定义多次。

    有结构体的沟通类型,如何描述一个对象:

    struct student{   // 声明一个结构体类型,此时struct student就表示一个结构体类型名,
    					// 使用此类型可以定义结构体类型的变量
    	char name[20];
         int age;
         char sex;
         int score; 
    };
    

    // 定义一个对象
    struct student stu1;
    // 定义100个对象
    struct student stu_arr[100];

2 声明结构体类型的语法格式

// 1. 声明一个结构体类型, 声明结构体类型时并没有在内存中分配空间
struct 结构体名{
数据类型 变量名1;
数据类型 变量名2;
数据类型 变量名3;

数据类型 变量名n;
};

  1. 此时"struct 结构体名"就是自己构造的新的结构体类型,使用此结构体类型定义结构体类型的变量。

  2. 结构体中的成员的类型可以是:基本的数据类型,数组类型,指针类型,指针数组,数组指针,函数指针,
    函数指针数组,嵌套的结构体类型,枚举类型,联合体类型。

3 定义结构体类型的变量

  1. 定义普通的结构体类型的变量:
    struct 结构体名 结构体变量名;
  2. 定义结构体指针类型的变量:
    struct 结构体名 *结构体指针变量名;

4 结构体中成员的访问

  1. 定义普通的结构体类型的变量:
    结构体变量名.成员变量名;
  2. 定义结构体指针类型的变量:
    结构体指针变量名->成员变量名;

5 定义普通的结构体类型的变量,并访问

5.1 先声明结构体类型,在定义结构体类型的变量

  1. 声明结构体类型

    struct student{  
    	char name[20];
         int age;
         char sex;
         int score; 
    };
    
  2. 定义普通结构体类型的变量 : struct 结构体名 结构体变量名;
    struct student stu;

  3. 对结构体中的成员进行初始化
    3.1> 定义结构体类型变量的同时进行初始化
    struct student stu1 = {"yy", 18, 'M', 100};
    // 要求按照结构体中成员的类型依次进行初始化
    3.2> 先定义结构体类型变量,后进行初始化 : 结构体变量名.成员变量名 = 初始值;

    struct student stu2;
    strcpy(stu2.name, "yy");
    stu2.age = 18;
    stu2.sex = 'M';
    stu2.score = 100;
    

    3.3> 定义结构体类型变量的同时进行初始化

    struct student stu1 = {
        .name = "yy", 
        .age = 18, 
        .sex = 'M', 
        .sorce=100
    };
    

    优点:可以只对部分成员初始化,成员初始化的顺序没有要求。

#include <stdio.h>
#include <string.h>
// 1. 声明结构体类型,结构体类型中的成员根据自己的对象添加对应的成员
struct student
{
    char name[20];
    int age;
    char sex;
    int score;
};

// 相同结构体类型的变量,可以进行赋值操作,
// 结构体类型作为函数的形参使用
void print(struct student s)
{
    printf("我的名字叫%s,我的年龄%d,我的性别%c,我的成绩%d\n",
                s.name, s.age, s.sex, s.score);
}

int main(int argc, const char *argv[])
{
    /*your code*/
    // 1. 先定义结构体类型的变量,在对结构体变量中的成员初始化
    struct student stu1;
    strcpy(stu1.name, "yy");
    stu1.age = 18;
    stu1.sex = 'M';
    stu1.score = 100;
    print(stu1);
    
    // 2. 定义结构体类型变量的同时进行初始化
    struct  student stu2 = {"yy", 28,'M',88};
    print(stu2);

    // 3. 定义结构体类型变量的同时进行初始化
    struct student stu3 = {
        .name = "lisi",
        .sex = 'W',
        .age = 24,
        .score = 99
    };
    print(stu3);

    return 0;
}

5.2 声明结构体类型的同时定义结构体类型的变量

  1. 声明结构体类型的同时定义结构体类型的变量

    struct student{  
    	char name[20];
        int age;
        char sex;
        int score; 
    }stu1, stu2, stu3;
    
  2. 对结构体类型的变量进行初始化
    2.1> 声明结构体类型的同时定义结构体变量,同时初始化。

    struct student{  
             char name[20];
             int age;
             char sex;
             int score; 
    }stu1={"yy",18,'M',100};
    

    2.2> 声明结构体类型的同时定义结构体变量,同时初始化。

    struct student{  
             char name[20];
             int age;
             char sex;
             int score; 
         }stu2 = {
         	.name = "yy",
         	,age = 18,
         	.sex = 'M',
         	.score = 100};
    

    2.3> 声明结构体类型的同时定义结构体变量,最后在进行初始化。

    struct student{  
             char name[20];
             int age;
             char sex;
             int score; 
         }stu3;     
    
    strcpy(stu3.name, "yy");
    stu3.age = 18;
    stu3.sex = 'M';
    stu3.score = 100;
    

没有结构体名字的结构体:

  1. 声明结构体类型的同时定义结构体类型的变量, 省略结构体的名字,
    后续不可以单独使用这个结构体类型在定义新的变量。

    struct  {  
    	char name[20];
        int age;
        char sex;
        int score; 
    	}stu1, stu2, stu3;
    
  2. 对结构体类型的变量进行初始化
    2.1> 声明结构体类型的同时定义结构体变量,同时初始化。

    struct {  
        char name[20];
        int age;
        char sex;
        int score; 
    }stu1={"yy",18,'M',100};
    

    2.2> 声明结构体类型的同时定义结构体变量,同时初始化。

    struct {  
             char name[20];
             int age;
             char sex;
             int score; 
         }stu2 = {
         	.name = "yy",
         	,age = 18,
         	.sex = 'M',
         	.score = 100
     };
    

    2.3> 声明结构体类型的同时定义结构体变量,最后在进行初始化。

    struct {  
        char name[20];
        int age;
        char sex;
        int score; 
    }stu3;
    strcpy(stu3.name, "yy");
    stu3.age = 18;
    stu3.sex = 'M';
    stu3.score = 100;
    

练习题:定义教师结构体类型,成员姓名(字符数组name),年龄(age),工资(salary)。
并使用类定义结构体变量,对成员进行初始化。

#include <stdio.h>
#include <string.h>
// 声明结构体类型的同时定义结构体变量
struct  teacher
{
    char name[20];
    int age;
    int salary;
}tea1 = {"yy", 18, 30000}, 
tea2 = {
    .name = "yy", 
    .age = 18, 
    .salary = 35000}, 
tea3;

void print(struct teacher t)
{
    printf("姓名:%s, 年龄:%d, 工资:%d\n",
            t.name, t.age, t.salary);
}

int main(int argc, const char *argv[])
{
    /*your code*/
    // 先声明结构体类型,定义结构体变量,后进行初始化
    strcpy( tea3.name, "yy");
    tea3.age = 16;
    tea3.salary = 32000;

    print(tea1);
    print(tea2);
    print(tea3);

    return 0;
}

6 定义结构体指针类型的变量,并访问

  1. 声明结构体类型

    struct student {  
    	char name[20];
         int age;
         char sex;
      int score; 
    };
    
  2. 定义结构体指针变量
    struct student *p;

  3. 对结构体指针变量进行初始化
    3.1 结构体指针变量指向栈区的空间:

    struct student stu = {"yy", 18, 'M', 100};  // 定义普通结构体变量
    struct student *p = &stu;
    struct student *p = NULL;
    p = &stu;
    

    3.2 结构体指针变量指向堆区的空间:

    struct student *p = (struct student *)malloc(sizeof(struct student));
    strcpy(p->name, "yy");
    p->age = 18;
    p->sex = 'M';
    p->score = 100;
    
  4. 如果定义的是结构体指针变量,没有以下初始化的方式,原因是结构体指针变量占8字节空间(64位系统)

struct student *p = {
->name = "yy",
->age = 18,
->sex = 'M',
->score = 100,
};

测试:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 1. 声明结构体类型
struct student
{
    char name[20];
    int age;
    char sex;
    int score;
};

// 函数的形参是一个结构体指针类型
void print(struct student *t)
{
    printf("姓名:%s, 年龄:%d, 性别:%c, 成绩:%d\n",
                t->name, t->age, t->sex, t->score);
}

int main(int argc, const char *argv[])
{
    /*your code*/
    // 2. 定义结构体指针类型的变量,指向一个栈区的结构体变量
    struct student stu = {"yy", 18, 'M', 100};
    print(&stu);
    struct student *p1 = &stu;
    print(p1);

    // 3. 定义结构体指针类型的变量,指向一个堆区的空间。
    struct student *p2 = (struct student *)malloc(sizeof(struct student));
    if (p2 == NULL)
    {
        printf("malloc memory failed!\n");
        return -1;
    }
    strcpy(p2->name, "yy");
    p2->age = 18;
    p2->sex = 'M';
    p2->score = 100;
    print(p2);
    return 0;
}

7 结构体中的成员包含指针类型的成员

1. 声明结构体类型
	struct student {
		char *name;
		int *age;
	};

2. 定义结构体类型的变量并进行初始化
	int m_age = 18;
	struct student stu = {"yy", &m_age};  // char *name指向的是一个字符串常量
	
	char m_name[20]= "yy";
	int m_age = 18;
	struct student stu = {m_name, &m_age};  // char *name指向的是一个字符数组
	
	struct student stu;
	stu.name = (char *)malloc(sizeof(char)*20);  // char *name成员指向堆区空间
	stu.age = (int *)malloc(sizeof(int));  // int *age成员指向堆区空间
	strcpy(stu.name, "yy");
	*stu.age = 18;
	
	struct student *p1 = &stu;
	
	
	struct student *p2 /*定义结构体指针变量,p2在栈区分配8字节空间 */
				= (struct student *)malloc(sizeof(struct student)); 
				/* 让P2指向堆区空间, 给p2->name成员分配8字节空间,存放地址
				给p2->age成员分配8字节空间,存放地址 */
				
	/*对p2中的name成员分配堆区空间并指向堆区的空间 */ 
	p2->name = (char *)malloc(sizeof(char)*20);  // char *name成员指向堆区空间
	/*对p2中的age成员分配堆区空间并指向堆区的空间 */ 
	p2->age = (int *)malloc(sizeof(int));  // int *age成员指向堆区空间
	
	// 对堆区的空间进行初始化。
	strcpy(p2->name, "yy");
	*p2->age = 18;

测试:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student
{
    char *name;
    int *age;
};

void print(struct student *s)
{
    printf("姓名:%s, 年龄:%d\n", s->name, *s->age);
}

int main(int argc, const char *argv[])
{
    /*your code*/
    int m_age = 18;
    // 定义普通的结构体变量,并进行初始化
    struct student stu1 = {"yy", &m_age}; // char *name指向的是一个字符串常量
                                              // int *age 指向的一个int类型的变量
    print(&stu1);

    char m_name[20] = "yy";
    // 定义普通的结构体变量,并进行初始化
    struct student stu2 = {m_name, &m_age}; // char *name指向的是一个字符数组
                                        // int *age 指向的一个int类型的变量
    print(&stu2);


    // 定义普通结构体变量,让结构体中的指针类型的成员指向堆区空间
    struct student stu3;
    stu3.name = (char *)malloc(sizeof(char) * 20); // char *name成员指向堆区空间
    stu3.age = (int *)malloc(sizeof(int));         // int *age成员指向堆区空间
    // 对堆区的空间进行初始化操作
    strcpy(stu3.name, "ff");
    *stu3.age = 18;
    print(&stu3);

    // 定义结构体指针变量, 指向普通的结构体类型的变量
    struct student *p1 = &stu3;
    print(p1);

    // 定义结构体指针变量,指向堆区空间,结构体中的成员也指向堆区空间
    struct student *p2 /*定义结构体指针变量,p2在栈区分配8字节空间 */
        = (struct student *)malloc(sizeof(struct student));
    /* 让P2指向堆区空间, 给p2->name成员分配8字节空间,存放地址
    给p2->age成员分配8字节空间,存放地址 */

    /*对p2中的name成员分配堆区空间并指向堆区的空间 */
    p2->name = (char *)malloc(sizeof(char) * 20); // char *name成员指向堆区空间
    /*对p2中的age成员分配堆区空间并指向堆区的空间 */
    p2->age = (int *)malloc(sizeof(int)); // int *age成员指向堆区空间

    // 对堆区的空间进行初始化。
    strcpy(p2->name, "ff");
    *p2->age = 18;

    print(p2);
    
    return 0;
}

8 定义结构体数组

  1. 声明结构体类型

    struct student
     {
         char name[20];
         int age;
         char sex;
         int score;
     };
    
  2. 定义结构体数组变量 : struct student 结构体数组名[数组的长度];
    struct student arr[2];

  3. 对数组的成员进行初始化
    3.1> 定义的同时进行初始化
    struct student arr[2] = {{"yy",18,'M',100},{"yy",18,'M',90}};

    3.2> 定义的同时进行初始化

    struct student  arr[2] = {
    		[0] = {
    			.name = "yy",
    			.age = 18,
    			.sex = 'M',
    			.score = 100
    		},
    		[1] = {
    			.name = "yy",
    			.age = 18,
    			.sex = 'M',
    			.score = 90
    		}
    	};
    

    3.3> 先定义结构体数组,后进行初始化

    struct student  arr[2];
    strcpy(arr[0].name, "yy");
    arr[0].age = 18;
    arr[0].sex = 'M';
    arr[0].score = 100;
    strcpy(arr[1].name, "yy");
    arr[1].age = 18;
    arr[1].sex = 'M';
    arr[1].score = 90;
    
  4. 结构体数组中每个元素中的每个结构体成员的访问

    void print(struct student *s, int len)
    {
    	int i;
    	for (i = 0; i < len; i++) 
    	{
    		printf("%s %d %c %d\n", s[i].name, s[i].age, s[i].sex, s[i].score);
    		printf("%s %d %c %d\n", (s + i)->name, (s+i)->age, (s+i)->sex, (s+i)->score);
    	}
    }
    

练习题:定义教师结构体类型,成员姓名(字符数组name),年龄(age),工资(salary)。
并使用类定义结构体变量,对成员进行初始化

结构体数组实现:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct teacher
{
    char name[20];
    int age;
    int salary;
};

int main(int argc, const char *argv[])
{
    struct teacher tea[10];
    int n=0;//教师人数
    printf("请输入教师人数>");
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        printf("教师%d的姓名:",i);
        scanf("%s",tea[i].name);   
        printf("年龄:");
        scanf("%d",&(tea[i].age));
        printf("工资:");
        scanf("%d",&(tea[i].salary));
    }
    printf("打印教师工资表>\n");
    for (int i=1; i<=n;i++)
    {
        printf("教师%d的姓名:%s  年龄:%d   工资:%d\n",i,tea[i].name,tea[i].age,tea[i].salary);
    }
    return 0;
}

结构体指针实现:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct teacher
{
    char name[20];
    int age;
    int salary;
};

int main(int argc, const char *argv[])
{
    int n=0;//教师人数
    printf("请输入教师人数>");
    scanf("%d",&n);
    // struct teacher tea[10];
    struct teacher *tea=(struct teacher *)malloc(sizeof(struct teacher)*n);
    if(NULL==tea) printf("malloc memory filed!\n");
    for(int i=0;i<n;i++){
        printf("教师%d的姓名:",i+1);
        // scanf("%s",(*(tea+i)).name); 
        scanf("%s",(tea+i)->name); 
        printf("年龄:");
        // scanf("%d",&((*(tea+i)).age));
        scanf("%d",&(tea+i)->age);
        printf("工资:");
        // scanf("%d",&((*(tea+i)).salary));
        scanf("%d",&(tea+i)->salary);
    }
    printf("打印教师工资表>\n");
    for (int i=0; i<n;i++)
    {
        // printf("教师%d的姓名:%s  年龄:%d   工资:%d\n",i+1,(*(tea+i)).name,(*(tea+i)).age,(*(tea+i)).salary);
        printf("教师%d的姓名:%s  年龄:%d   工资:%d\n",i+1,(tea+i)->name,(tea+i)->age,(tea+i)->salary);
    }
    return 0;
}

9 定义结构指针数组

  1. 结构指针数组:本质是一个数组,数组中的成员都是结构体的指针。

  2. 格式:
    struct 结构体名 *结构体指针数组名[元素个数];

  3. 初始化:
    struct 结构体名 结构体变量0;
    struct 结构体名 结构体变量1;

    定义结构体指针数组的同时进行初始化:
    struct 结构体名 *结构体指针数组名[元素个数] = {&结构体变量0, &结构体变量1};

    先定义结构体指针数组,后进行初始化:
    struct 结构体名 *结构体指针数组名[元素个数];
    结构体指针数组名[下标] = &结构体变量0;
    结构体指针数组名[下标] = &结构体变量1;

  4. 访问结构体指针数组的每个元素,每个元素都是一个结构体指针类型,并访问结构体中的每个成员。
    结构体指针数组名[下标]->结构体成员名;

10 定义结构体数组指针

  1. 结构体数组指针 : 本质是一个指针,指向的是一个结构体二维数组

  2. 格式:
    struct 结构体名 (*结构体数组指针名)[元素个数];

  3. 初始化
    定义的同时进行初始化:
    struct 结构体名 结构体数组名[元素个数] = {{},{},…};
    struct 结构体名 (*结构体数组指针名)[元素个数] = &结构体数组名;

    先定义后进行初始化:
    struct 结构体名 (*结构体数组指针名)[元素个数];
    结构体数组指针名 = &结构体数组名;

  4. 成员的访问
    (*结构体数组指针名)[下标].结构体成员名;

    或者
    ((*结构体数组指针名)+下标)->结构体成员名;

11 相同结构体类型变量可以进行赋值操作

相同结构体类型的变量可以进行赋值操作。
struct student
{
    char name[20];
    int age;
    char sex;
    int score;
};
struct student stu1 = {"yy", 18, 'M', 100};
struct student stu2 = stu1;   // 普通结构体变量进行赋值

struct student *p = NULL;   // 结构体指针变量进行赋值
*p = &stu1;

struct student *p2 = p;  // 结构体指针变量进行赋值

12 小结

声明一个结构体类型:

struct teacher{
	char *name;
	int age;
	char sex;
	int salary;
};

// 1. 定义普通的结构体变量,并初始化,完成成员的访问(3种)
// 2. 定义结构体指针, 并初始化,指向堆区的空间或者栈区空间,并访问成员(堆区、栈区)
// 3. 定义结构体数组,并初始化,已经完成数组的每个元素及元素中的每个成员的访问(3种)
// 4. 定义结构体指针数组, 并初始化,访问成员(2种)
// 5. 定义结构体数组指针,并初始化,以及成员的访问

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct teacher{
    char *name;
    int age;
    char sex;
    int salary;
}tea;

int main(int argc, const char *argv[])
{
    //1. 定义普通的结构体变量,并初始化,完成成员的访问(3种)
    tea t1={"y1",18,'M',10000};//方法一
    tea t2={.name="y2",.age=19,.sex='M',.salary=100};//方法二
    //方法三
    tea t3;
    t3.name="y3";
    t3.age=20;
    t3.sex='M';
    t3.salary=10000;

    // 2. 定义结构体指针, 并初始化,指向堆区的空间或者栈区空间,并访问成员
    //在栈区
    tea t4={"y4",18,'M',10000};
    tea *p1_t4=&t4;

    //在堆区
    tea *p2=(tea *)malloc(sizeof(tea));
    if(NULL==p2)printf("malloc memory filed!\n");
    // 给结构体中的指针赋值的方式(3种)
    //结构体中name指针直接指向常量区
    p2->name="p2";
    //结构体中name指针指向栈区
    char name[20]="yy";
    p2->name=name;
    //结构体中name指针指向堆区
    p2->name=(char *)malloc(sizeof(20));
    strcpy(p2->name,"yy");

    p2->age=20;
    p2->sex='M';
    p2->salary=1000;
    free(p2);
    p2=NULL;
// #define DEBUG
#ifdef DEBUG1

    //error初始化,原因:指针的大小只有8字节(64位系统),不能存储那么多数据
    int *p3={
            ->name="p3",
            ->age=20,
            ->sex='M',
            ->salary=200}

#endif

    // 3. 定义结构体数组,并初始化,已经完成数组的每个元素及元素中的每个成员的访问(3种)
    tea t5[2]={{"y5",18,'M',10000},{"y6",18,'M',10000}};//方法一

    tea t6[2]={
            [0]={"y5",18,'M',10000},
            [1]={"y6",18,'M',10000}
            };//方法二
    //方法三
    tea t7[2];
    t7[0].name="y7";
    t7[0].age=20;
    t7[0].sex='M';
    t7[0].salary=2000;
    t7[1].name="y8";
    t7[1].age=20;
    t7[1].sex='M';
    t7[1].salary=2000;
    //访问
    for(int i=0;i<2;i++){
        printf("%s   %d   %c   %d\n",t7[i].name,t7[i].age,t7[i].sex,t7[i].salary);
        printf("%s   %d   %c   %d\n",(*(t7+i)).name,(*(t7+i)).age,(*(t7+i)).sex,(*(t7+i)).salary);
        printf("%s   %d   %c   %d\n",(t7+i)->name,(t7+i)->age,(t7+i)->sex,(t7+i)->salary);
    }


    // 4. 定义结构体指针数组, 并初始化,访问成员(2种)
    tea t9={"y9",18,'M',10000};
    tea t10={"y10",18,'M',10000};
    tea *t8[2]={&t9,&t10};//方法一,定义结构体指针数组的同时进行初始化
    //访问
    for(int i=0;i<2;i++){
        printf("%s   %d   %c   %d\n",(*t8[i]).name,(*t8[i]).age,(*t8[i]).sex,(*t8[i]).salary);
    }

    //方法二,先定义结构体指针数组,后进行初始化
    tea *t11[2];
    t11[0]=&t9;
    t11[1]=&t10;
    //访问
    for(int i=0;i<2;i++){
        printf("%s   %d   %c   %d\n",t11[i]->name,t11[i]->age,t11[i]->sex,t11[i]->salary);
    }

    // 5. 定义结构体数组指针,并初始化,以及成员的访问(2种)
    //方法一:定义的同时进行初始化
    tea t13[2]={{"y13",18,'M',10000},{"y13",19,'M',10000}};
    tea (*t12)[2]=&t13;
    //访问:
    for(int i=0;i<2;i++){
        printf("%s   %d   %c   %d\n",(*t12)[i].name,(*t12)[i].age,(*t12)[i].sex,(*t12)[i].salary);
        printf("%s   %d   %c   %d\n",(*((*t12)+i)).name,(*((*t12)+i)).age,(*((*t12)+i)).sex,(*((*t12)+i)).salary);
        printf("%s   %d   %c   %d\n",((*t12)+i)->name,((*t12)+i)->age,((*t12)+i)->sex,((*t12)+i)->salary);
    }
    //方法二:先定义后进行初始化
    tea (*t14)[2];
    t14=&t13;
    //访问:
    for(int i=0;i<2;i++){
        printf("%s   %d   %c   %d\n",(*t14)[i].name,(*t14)[i].age,(*t14)[i].sex,(*t14)[i].salary);
        printf("%s   %d   %c   %d\n",(*((*t14)+i)).name,(*((*t14)+i)).age,(*((*t14)+i)).sex,(*((*t14)+i)).salary);
        printf("%s   %d   %c   %d\n",((*t14)+i)->name,((*t14)+i)->age,((*t14)+i)->sex,((*t14)+i)->salary);
    }
    return 0;
}
;