C语言笔记(八)

1、为什么要使用结构体

思考:输入输出10个学生的年龄

数据模型:数组

操作:循环

思考:年龄只是学生的一个属性,如果想描述学生所有的信息

姓名 char name[20];

学号 int num;

性别 char sex;

年龄 int age;

成绩 float score;

住址 char addr[100];

为什么使用结构体类型:当程序中出现大量不同(相同)数据类型变量时,这些变量合在一起可以描述某些信息,通过结构体类型对这些不同变量进行整体的声明


2、结构体类型的声明

格式:

struct 结构体名

{

成员列表;

};

struct:声明结构体类型的关键字,不能够省略

struct 结构体名:结构体类型

成员列表:多个数据类型,变量名

例子:

姓名 char name[20];

学号 int num;

性别 char sex;

年龄 int age;

成绩 float score;

住址 char addr[100];


struct student

{

char name[20];

int num;

char sex;

int age;

float score;

char addr[100];

};


名字

{

代码;

}

注意:

结构体类型的声明只是相当于系统下创建一个新的数据类型,但是并没有定义出该类型下的变量,所以不会开辟任何的存储空间

#include <stdio.h>


#define NAME_SIZE 20

#define ADDR_SIZE 50


struct student

{

char name[NAME_SIZE];//姓名

int num;//学号

char sex;//性别

int age;//年龄

float score;//成绩

char addr[ADDR_SIZE];//地址

};//结构体类型的声明


struct teacher

{

char name[NAME_SIZE];

int age;

char sex;

};


struct birthday

{

int year;

int month;

int day;

};



int main(int argc, const char *argv[])

{

return 0;

}

练习:

1、定义出描述老师相关属性的结构体

struct teacher

{

char name[20];

char sex;

int age;

};

2、定义出描述生日的结构体(年、月、日)

struct birthday

{

int year;

int month;

int day;

};


补充:

1:结构体类型成员名可以和系统中的变量名相同

2:结构体成员也可以是其他类型的结构体变量

#include <stdio.h>


#define NAME_SIZE 20

#define ADDR_SIZE 50


struct birthday

{

int year;

int month;

int day;

};

struct student

{

char name[NAME_SIZE];//姓名

int num;//学号

char sex;//性别

int age;//年龄

float score;//成绩

char addr[ADDR_SIZE];//地址

struct birthday bd;//生日

};//结构体类型的声明


int main(int argc, const char *argv[])

{

return 0;


3、结构体类型变量的定义

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

2:先声明结构体类型再定义结构体变量(常用

#include <stdio.h>


#define NAME_SIZE 20

#define ADDR_SIZE 50


struct student

{

char name[NAME_SIZE];//姓名

int num;//学号

char sex;//性别

int age;//年龄

float score;//成绩

char addr[ADDR_SIZE];//地址

}std1;//声明的同时定义变量


int main(int argc, const char *argv[])

{

struct student std2;//先声明后定义

return 0;


注意:

结构体类型的声明只是声明了一个数据类型,不开辟存储空间,如果定义出该类型下的变量,就需要开辟存储空间。

声明一个结构体类型——>int a;中int

定义一个结构体类型变量——>int a中的a


扩充:

相同类型下的结构体变量之间可以直接赋值

struct student stu1={chen chao ….};

struct student stu2=stu1;


4、结构体类型变量的初始化

#include <stdio.h>


#define NAME_SIZE 20

#define ADDR_SIZE 50


struct student

{

char name[NAME_SIZE];//姓名

int num;//学号

char sex;//性别

int age;//年龄

float score;//成绩

char addr[ADDR_SIZE];//地址

}std1 = {"songhuiqiao", 2, 'W', 35, 99, "hui long guan"  };//声明的同时定义变量


int main(int argc, const char *argv[])

{

struct student std2 = {"chenchao", 1, 'M', 25, 100, "hui long guan"};//先声明后定义

return 0;


5、指向结构体变量的指针

1:定义

格式:struct 结构体名  *变量;

2:赋值

#include <stdio.h>


#define NAME_SIZE 20

#define ADDR_SIZE 50


struct student

{

char name[NAME_SIZE];//姓名

int num;//学号

char sex;//性别

int age;//年龄

float score;//成绩

char addr[ADDR_SIZE];//地址

};//声明的同时定义变量


int main(int argc, const char *argv[])

{

struct student std1 = { "chenchao", 1, 'M', 25, 100, "hui long guan"};//先声明后定义

struct student *p1 = &std1;//初始化

struct student *p2 = NULL;

p2 = &std1;

return 0;


3:大小 8个字节


6、结构体变量成员的应用

1:通过结构体变量引用结构体变量的成员

格式:结构体变量名 . 成员名

2:通过指针来引用结构体成员

格式:指针变量->成员名

#include <stdio.h>


#define NAME_SIZE 20

#define ADDR_SIZE 50


struct student

{

char name[NAME_SIZE];//姓名

int num;//学号

char sex;//性别

int age;//年龄

float score;//成绩

char addr[ADDR_SIZE];//地址

};//声明的同时定义变量



int main(int argc, const char *argv[])

{

struct student std1 = { "chenchao", 1, 'M', 25, 100, "hui long guan"};//先声明后定义

struct student *p = &std1;//初始化

printf("std1.name = %s\nstd1.num = %d\nstd1.sex = %c\nstd1.age = %d\nstd1.score = %f\nstd1.addr = %s\n", std1.name, std1.num, std1.sex, std1.age, std1.score, std1.addr);//结构体变量名

printf("(*p).name = %s\n(*p).num = %d\n(*p).sex = %c\n(*p).age = %d\n(*p).score = %f\n(*p).addr = %s\n", (*p).name, (*p).num, (*p).sex, (*p).age, (*p).score, (*p).addr);//指向结构体变量的指针

printf("p->name = %s\np->num = %d\np->sex = %c\np->age = %d\np->score = %f\np->addr = %s\n", p->name, p->num, p->sex, p->age, p->score, p->addr);//指向结构体变量的指针

printf("(&std1)->name = %s\n(&std1)->num = %d\n(&std1)->sex = %c\n(&std1)->age = %d\n(&std1)->score = %f\n(&std1)->addr = %s\n", (&std1)->name, (&std1)->num, (&std1)->sex, (&std1)->age, (&std1)->score, (&std1)->addr);//结构体变量名

return 0;

课堂练习:

1:输入两个学生的学号、姓名、和成绩,输出成绩较高的学生的学号、姓名和成绩。

#include <stdio.h>


#define NAME_SIZE 20

struct student//结构体类型的声明

{

int num;

char name[NAME_SIZE];

int score;

};


int main(int argc, const char *argv[])

{

struct student std1 = {};

struct student std2 = {};


scanf("%d", &(std1.num));//输入学生信息

getchar();

gets(std1.name);

scanf("%d", &(std1.score));


scanf("%d", &(std2.num));

getchar();

gets(std2.name);

scanf("%d", &(std2.score));


if (std1.score > std2.score){//比较两个学生的成绩

printf("std1.num = %d\nstd1.name = %s\nstd1.score = %d\n", std1.num, std1.name, std1.score);

} else {

printf("std2.num = %d\nstd2.name = %s\nstd2.score = %d\n", std2.num, std2.name, std2.score);

}

return 0;

2:输入三个学生的学号、姓名和成绩,按成绩高低排序,并输出排序后结果

#include <stdio.h>


#define NAME_SIZE 20

struct student//结构体类型的声明

{

int num;

char name[NAME_SIZE];

int score;

};


int main(int argc, const char *argv[])

{

    int i,j;

struct student std[3] = {};

    struct student st = {};

    for (i=0; i<3; i++) {

        scanf("%d %s %d",&std[i].num,std[i].name,&std[i].score);

    }

    for (i=0; i<3; i++) {

        for (j=0; j<3-i; j++) {

            if (std[j].score>std[j+1].score) {

                st=std[j];

                std[j]=std[j+1];

                std[j+1]=st;

            }

        }

    }

for (i=0; i<3; i++) {

        printf(" %d  %s  %d\n", std[i].num, std[i].name, std[i].score);

    }

    return 0;


7、结构体数组和指向结构体数组首元素的指针及函数

思考:

大量整型变量——>整型数组

大量字符变脸——>字符数组

大量指针变量——>指针数组

大量结构体变量——>结构体数组

格式:

struct  结构体名  数组名[常量];

数组名:数组首元素的地址,地址常量

struct 结构体名:数组元素的类型

常量:数组成员的个数


赋值:

初始化

赋值语句

#include <stdio.h>


#define NAME_SIZE 20

#define ADDR_SIZE 50

#define NUM 10


struct student

{

char name[NAME_SIZE];//姓名

int num;//学号

char sex;//性别

int age;//年龄

float score;//成绩

char addr[ADDR_SIZE];//地址

};//结构体类型的声明


int main(int argc, const char *argv[])

{

struct student arr[NUM] = {};//结构体数组,数组成员10

struct student (*pArr1) = arr;//初始化

struct student (*pArr2) = NULL;

pArr2 = arr;//赋值语句

return 0;


练习:

输入输出5个学生的信息

#include <stdio.h>


#define NUM 5

#define NAME_SIZE 20

struct student//声明结构体类型

{

int num;

char name[NAME_SIZE];

int age;

};


int main(int argc, const char *argv[])

{

struct student arr[NUM] = {};//结构体数组

int i = 0;


//输入

for (i=0; i<NUM; i++){//arr[i]结构体变量

scanf("%d", &(arr[i].num));

getchar();

gets(arr[i].name);

scanf("%d", &(arr[i].age));

}

//输出

for (i=0; i<NUM; i++){

printf("arr[%d].num = %d\narr[%d].name = %s\narr[%d].age = %d\n", i, arr[i].num,  i, arr[i].name, i, arr[i].age);

}

return 0;


#include <stdio.h>


#define NUM 5

#define NAME_SIZE 20

struct student//声明结构体类型

{

int num;

char name[NAME_SIZE];

int age;

};


int main(int argc, const char *argv[])

{

struct student arr[NUM] = {};//结构体数组

struct student *pArr = arr;//指向结构体数组首元素的指针

int i = 0;


//输入

for (i=0; i<NUM; i++){//arr[i]结构体变量

scanf("%d", &((pArr+i)->num));

getchar();

gets((pArr+i)->name);

scanf("%d", &((pArr+i)->age));

}

//输出

for (i=0; i<NUM; i++){

printf("(pArr+%d)->num = %d\n(pArr+%d)->name = %s\n(pArr+%d)->age = %d\n", i, (pArr+i)->num,  i, (pArr+i)->name, i, (pArr+i)->age);

}

return 0;


#include <stdio.h>


#define NUM 5

#define NAME_SIZE 20

struct student//声明结构体类型

{

int num;

char name[NAME_SIZE];

int age;

};


void input(struct student arr[], int n);//声明

void output(struct student arr[], int n);//声明

int main(int argc, const char *argv[])

{

struct student arr[NUM] = {};//结构体数组


input(arr, NUM);//调用

output(arr, NUM);

return 0;

void input(struct student arr[], int n)//定义

{

int i = 0;

//输入

for (i=0; i<n; i++){//arr[i]结构体变量

scanf("%d", &(arr[i].num));

getchar();

gets(arr[i].name);

scanf("%d", &(arr[i].age));

}

}


void output(struct student arr[], int n)

{

int i = 0;

//输出

for (i=0; i<n; i++){

printf("arr[%d].num = %d\narr[%d].name = %s\narr[%d].age = %d\n", i, arr[i].num,  i, arr[i].name, i, arr[i].age);

}

}


#include <stdio.h>


#define NUM 5

#define NAME_SIZE 20

struct student//声明结构体类型

{

int num;

char name[NAME_SIZE];

int age;

};

void input(struct student *pArr, int n);//声明

void output(struct student *pArr, int n);


int main(int argc, const char *argv[])

{

struct student arr[NUM] = {};//结构体数组

struct student *pArr = arr;//指向结构体数组首元素的指针


input(arr, NUM);

output(arr, NUM);

return 0;

void input(struct student *pArr, int n)//定义

{

int i = 0;

//输入

for (i=0; i<n; i++){//arr[i]结构体变量

scanf("%d", &((pArr+i)->num));

getchar();

gets((pArr+i)->name);

scanf("%d", &((pArr+i)->age));

}

}

void output(struct student *pArr, int n)

{

int i = 0;

//输出

for (i=0; i<n; i++){

printf("(pArr+%d)->num = %d\n(pArr+%d)->name = %s\n(pArr+%d)->age = %d\n", i, (pArr+i)->num,  i, (pArr+i)->name, i, (pArr+i)->age);

}

}


练习:

num

name

score

1:输入5个学生的全部信息,输出成绩最高的学生的信息

2:输入5个学生的全部信息,按成绩(姓名)高低进行排序,输出排序后学生的信息



#include <stdio.h>

#include <string.h>

#define SIZE 100

#define NUM 5

struct student{

    int num;

    char name[SIZE];

    int score;

};

void input(struct student stu[],int n);

void output(struct student stu[],int n);

void paixu(struct student stu[],int n);

void xmpaixu(struct student stu[],int n);

int main(int argc, const char *argv[])

{

    struct student stu[NUM]={};

    input(stu,NUM);

    paixu(stu,NUM);

    output(stu, NUM);

    printf("\n");

    xmpaixu(stu,NUM);

    output(stu, NUM);

    printf("\n");

    return 0;

}

void input(struct student stu[],int n){

    int i;

    for (i=0; i<n; i++) {

        scanf("%d %s %d",&stu[i].num,stu[i].name,&stu[i].score);

    }

}

void output(struct student stu[],int n){

    int i;

    for (i=0; i<n; i++) {

        printf("%d  %s  %d\n",stu[i].num,stu[i].name,stu[i].score);

    }

}

void paixu(struct student stu[],int n){

    int i,j;

    struct student s;

    for (i=0; i<n; i++) {

        for (j=0; j<n-1; j++) {

            if (stu[j].score<stu[j+1].score) {

                s=stu[j];

                stu[j]=stu[j+1];

                stu[j+1]=s;

            }

        }

    }

}

void xmpaixu(struct student stu[],int n){

    int i,j;

    struct student s;

    for (i=0; i<n; i++) {

        for (j=0; j<n-1; j++) {

            if (strcmp(stu[j].name, stu[j+1].name)>0) {

                s=stu[j];

                stu[j]=stu[j+1];

                stu[j+1]=s;

            }

        }

    }

}


补充:

1、预处理

1:什么是预处理

预处理发生在编译程序的第一个阶段,将预处理命令装换成纯粹的c语句

2:常见预处理的种类和特点

种类:

1、宏定义

2、文件包含

3、条件编译

特点:

1、#开头

2、独占一行

3、末尾没有分号

3:宏定义

1、不带参数的宏定义

格式:#define 宏名 字符串

作用:将程序中出现宏名的地方都用字符串进行简单的替换

作用范围:定义开始,文件末尾结束

定义的位置:程序的任何位置

例子:

#define NUM   10

#define SIZE 100

例子:求圆的面积

#define PI 3.14

#define R 3

printf(“%f”, R*PI);


2、带参数的宏定义

格式:#define  宏名(参数列表)  字符串

作用:不仅要对字符串进行替换,还要对参数进行替换

例子:

#define S(a, b)   a+b

int area = S(3, 5);——>3+5

方法:实参替换行参,其他字符串原样保留

#define PI 3

#define S(r) ((r)*(r)*(PI))

printf(“%f”, S(3));——>3*3*3.14

思考:

s(3+2);——> ((3+2) *(3+2)* (3))

a*=b;

3 *= 2+3;——>a = 3*(2+3);


4:文件包含

文件包含:就是把头文件内容加载到当前程序中

1、#include <head.h>:到存放系统标准库函数头文件的路径去查找head.h

2、#include“head.h”:首先在当前路径下查找head.h文件,如果找不到,按照标准方式查找

5:条件编译

条件编译:正常情况下程序中的每一行代码都要参与编译,如果想让程序中的某些代码在满足一定条件下才参与编译,这就是条件编译

条件编译的几种形式:

1:

#ifdef 标识符

程序段1;

#else //可有可无

程序段2;

#endif

执行过程:如果标识符已经被#define过了则编译程序段1,否 则编译程序段2

2:

#ifndef 标识符

程序段1;

#else //可有可无

程序段2;

#endif

执行过程:如果标识符已经被#define过了则编译程序段2,否 则编译程序段1


工程常用条件编译:

1:#if 0 #endif之间的代码就不参与编译

#if 0

#endif

2:防止头文件重复包含

.h文件开始处加上:

#ifndef   _HEAD_H

#define _HEAD_H


#endif


2、枚举

1:枚举的作用

思考:如何描述一个季节

季节:春、夏、秋、冬

枚举:当一个变量的值,只有几种可能的时候,这时候可以通过枚举元素去一一列举变量的值

例子:

1:季节

2:星期

3:月份


2:枚举类型的声明

格式:enum  枚举名  {枚举元素列表};

enum:声明枚举类型的关键字,不能省略

enum  枚举名:枚举类型

例子:

enum season{spring,summer,autumn,winter};

enum week{……};

enum month{…………};


3:枚举变量的定义

1、声明的同时定义枚举变量

2、先声明枚举类型,再定义枚举变量

#include <stdio.h>


enum Season{spring, summer, autumn, winter}season1;//声明枚举类型的同时定义变量


int main(int argc, const char *argv[])

{

enum Season season2;//先声明枚举类型,在定义枚举变量

return 0;


4:枚举变量的赋值

#include <stdio.h>


enum Season{spring, summer, autumn, winter}season1;//声明枚举类型的同时定义变量


int main(int argc, const char *argv[])

{

enum Season season2;//先声明枚举类型,在定义枚举变量

return 0;

chenchaos-MacBook-Pro:day10 mac$ vim 1.c

chenchaos-MacBook-Pro:day10 mac$ cat 1.c

#include <stdio.h>


enum Season{spring, summer, autumn, winter};//枚举类型的声明


int main(int argc, const char *argv[])

{

enum Season season1 = spring;//先声明枚举类型,在定义枚举变量

enum Season season2;//先声明枚举类型,在定义枚举变量

season2 = winter;


return 0;


5:关于枚举的几点说明

1、编译器是把枚举元素的值当作常量来处理的,程序运行过程中不能够修改枚举元素的值

2、枚举元素中,每个元素的值对应一个整数值,枚举元素值的大小是由枚举元素在枚举元素列表中的位置决定的

spring(0)summer(1),autumn(2),winter(3)

枚举元素可以在声明的同时进行初始化

#include <stdio.h>


enum Season{spring, summer=5, autumn, winter};//枚举类型的声明


int main(int argc, const char *argv[])

{

enum Season season = spring;//先声明枚举类型,在定义枚举变量

printf("season = %d\n", season);


return 0;


3、枚举元素之间,可以进行关系运算

#include <stdio.h>


enum Season{spring, summer, autumn, winter};//枚举类型的声明


int main(int argc, const char *argv[])

{

enum Season season;//先声明枚举类型,在定义枚举变量

for (season=spring; season<=winter; season++){

printf("season = %d\n", season);

}


return 0;


3typedef

1:typedef的作用

  typedef可以对系统中已经存在的数据类型起一个别名,typedef并没有创新的数据类型,只是在原有类型的基础上起了一个新的名字

2:typedef给类型起别名的步骤

  1、定义出原有类型下的变量

  2、将变量名改成新的类型名

  3、在最开始处加上typedef

  4、用新类型名定义出变量


3:typedef和其他数据类型

  1: typedef和基本数据类型

例子:

int 

typedef int Interger;

Interger a;//等价于int a;//Interger是数据类型,等价于int

2: typedef和数组

例子:

int [10];

typedef int Arr10[10]; Arr10 arr;//等价于int arr[10];//Arr10是数据类型,等价于int [10]


3: typedef和指针

1: typedef和一级指针

例子:typedef int *Pointer;

Pointer p;//等价于 int *p//Pointer是数据类型,等价于int *


2:typedef和二级指针

例子:typedef int **PPointer;

PPointer pp;//等价于 int **pp//PPointer是数据类型,等价于int **


3:typedef和函数指针

例子:

int add(int a, int b);

typedef int (*Pfun)(int a, int b);

Pfun p = add;//等价于int (*p)(int a, int b)//Pfun是数据类型,int (*)(int a, int b)


4: typedef和结构体

1: typedef和结构体变量

2: typedef和指向结构体变量的指针


typedef struct student//结构体名可以省略 

{

int num;

char name[20];

}Student, *Pstudent;

Student std;//等价于struct student std;//Student是数据类型,struct student

Pstudent p;//等价于struct student *p;//Pstudent数据类型,struct student *


5: typedef和枚举

例子:

typedef enum Season{spring, summer, autumn, winter} EnumSeason;

EnumSeason season;//等价于enum Season season//EnumSeason是数据类型,enum Season

#include <stdio.h>


int add(int a, int b)

{

return a+b;

}


typedef int interger;//基本数据类型

typedef int Arr10[10];//数组

typedef int *Pointer;//一级指针

typedef int **PPointer;//二级指针

typedef int (*Pfun)(int a, int b);//函数指针


typedef struct student

{

int num;

char name[20];

}Studnet, *Pstudent;//结构体


typedef enum Season {spring, summer, autumn, winter}EnumSeason;//枚举


int main(int argc, const char *argv[])

{

interger a;//整型变量

Arr10 arr;//数组,数组成员10

Pointer p;//一级指针

PPointer pp;//二级指针

Pfun pfun = add;//函数指针

Studnet std;//结构体变量

Pstudent pstd;//结构体指针

EnumSeason season;//枚举变量

return 0;









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值