《C语言高级》(三)------ 结构体、联合体、枚举与预处理

目录

一、结构体、联合体和枚举

1.1、创建和使用结构体

1.2、结构体数组和指针

1.3、联合体

1.4、枚举

1.5、typedef关键字

二、预处理

2.1、系统库介绍

2.2、宏定义

2.3 条件编译


一、结构体、联合体和枚举

我们之前认识过很多种数据类型,包括整数、小数、字符、数组等,通过使用对应的数据类型,我们就可以很轻松地将我们的数据进行保存了,但是有些时候,这种简单类型很难去表示一些复杂结构。

1.1、创建和使用结构体

比如我们现在要保存100个学生的信息(学生信息包括学号、姓名、年龄)我们发现似乎找不到一种数据类型能够同时保存这三种数据(数据虽然能保存一些列的元素,但是只能保存同种类型的)。但是如果把它们拆开单独存在,就可以使用对应的类型存放了,不过这样很不方便,这些数据应该是捆绑在一起的,而不是单独地去存放。所以,为了解决这种问题,C语言提供了结构体类型,它能够将多种类型的数据集结到一起,让他们形成一个整体。

#include 

//使用(struct关键字 + 结构体类型名称)来声明结构体类型,这种类型是我们自己创建的(同样也可以作为函数的参数,返回值之类)
struct Student {
    int id;  // 结构体中可以包含多个不同类型的数据,这些数据共同组成了整个结构体类型(当然结构体内部也能包含结构体类型的变量)
    int age;
    char * name;  //用户名可以用指针指向一个字符串,也可以用char数组来存,如果是指针的话,那么数据不会存在结构体中,只会存放字符串的地址,但是如果是数组的话,数据会存放在结构体中
};

int main(){
    struct Student student = {1, 18, "小明"};
}

那么现在我们拿到结构体变量后,怎么去访问结构体内部存储的各种数据呢

int main(){
    struct Student student = {1, 18, "小明"};
    int a = student.age;
    printf("%d", a);
}

那么结构体在内存中占据的大小是如何计算的呢?比如下面的这个结构体

struct Object {
    int a;
    short b;
    char c;

}

这里我们可以借助sizeof关键字来帮助我们进行计算:

int main() {

    printf("int类型的大小是:%lu", sizeof(int));
}

1.2、结构体数组和指针

前面我们介绍了结构体,现在我们可以将各种类型的数据全部安排到结构体中一起存放了。

不过仅仅只是使用结构体还不够,我们可能需要保存很多个学生的信息,所以我们需要使用结构体类型的数组来进行保存:

#include 

//使用(struct关键字 + 结构体类型名称)来声明结构体类型,这种类型是我们自己创建的(同样也可以作为函数的参数,返回值之类)
struct Student {
    int id;  // 结构体中可以包含多个不同类型的数据,这些数据共同组成了整个结构体类型(当然结构体内部也能包含结构体类型的变量)
    int age;
    char * name;  //用户名可以用指针指向一个字符串,也可以用char数组来存,如果是指针的话,那么数据不会存在结构体中,只会存放字符串的地址,但是如果是数组的话,数据会存放在结构体中
};

int main(){
    struct Student arr[3] = {{1, 18, "小明"},
                             {2, 17, "小红"},
                             {3, 18, "小刚"}};

    printf("%s", arr[1].name);
}
#include 

//使用(struct关键字 + 结构体类型名称)来声明结构体类型,这种类型是我们自己创建的(同样也可以作为函数的参数,返回值之类)
struct Student {
    int id;  // 结构体中可以包含多个不同类型的数据,这些数据共同组成了整个结构体类型(当然结构体内部也能包含结构体类型的变量)
    int age;
    char * name;  //用户名可以用指针指向一个字符串,也可以用char数组来存,如果是指针的话,那么数据不会存在结构体中,只会存放字符串的地址,但是如果是数组的话,数据会存放在结构体中
};

int main(){
    struct Student student = {1, 18, "小明"};
    struct Student * p = &student;  //同样的,类型后面加上*就是一个结构体类型的指针了
    printf("%s", (*p).name);  //由于.运算符优先级更高,所以需要先使用*p得到地址上的值,然后再去访问对应数据
}

同样,指针还有简便写法

int main(){
    struct Student student = {1, 18, "小明"};
    struct Student * p = &student;  //同样的,类型后面加上*就是一个结构体类型的指针了
    printf("%s", (*p).name);  //由于.运算符优先级更高,所以需要先使用*p得到地址上的值,然后再去访问对应数据
    printf("%s", p -> name);  //使用 -> 运算符来快速将指针所指结构体的对应数据取出
}

1.3、联合体

联合体也可以在内部定义很多种类型的变量,但是它与结构体不同的是,所有的变量共用同一个空间。

#include 
union Object{
    int a;
    char b;
    float c;
};

int main() {
    union Object object;
    object.a = 66;
    printf("%d", object.b);


}

1.4、枚举

枚举类型一般用于表示一些预设好的整数常量,比如我们风扇有低、中

高三个档位,我们总是希望别人使用我们预设好的这三个档位,而不希望使用其他的档位,因为我们风扇就只设计了这三个档位。

#include 
//比如我们现在设计:1 = 低档位  2 = 中档位  3 = 高档位
//enum 枚举类型名称 {枚举 = 初始值, 枚举....}
enum status {low = 1, middle = 2, high = 3};

int main() {

    enum status a = high;
    if(a == low){ printf("低档位");}
    else if (a == high) {
        printf("高档位");
    } else {
        printf("中档位");
    }

}

1.5、typedef关键字

这个关键字用于给指定的类型起别名

#include 
typedef int lbwnb;

int main() {
    lbwnb i = 666;
    printf("%d", i);
    
}

二、预处理

2.1、系统库介绍

前面我们介绍了如何使用#include 引入其他文件,我们接着来了解一下系统为我们提供的一些常用库。实际上我们已经使用过不少官方库提供的内容了

#include 
int main() {
    int a;
    scanf("%d", &a);
    printf("%d", a);
    getchar();
    putchar('A');
}

包括我们在实战中用到了一次string.h中提供的计算字符串长度的函数

#include 
#include 
int main() {
    char *c = "hello world";
    printf("%lu", strlen(c));
}
#include 
#include 
int main() {
    //现在有两个字符串,我们希望把他们拼接到一起
    char a[20] = "hello", *b = "world";
    //注意不能写 char *a = "world", *b = "world";
    //如果直接用指针指向字符串常量,是无法进行拼接的,因为大小已经固定
    //这里需要两个参数,第一个是目标字符串,将会将第二个参数的字符串拼接到第一个字符串中,注意要装得下
    strcat(a, b);
    printf("%s", a);
}

还有关于处理数学问题的相关库

#include 
#include 
int main() {
    int a = 2;
    double d = sqrt(a);
    printf("%lf", d);
}
#include 
#include 
int main() {
    double x = 3.14;
    printf("不小于x的最小整数:%f\n", ceil(x));
    printf("不大于x的最大整数:%f\n", floor(x));
}

2.2、宏定义

前面我们认识了#include指令,我们接着来看#define指令,它可以实现宏定义

#include 
#define PI 3.1415926
int main() {
    printf("Π的值为:%f", PI);
}

2.3 条件编译

我们来看看条件编译,我们还可以根据条件,选择性地对某些内容进行忽略

#include 

#ifdef PI //ifdef用于判断是否定义了符号PI,如果没有的话则处理以下指令
#define M 666

#else  //如果没有定义了符号PI,那么就处理这个分支的语句
#define M 777

#endif  //最后以endif结束整个判断
int main() {
    printf("%d", M);
}

你可能感兴趣的:(数据结构与算法,c语言,c++,开发语言)