zoukankan      html  css  js  c++  java
  • 8.结构体

     一.结构体的定义

    1.结构体的定义

    struct _Teacher
    {
        char name[62];
        char c;
        int age;
    }
    
    typedef sturct _Teacher
    {
        char name[62];
        char c;
        int age;
        
    } Teacher;

    2.定义结构体变量的三种方法

    a.第一种

    Teacher t1;
    Teacher *p = (Teacher *)malloc(sizeof(Teacher));

    b.第二种

    struct _Teacher2
    {
        char name[62];
        char c;
        int age;
    } t2,t3;

    c.第三种

    struct 
    {
        char name[62];
        char c;
        int age;
    } t4;

    二.结构体元素作为函数参数

    实例:有如下结构体,分别在堆区和栈区实现结构体元素的赋值,排序和打印。

    typedef struct _Teacher
    {
        char name[62];
        char c;
        int age;
    }Teacher;

    在栈区实现结构体元素的赋值,排序和打印

    /*打印年龄*/
    void printfTeacherInfo(Teacher *tArray, int num)
    {
        int i = 0;
        for (i = 0; i < num; i++)
        {
            printf("第%d个老师的年龄为%d
    ", i + 1, tArray[i].age);
        }
    }
    
    
    void sortTeacherArray(Teacher *tArray, int num)
    {
        int i = 0,j = 0;
        Teacher tmp;
        if (tArray != NULL)
        {
            for (i = 0; i < num; i++)
            {
                for (j = i+1; j < num; j++)
                {
                    if (tArray[j].age > tArray[i].age)
                    {
                        tmp = tArray[i];
                        tArray[i] = tArray[j];
                        tArray[j] = tmp;
                    }
                }
            }
        }
    }
    
    
    
    // 在栈区实现结构体元素的赋值,排序,打印
    int main()
    {
    
        Teacher tArray[3];
        int origin_age = 30;
    
        int i = 0,j = 0;
        Teacher tmp;
    
        for (i = 0; i < 3; i++)
        {
            printf("请输入第%d个老师的年龄:",i+1);
            scanf("%d", &tArray[i].age);
        }
    
        printf("排序之前.............................................
    ");
        printfTeacherInfo(tArray,3);
    
        // 排序
        sortTeacherArray(tArray, 3);
    
        printf("排序之后.............................................
    ");
        printfTeacherInfo(tArray, 3);
    
        system("pause");
        return 0;
    
    }

    运行:

    在堆区实现结构体元素的赋值,排序和打印

    /*打印年龄*/
    void printfTeacherInfo(Teacher *tArray, int num)
    {
        int i = 0;
        for (i = 0; i < num; i++)
        {
            printf("第%d个老师的年龄为%d
    ", i + 1, tArray[i].age);
        }
    }
    
    
    void sortTeacherArray(Teacher *tArray, int num)
    {
        int i = 0,j = 0;
        Teacher tmp;
        if (tArray != NULL)
        {
            for (i = 0; i < num; i++)
            {
                for (j = i+1; j < num; j++)
                {
                    if (tArray[j].age > tArray[i].age)
                    {
                        tmp = tArray[i];
                        tArray[i] = tArray[j];
                        tArray[j] = tmp;
                    }
                }
            }
        }
    }
    
    
    Teacher* createTarray(int num)
    {
        Teacher *tArray = (Teacher *)malloc(num * sizeof(Teacher));
        return tArray;
    }
    
    
    // 在堆区实现结构体元素的赋值,排序和打印
    int main()
    {
        Teacher *tArray = createTarray(3);
        int i = 0, j = 0;
        Teacher tmp;
    
        if (tArray != NULL)
        {
            for (i = 0; i < 3; i++)
            {
                printf("请输入第%d个老师的年龄:",i+1);
                scanf("%d", &tArray[i].age);
            }
        }
    
        printf("排序之前.............................................
    ");
        printfTeacherInfo(tArray, 3);
        
        // 排序
        sortTeacherArray(tArray,3);
    
        printf("排序之后.............................................
    ");
        printfTeacherInfo(tArray, 3);
    
        free(tArray);
    
        system("pause");
    
        return 0;
    }

    运行:

    【重点!!!-在堆区实现结构体元素的赋值,排序和打印(结构体作为函数参数)】

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #pragma warning(disable:4996)
    
    typedef struct _Teacher
    {
        char *name;
    }Teacher;
    
    int createTeacherArray(Teacher **myTeacher)
    {
        *myTeacher = malloc(3 * sizeof(Teacher));
        return 0;
    }
    
    
    int freeTeacherArray(Teacher **myTeacher)
    {
        free(*myTeacher);
    }
    
    void main()
    {
        Teacher *p2 = NULL;
        createTeacherArray(&p2);
        freeTeacherArray(&p2);
        system("pause");
    }

    三.结构体成员域中含有一级指针

    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    #pragma warning(disable:4996)
    
    
    typedef struct _Teacher
    {
        char name[62];
        char c;
        char *nickName;
        int age;
    }Teacher;
    
    
    /*打印年龄*/
    void printfTeacherInfo(Teacher *tArray, int num)
    {
        int i = 0;
        for (i = 0; i < num; i++)
        {
            printf("第%d个老师的年龄为%d
    ", i + 1, tArray[i].age);
            printf("第%d个老师的昵称为%s
    ", i + 1, tArray[i].nickName);
        }
    }
    
    
    void sortTeacherArray(Teacher *tArray, int num)
    {
        int i = 0,j = 0;
        Teacher tmp;
        if (tArray != NULL)
        {
            for (i = 0; i < num; i++)
            {
                for (j = i+1; j < num; j++)
                {
                    if (tArray[j].age > tArray[i].age)
                    {
                        tmp = tArray[i];
                        tArray[i] = tArray[j];
                        tArray[j] = tmp;
                    }
                }
            }
        }
    }
    
    
    Teacher* createTarray(int num)
    {
        Teacher *tArray = (Teacher *)malloc(num * sizeof(Teacher));
        if (tArray != NULL)
        {
            for (int i = 0; i < num; i++)
            {
                tArray[i].nickName = (char *)malloc(100 * sizeof(char));
            }
        }
        return tArray;
    }
    
    
    // 在堆区实现结构体元素的赋值,排序和打印
    int main()
    {
        Teacher *tArray = createTarray(3);
        int i = 0, j = 0;
        Teacher tmp;
    
        if (tArray != NULL)
        {
            for (i = 0; i < 3; i++)
            {
                printf("请输入第%d个老师的年龄:",i+1);
                scanf("%d", &tArray[i].age);
                printf("请输入第%d个老师的昵称:",i+1);
                scanf("%s", tArray[i].nickName);
            }
        }
    
        printf("排序之前.............................................
    ");
        printfTeacherInfo(tArray, 3);
        
        // 排序
        sortTeacherArray(tArray,3);
    
        printf("排序之后.............................................
    ");
        printfTeacherInfo(tArray, 3);
    
        free(tArray);
    
        system("pause");
    
        return 0;
    }

    运行

    注意:

    1.只有分配内存块才可以使用指针!

    2.buffer与指针的最大区别

    typedef struct _Teacher
    {
        char name[62];             //这里已经分配了62个字节的内存
        char c;
        char *nickName;            //这里只分配了4个字节的变量,还没有分配内存!
        int age;
    }Teacher;

    四.结构体成员域中含有二级指针

    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    #pragma warning(disable:4996)
    
    
    typedef struct _Teacher
    {
        char name[62];                           // <<< 老师名字
        char c;                                  // <<< 老师性别
        char *nickName;                          // <<< 老师真实姓名
        char **releStudent;                      // <<< 老师教的学生
        int age;                                 // <<< 老师年龄
    }Teacher;
    
    
    
    /*打印年龄*/
    void printfTeacherInfo(Teacher *tArray, int num)
    {
        int i = 0,j = 0;
        for (i = 0; i < num; i++)
        {
            printf("第%d个老师的年龄为%d
    ", i + 1, tArray[i].age);
            printf("第%d个老师的昵称为%s
    ", i + 1, tArray[i].nickName);
            
            for (j = 0; j < 3; j++)
            {
                printf("该老师所带的第%d个学生的名字为:%s
    ",j+1,tArray[i].releStudent[j]);
            }
    
        }
    }
    
    
    void sortTeacherArray(Teacher *tArray, int num)
    {
        int i = 0,j = 0;
        Teacher tmp;
        if (tArray != NULL)
        {
            for (i = 0; i < num; i++)
            {
                for (j = i+1; j < num; j++)
                {
                    if (tArray[j].age > tArray[i].age)
                    {
                        tmp = tArray[i];
                        tArray[i] = tArray[j];
                        tArray[j] = tmp;
                    }
                }
            }
        }
    }
    
    
    // 在堆区创建老师数组
    Teacher* createTarray(int num)
    {
        Teacher *tArray = (Teacher *)malloc(num * sizeof(Teacher));
        int i = 0,j = 0;
    
        if (tArray != NULL)
        {
            for (i = 0; i < num; i++)
            {
                tArray[i].nickName = (char *)malloc(100 * sizeof(char));
    
                char **pReleStudent = (char **)malloc(3 * sizeof(char *));
                for (j = 0; j < num; j++)
                {
                    pReleStudent[j] = (char *)malloc(50 * sizeof(char));
                }
    
                tArray[i].releStudent = pReleStudent;
    
            }
        }
        return tArray;
    }
    
    
    // 释放老师数组
    void freeTarray(Teacher *tArray, int num)
    {
        if (tArray != NULL)
        {
            int i = 0,j = 0;
            // free 真实姓名
            for (i = 0; i < num; i++)
            {
                char *pNickName = tArray[i].nickName;
                if (pNickName != NULL) free(pNickName);
    
                // free 老师教的学生&每个学生的名字
                char **pReleStudent = tArray[i].releStudent;
                if (pReleStudent != NULL)
                {
                    for (j = 0; j < 3; j++)
                    {
                        char *student = pReleStudent[j];
                        if (student != NULL) free(student);
                    }
                    free(pReleStudent);
                }
    
            }
            free(tArray);
        }
    
    }
    
    
    
    
    // 在堆区实现结构体元素的赋值,排序和打印
    int main()
    {
        Teacher *tArray = createTarray(3);
        int i = 0, j = 0;
        Teacher tmp;
    
        printf("*******************木叶师生关系*******************
    ");
        printf("
    ");
        if (tArray != NULL)
        {
            for (i = 0; i < 3; i++)
            {
                printf("请输入第%d个老师的昵称:", i + 1);
                scanf("%s", tArray[i].nickName);
    
                printf("请输入第%d个老师的年龄:",i+1);
                scanf("%d", &tArray[i].age);
                
                for (j = 0; j < 3; j++)
                {
                    printf("请录入该老师所带的第%d个学生的姓名:",j+1);
                    scanf("%s",tArray[i].releStudent[j]);
                }
    
            }
        }
    
        printf("排序之前.............................................
    ");
        printfTeacherInfo(tArray, 3);
        
        // 排序
        sortTeacherArray(tArray,3);
    
        printf("排序之后.............................................
    ");
        printfTeacherInfo(tArray, 3);
    
        // 释放内存
        freeTarray(tArray,3);
    
        system("pause");
    
        return 0;
    }

    运行:

    五.结构体中的浅拷贝和深拷贝

    先看下面的代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #pragma warning(disable:4996)
    
    
    typedef struct _Teacher
    {
        char *name;
        int age;
    }Teacher;
    
    
    
    
    void main()
    {
    
        Teacher t1, t2;
        t1.name = (char *)malloc(100);
        t1.age = 10;
    
        t2 = t1;
        
        if (t1.name != NULL)
        {
            free(t1.name);
        }
    
        if (t2.name != NULL)
        {
            free(t2.name);
        }
    
        system("pause");
    }

    运行,发现程序crach掉了,crash的位置在free(t2.name)这里,crach的原因在t2=t1这一行,因为普通的C++编译器提供的拷贝行为,只是一个简单的复制(浅拷贝,指针变量的拷贝)。当结构体成员中含有buf的时候也是没有问题的,但是当结构体成员中含有指针的时候,C++编译器只会进行指针变量的拷贝,却不会拷贝指针变量所指向的内存空间,这就是编译器的浅拷贝行为。

    在本例中,将t1的值拷贝给t2的话,只会将t1.name所保存的指针地址拷贝给t2.name,却不会再额外再开辟新的内存空间,因此当t1.name所指向的内存空间free掉了之后,t2.name再去free,程序就crash掉了。下面给出一种简单的深拷贝方法:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #pragma warning(disable:4996)
    
    
    typedef struct _Teacher
    {
        char *name;
        int age;
    }Teacher;
    
    
    
    void copyT1T2(Teacher *from, Teacher *to)
    {
    
        memcpy(to, from, sizeof(Teacher));
        to->name = (char *)malloc(100);
        strcpy(to->name, from->name);
    
    }
    
    void main()
    {
    
        Teacher t1, t2;
        t1.name = (char *)malloc(100);
        t1.age = 10;
    
        copyT1T2(&t1, &t2);
        
        if (t1.name != NULL)
        {
            free(t1.name);
        }
    
        if (t2.name != NULL)
        {
            free(t2.name);
        }
    
        system("pause");
    }

    即自己编写拷贝行为,这样t1.name和t2.name都有独立的内存空间,再次运行,程序就不会再crach了。

  • 相关阅读:
    Linux 显示当前时间
    Jenkins 更改工作目录;
    Jenkins 编译 .net 项目
    Jenkins 通过 maven 构建编译 JAVA 项目环境
    Jenkins
    Zatree
    Zabbix 邮件报警示例
    Zabbix 短信报警示例
    Linux 检测出口IP地址
    数据结构与算法面试题80道(4)
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/6858477.html
Copyright © 2011-2022 走看看