结构体集合 再不会的话,我就请你吃大餐了 (自我惩罚)
一步到位了,最近加班有点严重。下面看看准备写一下链表。
/****
可能会用的结构体,请深入理解
****/
//先描绘一个框架
struct 结构体类型名 结构体变量名 //这是标准
struct Info
{
unsigned long identifier;//学号,用无符号长整数表示
char name[20];//名字,用字符数组表示
unsigned int year;//入学年份,用无符号整数表示
unsigned int years;//学制,用无符号整数表示
}
int main(void)
{
/**
*在main函数中声明结构体变量
*结构体变量名叫info
*struct关键字不能丢
*/
struct Info info; // struct Info info = {};
...
}
//也可以在声明的时候就把变量名定义下来(此时这个变量是全局变量):
struct Info
{
unsigned long identifier;//学号,用无符号长整数表示
char name[20];//名字,用字符数组表示
unsigned int year;//入学年份,用无符号整数表示
unsigned int years;//学制,用无符号整数表示
} info;
/**
*此时直接定义了变量
*该变量是全局变量
*变量名叫info
*/
int main(void)
{
...//这里即可直接使用
}
//访问结构体成员
int main(void)
{
struct Info info;
.......
.......
printf("学号:%d\n姓名:%s\n入学年份:%d\n学制:%d\n毕业时间:%d\n", \
info.identifier, info.name, info.year, info.years, info.year + info.years);
return 0;
}
//初始化结构体
struct Info info = {
20191101,
"Harris",
2019,
4
};
/****或者这样****/
struct Info info = {
.name = "Harris",
.year = 2019
}; //对于没有被初始化的成员,则「数值型」成员初始化为0,「字符型」成员初始化为‘\0’。
//结构体嵌套
struct Date
{
unsigned int year;
unsigned int month;
unsigned int day;
};
struct Info
{
unsigned long identifier;//学号,用无符号长整数表示
char name[20];//名字,用字符数组表示
struct Date date;/*---入学日期,用结构体Date表示---*/
unsigned int years;//学制,用无符号整数表示
};
int main(void)
{
...
/**
访问变量,就必须用点号一层层往下访问。比如要访问day这个成员,
那就只能info.date.day而不能直接info.date或者info,day。
**/
}
//结构体数组
struct 结构体类型
{
成员;
} 数组名[长度];
/****或者这样****/
struct 结构体类型
{
成员;
};
struct 结构体类型 数组名[长度];
//结构体指针
把结构体看作一个类型,那么也就必然有对应的指针变量
struct Info* pinfo;
和数组的区别,数组名实际上就是指向这个数组第一个元素的地址,所以可以将数组名直接赋值给指针。而结构体的变量名并不是指向该结构体的地址,
所以要使用取地址运算符&才能获取地址:
pinfo = &info;
//访问指针结构体的两种方式
1.(*结构体指针).成员名 //点号运算符比指针的取值运算符优先级更高,因此需要加一个小括号来确定优先级
2.结构体指针->成员名
int main(void)
{
struct Info *p;
p = &info;
.....
printf("入学时间:%d/%d/%d\n", (*p).date.year, (*p).date.month, (*p).date.day); //1
printf("入学时间:%d/%d/%d\n", p -> date.year, p -> date.month, p -> date.day); //2
return 0;
}
//传递结构体变量 或者这样说 结构体做为参数 用来传递
struct Date
{
unsigned int year;
unsigned int month;
unsigned int day;
};
struct Info
{
unsigned long identifier;
char name[20];
struct Date date;
unsigned int years;
};
struct Info getInput(struct Info info);
void printInfo(struct Info info);
struct Info getInput(struct Info info)
{
scanf("%d", &info.identifier);
scanf("%s", info.name);
...
scanf("%d", &info.date.day);
scanf("%d", &info.years);
return info; //返回一个结构体
}
void printInfo(struct Info info)
{
printf("学号:%d\n姓名:%s\n入学时间:%d/%d/%d\n学制:%d\n毕业时间:%d\n", \
info.identifier, info.name, info.date.year, info.date.month, info.date.day, \
info.years, info.date.year + info.years);
}
int main(void)
{
struct Info i = {};
i = getInput(i);
printInfo(i);
return 0;
}
/****或者这样******/
struct result{
int myadd;
int mydiff;
};
struct param{
int first;
int second;
};
struct result arc(struct param qiang){
struct result temp;
temp.myadd = qiang.first+qiang.second;
temp.mydiff = qiang.first-qiang.second;
return temp;
}
int main(){
struct result chu;
struct param jia;
jia.first = 500;
jia.second = 400;
chu = arc(jia); //传递结构体名称
printf("%d and %d \r\n",chu.myadd,chu.mydiff);
return 0;
}
/********函数返回结构体**/
struct result{
int myadd;
int mydiff;
};
struct result arc(int a,int b){
struct result temp;
temp.myadd = a+b;
temp.mydiff = a-b;
return temp;
}
int main(){
struct result start;
start = arc(300,200);
printf("%d and %d \r\n",start.myadd,start.mydiff);
return 0;
}
//结构体指针作为参数传递
传递指向结构体变量的指针
/**
主要是考虑到如果结构体的内存占用太大,那么整个程序的内存开销就会爆炸,选择没有那么讲究,但是依旧要珍惜有限的资源。
**/
struct result{
int myadd;
int mydiff;
};
struct result arc(struct result *temp){
temp->myadd = 100+300;
temp->mydiff = 500-200;
return *temp;
}
int main(){
struct result start;
struct result stop;
start = arc(&stop);
printf("%d and %d \r\n",start.myadd,start.mydiff);
return 0;
}
/****或者这样******/
struct student
{
int num;
char name[20];
//char *name; //若定义为指针则应与下面 stu.name = "jacob"; 配对使用,交叉使用则会报错
//当定义为char name[20]时,这是一个存在于栈的具体空间,而"jacob"则是一个字符串常量,存在于内存的data空间。
float score[3];
};
void print(struct student *); //声明一个结构体指针 这种表示也很狂野
int main()
{
struct student stu;
stu.num=18;
strcpy(stu.name,"jacob"); //用函数strcpy,"jacob"复制进数组name内。
//stu.name = "jacob";
stu.score[0]=91;
stu.score[1]=95;
stu.score[2]=99;
print(&stu); // 结构体变量stu作为函数实参。
}
void print(struct student *p) //定义一个结构体指针变量p,接收的是结构体变量stu的地址即p指向结构体stu首地址
{
printf("num :%d\n",p->num); //此时引用结构体各成员需要用此格式 指针变量->结构体成员变量名。
printf("name :%s\n",p->name);
printf("score_1 :%f\n",p->score[0]);
printf("score_2 :%f\n",p->score[1]);
printf("score_3 :%f\n",p->score[2]);
}
//动态申请结构体
结构体也可以在堆里面动态申请
int main(void)
{
struct Info *i1;
struct Info *i2;
i1 = (struct Info *)malloc(sizeof(struct Info));
i2 = (struct Info *)malloc(sizeof(struct Info));
if (i1 == NULL || i2 == NULL)
{
printf("内存分配失败!\n");
exit(1);
}
printf("请录入第一个同学的信息...\n");
getInput(i1);
putchar('\n');
printf("请录入第二个学生的信息...\n");
getInput(i2);
printf("\n录入完毕,现在开始打印...\n\n");
printf("打印第一个学生的信息...\n");
printInfo(i1);
putchar('\n');
printf("打印第二个学生的信息...\n");
printInfo(i2);
free(i1); //哪里申请哪里释放
free(i2);
return 0;
}
实战,建立一个图书馆数据库
/**
建立的数组可以是指向结构体指针的数组
**/
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
struct Date
{
int year;
int month;
int day;
};
struct Book
{
char title[128];
char author[48];
float price;
struct Date date;
char publisher[48];
};
void getInput(struct Book* book);//录入数据
void printBook(struct Book* book);//打印数据
void initLibrary(struct Book* lib[]);//初始化结构体
void printLibrary(struct Book* lib[]);//打印单本书数据
void releaseLibrary(struct Book* lib[]);//释放内存
void getInput(struct Book* book)
{
printf("请输入书名:");
scanf("%s", book->title);
printf("请输入作者:");
scanf("%s", book->author);
printf("请输入售价:");
scanf("%f", &book->price);
printf("请输入出版日期:");
scanf("%d-%d-%d", &book->date.year, &book->date.month, &book->date.day);
printf("请输入出版社:");
scanf("%s", book->publisher);
}
void printBook(struct Book* book)
{
printf("书名:%s\n", book->title);
printf("作者:%s\n", book->author);
printf("售价:%.2f\n", book->price);
printf("出版日期:%d-%d-%d\n", book->date.year, book->date.month, book->date.day);
printf("出版社:%s\n", book->publisher);
}
void initLibrary(struct Book* lib[])
{
for (int i = 0; i < MAX_SIZE; i++)
{
lib[i] = NULL;
}
}
void printLibrary(struct Book* lib[])
{
for (int i = 0; i < MAX_SIZE; i++)
{
if (lib[i] != NULL)
{
printBook(lib[i]);
putchar('\n');
}
}
}
void releaseLibrary(struct Book* lib[])
{
for (int i = 0; i < MAX_SIZE; i++)
{
if (lib[i] != NULL)
{
free(lib[i]);
}
}
}
int main(void)
{
struct Book* lib[MAX_SIZE];
struct Book* p = NULL;
int ch, index = 0;
initLibrary(lib);
while (1)
{
printf("请问是否要录入图书信息(Y/N):");
do
{
ch = getchar();
} while (ch != 'Y' && ch != 'N');
if (ch == 'Y')
{
if (index < MAX_SIZE)
{
p = (struct Book*)malloc(sizeof(struct Book));
getInput(p);
lib[index] = p;
index++;
putchar('\n');
}
else
{
printf("数据库已满!\n");
break;
}
}
else
{
break;
}
}
printf("\n数据录入完毕,开始打印验证...\n\n");
printLibrary(lib);
releaseLibrary(lib);
return 0;
}
//运行结果;
请问是否要录入图书信息(Y/N):Y
请输入书名:人类简史
请输入作者:尤瓦尔·赫拉利
请输入售价:32.25
请输入出版日期:2016-3-4
请输入出版社:中信出版集团
请问是否要录入图书信息(Y/N):N
数据录入完毕,开始打印验证...
书名:人类简史
作者:尤瓦尔·赫拉利
售价:32.25
出版日期:2016-3-4
出版社:中信出版集团