// 本节有两部分,第一部分为结构体的定义、初始化、结构体数组。第二部分为结构体对齐,在考研初试中选择题出现较多。(☆☆☆☆)
1、结构体的定义、初始化、结构体数组。
Q1:首先知道,为什么要学结构体?
之前学过的构造数据类型有,数组,但是数组只能放相同的数据类型,例如int类型数组只能放int类型的数据,而很多时候需要将不同类型的数据组合成一个整体,以方便引用。例如:一个学生的信息有,学号,姓名,性别,年龄,地址等等属性,如果针对学生的各个属性都分别单独定义一个变量,那么在有多个学生时,变量就难以分清,因此,C语言提供了结构体来管理不同类型的数据组合。
struct student//结构体名
{//成员列表
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}; //注:定义结构体一定要加分号。
一般将结构体定义在main函数外。
【例 1.1】结构体的 scanf 读取和输出。
注:结构体输出时必须单独去访问内部每个成员
#include <stdio.h>
struct student//结构体名
{//成员列表
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
int main() {
struct student yhw={201245,"hh",'M',21,98.0,"nuc"};//变量和结构体类型名字不能相同
printf("%d,%s,%c,%d,%f,%s",yhw.num,yhw.name,yhw.sex,yhw.age,yhw.score,yhw.addr);
scanf("%d%s %c%d%f%s",&yhw.num,&yhw.name,&yhw.sex,&yhw.age,&yhw.score,&yhw.addr);//混合读取时,%d,%s,%f,都可以挨着,因为它们会忽略空格,%c和别的读取之间需要间隔,因为%c不能忽略空格。
printf("%d,%s,%c,%d,%f,%s",yhw.num,yhw.name,yhw.sex,yhw.age,yhw.score,yhw.addr);
return 0;
}
运行结果如图:
【例 1.2】结构体数组的 scanf 读取和输出。
#include <stdio.h>
struct student//结构体名
{//成员列表
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
int main() {
struct student y[3];
int i;
for(i=0;i<3;i++){
scanf("%d %s %c %d %f %s",&y[i].num,&y[i].name,&y[i].sex,&y[i].age,&y[i].score,&y[i].addr);
}
for(i=0;i<3;i++){
printf("%d,%s,%c,%d,%f,%s\n",y[i].num,y[i].name,y[i].sex,y[i].age,y[i].score,y[i].addr);
}
return 0;
}
运行结果如图:
2、结构体对齐
3、结构体指针与typedef
3.1 结构体指针
结构体指针就是该变量所占据的内存段的起始地址。可以设置一个指针变量,用它指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来 指向结构体数组中的元素,从而能够通过结构体指针快速访问结构体内的每个成员。
例一:结构体指针的使用
#include <stdio.h>
struct student{
int num;
char name[20];
char sex;
};
//结构体指针的练习
int main() {
struct student s={1001,"yhw",'M'};
struct student sarr[3]={1001,"yhw1",'M',1005,"yhw2",'M',1007,"yhw3",'F'};
struct student *p; //定义了一个结构体指针变量
p = &s;
printf("%d,%s,%c\n",s.num,s.name,s.sex);
p = sarr;//数组名里面所存的是数组起始地址,因此p = sarr 和 p = &sarr[0] 等价。
printf("%d,%s,%c\n",(*p).num,(*p).name,(*p).sex);
p++;
printf("%d,%s,%c\n",(*p).num,(*p).name,(*p).sex);//方式1通过结构体指针访问成员
printf("%d,%s,%c\n",p->num,p->name,p->sex);//方式2通过结构体指针访问成员
return 0;
}
3.2 typedef的使用
#include <stdio.h>
//typedef的使用,typedef起别名
typedef struct student{
int num;
char name[20];
char sex;
}stu,*pstu;//stu 等价于struct student
//pstu 等价于struct student *
typedef int INGETER;
int main() {
stu s={1001,"yhw",'M'};
stu *p1 = &s;//定义了一个结构体指针变量
pstu p2 = &s;
INGETER num = 10 ;
printf("i=%d,p->num=%d\n",num,p1->num);
printf("i=%d,p->num=%d\n",num,p2->num);
return 0;
}
使用stu定义结构体变量和使用structstudent定义结构体变量是等价的;使用INTEGER 定义变量i和使用int定义变量i是等价的;pstu等价于structstudent*,所以p是结构体指针变量。
4、C++引用讲解
4.1 C++应用讲解
#include <stdio.h>
//C++的引用的讲解,在子函数中修改主函数普通变量的值。
void modify_num(int &b){//形参中写&这个符号,称之为引用而不是取地址。
b = b + 1;
}
int main() {
int a = 10;
modify_num(a);
printf("after modify_num = %d\n",a);
return 0;
}
在上述代码中,如果改为纯C,则代码如下:
#include <stdio.h>
void modify_num(int *b)
{
*b=*b+1;
}
int main() {
int a=10;
modify_num(&a);
printf("after modify_num a=%d\n",a);
return 0;
}
可以发现,在C++代码中当在子函数中要修改函数中变量的值,就用&,不需要修改,就不用,代码效率明显变高。
例4.1.2,在子函数中修改主函数的一级指针变量。
#include <iostream>
void modify_pointer(int* &p,int* &q)//引用必须和变量名紧邻。
{
p = q;
}
//子函数中修改主函数的一级指针变量
int main() {
int *p = NULL;
int i = 10;
int *q = &i;
modify_pointer(p,q);
printf("after modify_point = %d\n",*p);//操作系统中设置了,空地址不能访问。
return 0;//当代码执行完毕后,退出代码为 -1073741819,不为0,那么代表进程异常结束。
}
上述代码如果改为纯C,就需要用到二级指针:
#include <stdio.h>
void modify_pointer(int **p,int *q)//相对于 C++这里是 int **p;
{
*p=q;//这里的写法和例 1.2 中的是非常类似的
}
int main() {
int *p=NULL;
int i=10;
int *q=&i;
modify_pointer(&p,q);//相对于 C++这里是&p
printf("after modify_pointer *p=%d\n",*p);
return 0;
}
4.2 C++的布尔类型
#include <stdio.h>
//设置布尔值的好处是提升了代码的可阅读性
int main() {
bool a= true;
bool b= false;
printf("a=%d,b=%d\n", a,b);
return 0;
}
5.课后OJ作业
5.1 作业1代码
#include <stdio.h>
typedef struct student{
int num;
char name[20];
char sex;
}stu;
int main() {
stu s;
scanf("%d %s %c",&s.num,s.name,&s.sex);
printf("%d %s %c\n",s.num,s.name,s.sex);
return 0;
}
5.2 作业2代码
#include <stdio.h>
#include <stdlib.h>
void modify_pointer(char * &p)
{
p = (char*)malloc(100);
fgets(p,100,stdin);//stdin代表标准输入。
};
int main() {
char *p=NULL;
modify_pointer(p);
puts(p);
return 0;
}