一,学习内容简要
1.c语言进度:学习到结构体结束,初步了解结构体的定义,初始化和使用。了解了一些程序结构的基础知识
2.洛谷:完成题目 道
二,结构体类型
1.结构体类型定义
格式:
struct <结构标记>
{
成员1;
成员2;
...
成员n;
};
struct是结构体类型的关键字,和后面的类型标记符号一起组成结构体类型名。大括号里的成员表由若干个成员定义组成。成员定义的一般格式:
类型名 成员名;
例如:
struct date
{
int year;
int month;
int day;
};
struct student
{
char number[9];//有效长度为8的学号
char name[31];//有效长度为30的姓名
char sex;//性别
int age;//年龄
float score;//分数
char address[51];//有效长度为50的地址
char date birthday;//引用 struct date 结构体类型
}
注意
(1)大括号后面要有分号;
(2)定义结构体成员和定义变量格式虽然一样,但是不能给它赋初值;
(3)结构体成员可以是简单的变量(如:sex,age),数组(如:number,name,address),也可以是另一个结构体变量(如:birthday)。
2.结构体变量的定义
有三种格式:
(1)先定义结构体类型,再定义变量,类型和变量分开定义。格式如下:
结构体类型名 结构体变量名表;
例如:
struct student
{
...
};
struct student stu1,stu2;
(2)定义结构体类型的同时定义变量。格式如下:
struct <结构标记>
{
成员1;
成员2;
...
成员n;
}结构体变量名表;
例如:
struct student
{
...
}stu1,stu2;
(3)不定义类型名,直接定义结构体变量。格式如下:
struct
{
成员1;
成员2;
...
成员n;
}结构体变量名表l;
例如:
struct
{
...
}stu1,stu2;
此方法定义了两个结构体变量stu1和stu2。
上述三种方法都存在优点和缺点:
方法一最常用,适用于大量引用结构体的情况。
方法二是简略形式,适用于引用次数少的情况。
方法三的struct后面没有结构标记,因此只能使用一次,不能在其他地方进行引用。
//结构体变量在内存中所占字节数=所有成员的字节数之和
3.结构体变量的使用
(1)初始化
初始化的实质是对各个成员变量进行赋初值,一般格式如下:
结构体类型名 结构体变量={
初始值表};
例如:
main()
{
struct student stu1={
"04201206","jiahaochen","m",18,85,"chengchengxian",2002,10,22};
struct student stu2={
"04201210"};
...
}
初始值表由若干个用逗号分隔的初始值构成,初始值的顺序与类型应当和相应成员的顺序和类型一致。在初始化时允许部分初始化,未初始化的成员必须位于列表末尾。初始值的个数不能超成员数,若小于成员数,则剩余成员被初始为默认值。对整数于和浮点数默认值为0,对于字符和字符串,默认值为“\0”。只能在定义结构体变量时使用此初始化格式。
(2)引用
访问和给结构体成员赋值有多种方法,但成员本身并不是变量,必须和结构体变量相连接,以便使用它们的成员。c语言中,可以对结构体变量最低一级的成员进行引用。
引用结构体变量的一般格式如下:
结构体变量名.成员名
“.”是结构体成员运算符,是所有运算符中优先级最高的运算符,左结合。
例如给结构体变量stu1的各个成员赋值:
main()
{
struct student stu1;
strcpy(stu1.number,"04201206");
strcpy(stu1.name,"jiahaochen");
stu1.sex='m';
stu1,age=18;
stu1.score=85;
strcpy(stu1.address,"chengchengxian");
stu1.birthday.year=1001;
stu1,birthday.month=10;
stu1.birthday.day=22;
}//对于stu1.birthday成员,还需要通过"."对其对低级的各成员赋值
结构体成员扮演的角色和同类型的普通变量一样,因此结构体成员还可以进行该成员类型允许的各种运算操作。例如:
sum=stu1.score+stu2.score;//算术运算
if(stu.score>max_score)
{
max_score=stu.score;
}//比较运算
scanf("%s",&stu.name);//字符串输入
scanf("%d",&stu.birthday.year);//输入
printf("%d",stu.birthday.year);//输出
对于stu1.name输入时,如果考虑空格,则可以使用gets函数。例如:
gets(stu1.name);
不允许对结构体变量整体进行此类操作。例如:以下语句是错的
sum=stu1+stu2;
scanf("%s",&stu1);
(3)对结构体变量整体的引用
1)可作为函数的形参,实参或函数的返回值来进行函数的数据传递。
2)当两个结构体变量的类型相同时,可以互相整体赋值。例如,stu1和stu2的类型相同,可以互相赋值,即stu1=stu2;
3)C语言不允许对结构体变量进行任何逻辑操作,只能逐个比较成员。例如以下语句错误
stu1==stu2;
stu1!=stu2;
三,结构体数组
1.结构体数组的定义
(1)先定义结构体类型,后定义结构体数组,一般格式如下:
结构体类型定义;
结构体类型名 结构体数组名[数组长度];
结构体类型名必须是已经定义过的结构体类型,数组长度是结构体元素的个数,例如:
struct student
{
char num[9];
char name[21];
char sex;
int score [3];
};
struct student stu [3];
(2)在定义结构体类型的同时定义数组,格式如下:
sturct <结构标记>
{
成员1;
成员2;
...
成员n;
}结构体数组名[数组长度];
例如:
struct student
{
...
}stu[3];
(3)不定义类型名,直接定义结构体变量,格式如下:
struct
{
成员1;
成员2;
...
成员n;
}结构体数组名[数组长度];
例如:
struct
{
...
}stu[3];
2.结构体元素的使用
(1)结构体数组元素的初始化
结构体数组在定义的同时可以进行初始化。格式如下:
结构体类型名 结构体数组名[数组长度]={
初始值表};
例如
sturct student stu[2]={
{
"04201206","jiahaochen"},{
"04201210","han"}
};
(2)结构体数组元素的引用
结构体数组中的每个元素相当于一个结构体变量,可以进行结构体变量允许的各种操作。既要遵循数组元素的引用法则,还要遵循结构体变量的规定。如果要引用结构体数组整体元素,则要应用数组名加下标;如果要引用元素中的成员,还要在后面加上成员访问符“.”和成员名。
格式如下:
结构体数组名[下标]//引用数组某一元素
结构体数组名[下标].成员名//引用某一元素的某成员
例如:
strcpy(stu[0].num,"04201206");
stu[0].sex='m';
stu[0]score[0]=90;
说明:
1)可以将结构体(变量,数组元素或函数值)赋给同类型的结构体变量或数组元素。例如:数组stu的元素类型与变量t的类型为相同结构体类型时,要交换啷个数组元素,可以如下操作:
t=stu[i];
stu[i]=stu[j];
stu[j]=t;
2)与结构体变量相同,结构体数组元素不能整体进行输入或输出
四,结构体和函数
1.结构体作函数参数
结构体的值从 一个函数传递给另一个函数有以下三种方法:
(1)把结构体变量的每个成员作为函数调用的实参进行传递,然后像普通变量一样处理实参。但是结构体太大时效率太低
(2)结构体变量整体做函数的参数,在函数中对形参结构体变量成员的任何修改都不能反映到实参结构体变量中。此时需要函数将整个结构体变量值返回给调用函数。这样被调用的函数在定义时就必须以该结构体类型作为函数的返回类型。
(3)使用指针以参数形式来传递结构体变量。这种情况下结构体变量的地址传递给被调用函数。该函数可以间接访问该结构体变量的成员。(比方法2更有效)
2.返回值为结构体类型的函数
结构体数组名作为函数参数时,和普通数组名作为函数参数一样,传递的是数组的首地址值。该函数可以间接访问和修改该数组元素的成员。
注意
(1)被调用函数中用作实参的结构体变量和相应形参必须为相同的结构体类型。
(2)当被调用函数返回数据给调用函数时,才需要return 语句。其表达式可以是任意简单的变量,结构体变量或使用简单变量的表达式。
五,结构类型
1.枚举
enum 枚举类型名字 {
名字0,名字1,......名字n};
例如:
enum COLOR{
RED,YELLOW,GREEN};
大括号内的名字是常量字符,类型为int,值从0到n
声明枚举量时可以指定值
枚举只是int
2.结构
在某函数内部申明结构,则该结构只能在该函数中使用
3.结构运算
要访问整个结构,直接用结构变量的名字。
对于整个结构,可以做赋值,取地址,也可以传递给函数形参。
p1=(struct point){
5,10};//相当于p1.x=5,p1.y=10;
p1=p2;//相当于p1.x=p2.x,p1.y=p2.y;
4.结构指针
结构变量的名字不是结构变量的地址,必须用&运算符。
例如:
struct date *pDate=&today;
5.结构作为函数参数
示例:
int number of Days(struct date d)
整个结构可以作为参数的值传入函数,这时是在函数内新建一个结构变量,并复制调用结构的值
也可以返回一个结构,这与数组完全不同。
6.输入结构
在输入结构时不能直接用scanf输入一个结构
7.结构指针作为参数
用->表示指针所指的结构变量中的成员
8.结构中的结构
结构的嵌套
示例:
struct date and time
{
struct date sdate;
struct time stime;
}
9.自定义数据类型(typedef)
用来声明一个已有的数据类型的新名字
typedef int LENGTH;
使LENGTH成为int类型的别名
六,程序结构
1.全局变量
定义在函数外面,具有全局的生存期和作用域
与任何函数都无关,在任何函数中都可以使用
没有做初始化的全局变量会得到0值
指针会得到NULL值
只能用编译时刻已知的值来初始化全局变量
它们的初始化发生在main之前
2.静态本地变量
在本地变量定义时加上static修饰符,成为静态本地变量
函数离开时,静态本地变量会继续存在并保持其值
实质上静态本地变量是特殊的全局变量
位于相同的内存区域,具有全局变量的生存期,函数内的局部作用
static在这里意为局部作用域
返回本地变量的地址是危险的
返回全局变量或静态本地变量的地址是安全的
返回在函数内malloc的内存是安全的,但容易造成问题
最好的做法是返回传入的指针
不要使用全局变量在函数间传递参数和结果
尽量避免使用全局变量
使用全局变量和静态本地变量的函数是不安全的
3.编译预处理和宏
(1)#开头的是编译预处理指令,它们不是C语言的成分,但C语言离不开它们。
(2)#define用来定义一个宏。
(3)宏
如果宏的值中有其他宏的名字,也会被替换
如果一个宏的值超过一行,最后一行之前的行末要加上
宏的值后面出现的注释不会被当作宏的值的一部分
没有值的宏
#define_DEBUG
这类宏用于条件编译,后面有其他的编译预处理指令来检查这个宏是否已经被定义过
预定义的宏
LINE
FILE
DATE
TIME
STDC
emmmm目前就学到这了哈哈哈哈哈