C语言 结构体

C语言 结构体

数组:描述一组具有相同类型数据的有序集合,用于处理大量相同类型的数据运算。

有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性。显然单独定义以上变量比较繁琐,数据不便于管理。

C语言中给出了另一种构造数据类型——结构体。

结构体变量定义初始化

一、定义结构体变量的方式

  • 先声明结构体类型再定义变量名
  • 在声明类型的同时定义变量
  • 直接定义结构体类型变量(无类型名)

二、 结构体类型和结构体变量关系

  • 结构体类型:指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元。
  • 结构体变量:系统根据结构体类型(内部成员状况)为之分配空间。

三、结构体案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// struct 结构体名
// {
// 结构体成员列表
//    姓名
//  年龄
//  成绩
// };

struct student
{
    char name[21];
    int age;
    int score;
    char addr[51];
};
// 方式三
// 创建全局变量
// stu = { "张三",18,100,"北京市昌平区北清路22号" };

int main(void)
{
    // 方式一
    // 创建结构体变量
    // 结构体类型 名称 结构体变量
    // struct student stu;
    // 数组结构体变量为常量:不能直接复制stu.name = "张三"; 
    // 通过拷贝方式赋值变量
    // strcpy(stu.name, "张三");
    // stu.age = 18;
    // stu.score = 100;
    // strcpy(stu.addr, "北京市昌平区北清路22号");

    // 方式二
    struct student stu = { "张三",18,100,"北京市昌平区北清路22号" };

    printf("姓名:%s\n", stu.name);
    printf("年龄:%d\n", stu.age);
    printf("成绩:%d\n", stu.score);
    printf("地址:%s\n", stu.addr);

    return 0;
}
结构体 使用案例:成员使用
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


struct student
{
    char name[21];
    int age;
    int score;
    char addr[51];
};

int main(void)
{
    // 通过键盘获取
    struct student stu;
    // 数组不需要取地址,变量需要取地址
    scanf("%s%d%d%s", stu.name, &stu.age, &stu.score,stu.addr);

    printf("姓名:%s\n", stu.name);
    printf("年龄:%d\n", stu.age);
    printf("成绩:%d\n", stu.score);
    printf("地址:%s\n", stu.addr);

    return 0;
}
结构体 使用案例:键盘获取
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student
{
    // 结构体成员需要偏移对齐
    char name[21];
    int age;
    char sex;
    int score[3];
    char addr[51];
};

int main(void)
{
    // 结构体数组
    struct student stu[]=
    {
        {"蛮王",34,'M',88,99,0,"诺克萨斯"},
        {43,'M',0,0,0,"德玛西亚",.name = "盖伦" },
        {"拉克丝",18,'F',2,2,2,"窑子"}
    };

    // 打印
    for (int i = 0; i < 3; i++)
    {
        printf("姓名:%s\n", stu[i].name);
        printf("年龄:%d\n", stu[i].age);
        printf("性别:%s\n", stu[i].sex == 'M' ? "" : "");
        printf("成绩:%d\n", stu[i].score[0]);
        printf("成绩:%d\n", stu[i].score[1]);
        printf("成绩:%d\n", stu[i].score[2]);
        printf("地址:%s\n\n", stu[i].addr);
    }

    // 通过sizeof求出结构体
    printf("结构体数组大小:%d\n", sizeof(stu));
    printf("结构体数组元素大小:%d\n", sizeof(stu[0]));
    printf("结构体数组元素个数:%d\n", sizeof(stu[0])/sizeof(stu[0]));

    return 0;
}
结构体 使用案例:结构体数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student
{
    char name[21];
    int age;
    char sex;
    int score[3];
    char addr[51];
};

int main(void)
{
    struct student stu[]=
    {
        {"蛮王",34,'M',88,99,0,"诺克萨斯"},
        {.age = 43,'M',0,0,0,"德玛西亚",.name = "盖伦" },
        {"拉克丝",18,'F',2,2,2,"窑子"}
    };

    // 根据年龄排序
    for (int i = 0; i < 3 - 1; i++)
    {
        for (int j = 0; j < 3 - 1 - i; j++)
        {
            if (stu[j].age > stu[j + 1].age)
            {
                struct student temp = stu[j];
                stu[j] = stu[j + 1];
                stu[j + 1] = temp;
            }
        }
    }


    // 打印
    for (int i = 0; i < 3; i++)
    {
        printf("姓名:%s\n", stu[i].name);
        printf("年龄:%d\n", stu[i].age);
        printf("性别:%s\n", stu[i].sex == 'M' ? "" : "");
        printf("成绩:%d\n", stu[i].score[0]);
        printf("成绩:%d\n", stu[i].score[1]);
        printf("成绩:%d\n", stu[i].score[2]);
        printf("地址:%s\n\n", stu[i].addr);
    }

    return 0;
}
结构体 使用案例:结构体排序
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 为 struct student 起别名
typedef struct student ss;

struct student
{
    char name[21];
    int age;
    char sex;
    int score[3];
    char addr[51];
};

int main(void)
{

    // 输出结构体大小
    // printf("%d\n", sizeof(struct student));

    // 创建结构体指针类型的堆空间并指定结构体内存大小
    ss * p = (ss *)malloc(sizeof(ss) * 3);
    prinf("结构体指针大小:%d", sizeof(ss*));

    // 通过键盘存储内容
    for (int i = 0; i < 3; i++)
    {
        scanf("%s%d,%c%d%d%d%s", p[i].name, &p[i].age, &p[i].sex, &p[i].score[0], &p[i].score[1], &p[i].score[2], p[i].addr);
    }

    // 打印
    for (int i = 0; i < 3; i++)
    {
        printf("姓名:%s\n", p[i].name);
        printf("年龄:%d\n", p[i].age);
        printf("性别:%s\n", p[i].sex == 'M' ? "" : "");
        printf("成绩:%d\n", p[i].score[0]);
        printf("成绩:%d\n", p[i].score[1]);
        printf("成绩:%d\n", p[i].score[2]);
        printf("地址:%s\n\n", p[i].addr);
    }

    // 释放内存
    free(p);

    return 0;
}
结构体 使用案例:结构体堆空间使用
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 游戏案例
/*
struct 技能
{
    名称
    等级
    伤害
    范围
    消耗
    冷却
}

struct 人物信息
{
    等级
    经验
    金钱
    hp
    mp
    力量
    智力
    敏捷
    struct 技能 skills[4]
}

struct 人物信息 info;
info.skills[0].名称

*/

struct scores
{
    int c1;//c语言
    int cpp;//c++
    int cs;//c#
};

struct student
{
    char name[21];
    int age;
    struct scores ss;
    char addr[51];
};

int main(void)
{
    // 赋值
    struct student stu = { "貂蝉",18,99,99,99,"徐州" };
    // 打印
    printf("%s\n%d\n%d\n%d\n%d%\n%s\n", stu.name, stu.age, stu.ss.c1, stu.ss.cpp, stu.ss.cs,stu.addr);

    // 赋值
    strcpy(stu.name, "小乔");
    stu.age = 16;
    stu.ss.c1 = 88;
    stu.ss.cpp = 88;
    stu.ss.cs = 88;
    strcpy(stu.addr, "江东");
    // 打印
    printf("%s\n%d\n%d\n%d\n%d%\n%s\n", stu.name, stu.age, stu.ss.c1, stu.ss.cpp, stu.ss.cs, stu.addr);

    printf("学生结构体大小%d\n",sizeof(stu));
    printf("学生结构体大小%d\n", sizeof(stu.ss));
    printf("名称数组大小%d\n", sizeof(stu.name));


    return 0;
}
结构体 使用案例:结构体嵌套结构体
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student
{
    char name[21];
    int age;
    int score;
    char addr[51];
};

int main(void)
{
    // 赋值
    struct student stu = {"孙嫩香",26,60,"巴蜀"};
    // 赋值变量
    struct student s1 = stu;
    
    // 深拷贝和浅拷贝
    strcpy(s1.name, "甘夫人");
    s1.age = 28;
    s1.score = 80;

    // 输出
    printf("%s\n", stu.name);
    printf("%d\n", stu.age);
    printf("%d\n", stu.score);

    
    return 0;
}
结构体 使用案例:结构体赋值
#include<stdio.h>
#include <string.h>
 
//结构体类型的定义
struct stu
{
       char name[50];
       int age;
};
 
//函数参数为结构体普通变量
void set_stu(struct stu tmp)
{
       strcpy(tmp.name, "mike");
       tmp.age = 18;
       printf("tmp.name = %s, tmp.age = %d\n", tmp.name, tmp.age);
}
 
int main()
{
       struct stu s = { 0 };
       set_stu(s); //值传递
       printf("s.name = %s, s.age = %d\n", s.name, s.age);
 
       return 0;
}
结构体 使用案例:结构体普通变量做函数参数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


typedef struct student ss;
struct student
{
    // char name[21]
    char *name;
    int age;
    int score;
    char addr[51];
};

void fun(ss stu)
{
    strcpy(stu.name, "卢俊义");
}


int main(void)
{
    ss stu = { NULL,50,101,"水泊梁山" };
    stu.name = (char*)malloc(sizeof(char) * 21);
    strcpy(stu.name, "松江");
    printf("%s\n", stu.name);
    fun(stu);
    printf("%s\n", stu.name);

    return 0;
} 
结构体 使用案例:结构体普通变量做函数参数 2

结构体和指针

一、说明

通过指针结合结构体进行操作

二、案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 结构体称为为指针类型
struct student
{
    char* name;
    int age;
    int *scores;
    char* addr;
};

int main(void)
{
    struct student stu;

    // 常量:stu.name = "张春生";//err
    // 开辟堆空间
    stu.name = (char*)malloc(sizeof(char) * 21);
    stu.scores = (int*)malloc(sizeof(int) * 3);
    stu.addr = (char*)malloc(sizeof(char) * 51);

    // 赋值
    strcpy(stu.name, "张三");
    stu.age = 18;
    stu.scores[0] = 88;
    stu.scores[1] = 99;
    stu.scores[2] = 100;
    strcpy(stu.addr, "北京市");

    // 打印
    printf("%s\n", stu.name);
    printf("%d\n", stu.age);
    printf("%d\n", stu.scores[0]);
    printf("%d\n", stu.scores[1]);
    printf("%d\n", stu.scores[2]);
    printf("%s\n", stu.addr);

    // 释放内存
    free(stu.name);
    free(stu.scores);
    free(stu.addr);

    return 0;
}
结构体和指针 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// 结构体称为为指针类型
struct student
{
    char name[21];
    int age;
    int scores[3];
    char addr[51];
};

int main(void)
{
    // 结构体指针
    struct student stu = {"林冲",30,100,100,100,"边境"};

    // 赋值结构体指针
    struct student * p = &stu;

    // 打印值
    // printf("%s\n", (*p).name);
    // printf("%d\n", (*p).age);
    // 结构体指针->成员
    // 结构体变量.成员
    printf("%s\n", p->name);
    printf("%d\n", p->age);
    printf("%d\n", p->scores[0]);
    printf("%d\n", p->scores[1]);
    printf("%d\n", p->scores[2]);
    printf("%s\n", p->addr);

    return 0;
}
结构体和指针 使用案例:2
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
 
//结构体类型的定义
struct stu
{
       char name[50];
       int age;
};
 
int main()
{
       struct stu *p = NULL;
 
       p = (struct stu *)malloc(sizeof(struct  stu));
 
       //如果是指针变量,通过->操作结构体成员
       strcpy(p->name, "test");
       p->age = 22;
 
       printf("p->name = %s, p->age=%d\n", p->name, p->age);
       printf("(*p).name = %s, (*p).age=%d\n", (*p).name,  (*p).age);
 
       free(p);
       p = NULL;
 
       return 0;
}
结构体和指针 使用案例:堆区结构体变量
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


typedef struct student ss;
struct student
{
    char* name;
    int age;
    int* scores;
    char* addr;
};

int main(void)
{
    // 开辟 结构体堆空间
    ss* p = (ss*)malloc(sizeof(ss) * 3);

    // 开辟 结构体成员堆空间
    for (int i = 0; i < 3; i++)
    {
        (p + i)->name = (char*)malloc(sizeof(char*) * 21);
        (p + i)->scores = (int*)malloc(sizeof(int) * 3);
        (p + i)->addr = (char*)malloc(sizeof(char*) * 51);
    }

    // 赋值
    for (int i = 0; i < 3; i++)
    {
        scanf("%s%d%d%d%d%s", p[i].name, &p[i].age, &p[i].scores[0], &p[i].scores[1], &p[i].scores[2], &p[i].addr);
    }

    // 输出
    for (int i = 0; i < 3; i++)
    {
        printf("%s\n", p[i].name);
        printf("%d\n", p[i].age);
        printf("%d\n", p[i].scores[0]);
        printf("%d\n", (p + i)->scores[1]);
        printf("%d\n", (p + i)->scores[2]);
        printf("%s\n", (p + i)->addr);
    }

    // 释放堆空间内层
    for (int i = 0; i < 3; i++)
    {
        free(p[i].name);
        free(p[i].scores);
        free(p[i].addr);
    }

    // 释放外层
    free(p);

    return 0;
}
结构体和指针 使用案例:结构体套一级指针
#include<stdio.h>
#include <string.h>
 
//结构体类型的定义
struct stu
{
       char name[50];
       int age;
};
 
//函数参数为结构体指针变量
void set_stu_pro(struct stu *tmp)
{
       strcpy(tmp->name, "mike");
       tmp->age = 18;
}
 
int main()
{
       struct stu s = { 0 };
       set_stu_pro(&s); //地址传递
       printf("s.name = %s, s.age = %d\n", s.name, s.age);
 
       return 0;
}
结构体和指针 使用案例:结构体指针变量做函数参数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


typedef struct student ss;
struct student
{
    char name[21];
    //char *name;
    int age;
    int score;
    char addr[51];
};

void fun(ss * p)
{
    strcpy(p->name, "公孙胜");
}

int main(void)
{
    // 结构体指针作为函数参数传递
    ss stu = { "吴用",50,101,"水泊梁山" };
    printf("%s\n", stu.name);
    fun(&stu);
    printf("%s\n", stu.name);
    return 0;
}
结构体和指针 使用案例:结构体指针变量做函数参数 2
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


typedef struct student ss;
struct student
{
    char name[21];
    int age;
    int score[3];
    char addr[51];
};

// 数组作为函数参数退化为指针、丢失元素静度、需要传递个数
void BubbleSort(ss * stu, int len)
{
    for (int i = 0; i < len - 1; i++)
    {
        for (int j = 0; j < len - i - 1; j++)
        {
            // if(stu[j].age>stu[j+1].age)
            if ((stu + j)->age > (stu + j + 1)->age)
            {
                ss temp = stu[j];
                stu[j] = stu[j + 1];
                stu[j + 1] = temp;
            }
        }
    }
}

int main(void)
{
    ss stu[3] = 
    { 
        { "鲁智深",30,33,33,33,"五台山" },
        { "呼延灼",45,33,33,33,"汴京" },
        { "顾大嫂",22,33,33,33,"汴京" },
    };

    // 传递结构体数组、 名称、通过函数排序
    BubbleSort(stu, 3);

    // 输出
    for (int i = 0; i < 3; i++)
    {
        printf("姓名:%s\n", stu[i].name);
        printf("年龄:%d\n", stu[i].age);
        printf("成绩:%d\n", stu[i].score[0]);
        printf("成绩:%d\n", (stu + i)->score[1]);
        printf("成绩:%d\n", (stu + i)->score[2]);
        printf("地址:%s\n", (stu + i)->addr);
    }
    return 0;
}
结构体和指针 使用案例:结构体数组名做函数参数
//结构体类型的定义
struct stu
{
       char name[50];
       int age;
};
 
void fun1(struct stu * const p)
{
       //p = NULL; //err
       p->age = 10; //ok
}
 
//void fun2(struct stu const*  p)
void fun2(const struct stu *  p)
{
       p = NULL; //ok
       //p->age = 10; //err
}
 
void fun3(const struct stu * const p)
{
       //p = NULL; //err
       //p->age = 10; //err
}
结构体和指针 使用案例:const修饰结构体指针形参变量

 

posted @ 2020-02-29 10:25  kevin.Xiang  阅读(455)  评论(0编辑  收藏  举报