C语言笔记13

161 阅读4分钟

结构 struct

由多个数据类型组成的数据类型
关键词struct
声明格式类似int 即在结构类型后填写变量名
访问时使用成员运算符.字段名

#include<stdio.h>
#include<string.h>
int main()
{
        struct {
                char name[20];
                int gender;
                double height;
                double weight;
        }timmy;

        //将timmy的数据装入结构变量
        strcpy(timmy.name, "timmy");
        timmy.gender = 1;
        timmy.height = 170.00;
        timmy.weight = 60;

        //从结构变量中显示timmy的数据
        printf("%s\n", timmy.name);
        printf("%d\n", timmy.gender);
        printf("%.2f\n", timmy.height);
        printf("%.2f\n", timmy.weight);
}  

结构别名

如果要定义多个内部成员一致的结构变量 则可以只声明一次结构类型 结构类型声明取一个别名 放在struct后面 相当于造了一个模板 后续声明该结构类型的变量时只需struct加别名
但如果结构类型声明在一个函数中 那么别名只能在函数内部使用 如果需要在多个函数中使用结构别名 则需要把它放在函数外面

struct person{
        char name[20];
        int gender;
	double height;
	double weight;
    };

struct person timmy;
struct person david;  

初始化结构

可在声明时初始化 类似数组初始化 在声明时加等号与初始化列表

  • 初始化列表由花括号包括
  • 花括号内为结构成员需要被初始化的值
  • 初始化值按照结构成员声明时的顺序依次排列
  • 每个初始化值之间用逗号分隔
struct person timmy = {"timmy",1,170.00,60.00};

结构数组

结构类型+[元素个数]

struct person people[3];

可用初始化列表初始化数组 模式如下

struct person people[3] = {
	{"timmy",1,170.00,60.00},
	{"david",1,175.00,65.00},
	{"jane",2,165.00,55.00}
};

也可以对结构使用赋值

struct person per = people[i];

也可以用结构初始化结构

struct person per;
per = people[i];

方括号加下标访问结构数组中的元素

people[i]  

嵌套结构

把结构作为结构的成员

#include<stdio.h>
#include<string.h>
    
int main()
{
        struct contact {
                char phone[20];
                char email[20];
        };

        //通讯方式为结构的第五个成员 
        struct person{
                char name[20];
                int gender;
                double height;
                double weight;
                struct contact c;
        };

        //在人员初始化列表的第五个位置填写通讯方式的初始化列表
        struct person timmy = {
                "timmy",1,170.0,60.00,{"12345678912","timmy@xxx.com"}
        };
    
        //.字段名访问元素 
        printf("%s\n", timmy.name);
        printf("%d\n", timmy.gender);
        printf("%.2f\n", timmy.height);
        printf("%.2f\n", timmy.weight);
        printf("%s\n", timmy.c.phone);
        printf("%s\n", timmy.c.email);
            
        return 0;
}

指向结构的指针

//声明
struct person* ptimmy = &timmy;
//使用时可先把指针转化成结构再使用
printf("%s\n", (* ptimmy).name);//成员运算符.高于取值运算符* 因此要用()包括

使用成员间接运算符->更简便

(* ptimmy).name等价于ptimmy->name     

printf("%s\n", ptimmy->name);

结构在函数中传递

不同函数中的参数相互独立 因此要通过指针实现传递与修改

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

struct person{
                char name[20];
                int gender;
                double height;
                double weight;
        };

void change(struct person*per)
{
        strcpy(per->name, "david");
        per->gender = 1;
        per->height = 175.00;
        per->weight = 65.00;
}
int main()
{
        struct person timmy = { "timmy",1,170.00,60.00 };
        change(&timmy);//将timmy的指针传入change函数
        
        printf("%s\n", timmy.name);
        printf("%d\n", timmy.gender);
        printf("%.2f\n", timmy.height);
        printf("%.2f\n", timmy.weight);
           
        return 0;
}

将结构从函数中返回然后赋值给timmy也可以

#include<stdio.h>
#include<string.h>
    
struct person{
        char name[20];
	int gender;
	double height;
	double weight;
    };

struct person change()
{
        struct person per;
        strcpy(per.name, "david");
        per.gender = 1;
        per.height = 175.00;
        per.weight = 65.00;
        return per;//函数返回结构per
}
    
int main()
{
        struct person timmy = { "timmy",1,170.00,60.00 };

        timmy=change();//把函数返回的结构赋值给timmy

        printf("%s\n", timmy.name);
        printf("%d\n", timmy.gender);
        printf("%.2f\n", timmy.height);
        printf("%.2f\n", timmy.weight);

        return 0;
}

联合 union

关键词union
声明类似struct 但联合中成员首地址是重叠的 共用一段内存 因此联合的大小为联合中最大成员的大小

性质

储存一个成员后 将覆盖其他成员的数据 因此联合也被称为共用

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

int main()
{
        union {
                char c;
                short s;
                long long ll;
        }u;
        u.c = 123;
        printf("u.c=%d\n", u.c);//u.c=123
        u.s = 0;
        printf("u.c=%d\n", u.c);//u.c=0
}

应用举例

有一个信息有三种形式 整数 浮点数 字符串 如果使用结构 则需要准备三个不同类型的成员 每次只出现一种形态 所以每次只使用一个成员 另外两个留空 占用内存较大 另外需要整型成员type来标记类型
此时可以使用union将三个不同类型的成员合三为一 同时使用type标记类型

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

struct message
{
        int type;
        union {
                int n;
                double f;
                char* str;
        }u;
};

void printmsg(struct message msg)
{
        switch (msg.type)
        {
        case 1:
                printf("%d\n", msg.u.n);
                break;
        case 2:
                printf("%f\n", msg.u.f);
                break;
        case 3:
                printf("%s\n", msg.u.str);
                break;
        }
}
int main()
{
        struct message msg[3];
        msg[0].type = 1;
        msg[0].u.n = 123;
        msg[1].type = 2;
        msg[1].u.f = 3.14;
        msg[2].type = 1;
        msg[2].u.str = "helloworld";
        
        for (int i = 0; i < 3; i++)
        printmsg(msg[i]);
        return 0;
}

还有一种匿名嵌套的写法 即省略union的成员名u union中的成员当作message的成员一样处理

struct message
{
        int type;
        union {
                int n;
                double f;
                char* str;
        };//省去成员名u 作为匿名嵌套成员
};

void printmsg(struct message msg)
{
        switch (msg.type)
        {
        case 1:
                printf("%d\n", msg.n);//msg.u.n省略为msg.n
                break;
        case 2:
                printf("%f\n", msg.f);//msg.u.f省略为msg.f
                break;
        case 3:
                printf("%s\n", msg.str);//msg.u.s省略为msg.s
                break;
        }
}

枚举 enum

关键词enum
一种特殊的整型 枚举类型 关键词为enum
把数字123用有意义的英文替代 比如1对应integer 2对应float
声明类似struct

枚举是特殊的整型

//枚举从0开始依次递增
#include<stdio.h>
#include<string.h>

enum msgtype
{
        einteger,
        efloat,
        estring
};

int main()
{
        printf("%d\n", einteger);//0
        printf("%d\n", efloat);//1
        printf("%d\n", estring);//2
        return 0;
}

如果要从1开始递增 只需在einteger后加=1
也可以指定每一个枚举中每个成员对应的数值

应用举例

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

enum msgtype
{
        einteger,
        efloat,
        estring
};

//用枚举代替数字
struct message
{
    enum msgtype type;
    union {
        int n;
        double f;
        char* str;
    }u;
};
    
//拿到信息后判断是哪一个枚举值
void printmsg(struct message msg)
{
    switch (msg.type)
    {
    case einteger:
        printf("%d\n", msg.u.n);
        break;
    case efloat:
        printf("%f\n", msg.u.f);
        break;
    case estring:
        printf("%s\n", msg.u.str);
        break;
    }
}
//使用枚举进行赋值
int main()
{
    struct message msg[3];
    msg[0].type = einteger;
    msg[0].u.n = 123;
    msg[1].type = efloat;
    msg[1].u.f = 3.14;
    msg[2].type = estring;
    msg[2].u.str = "helloworld";
    
    for (int i = 0; i < 3; i++)
        printmsg(msg[i]);
    return 0;
}