当前位置:网站首页>C语言n番战--结构体(七)
C语言n番战--结构体(七)
2022-07-23 04:51:00 【阿杰在线送代码】
嵌入式之路,贵在日常点滴
---阿杰在线送代码
目录
一、什么是结构体
- 结构体和数组一样属于构造类型
- 数组是用于保存一组相同类型数据的, 而结构体是用于保存一组不同类型数据的
- 例如,在学生登记表中,姓名应为字符型;学号可为整型或字符型;年龄应为整型;性别应为字符型;成绩可为整型或实型。
- 显然这组数据不能用数组来存放, 为了解决这个问题,C语言中给出了另一种构造数据类型——“结构(structure)”或叫“结构体”。
二、定义结构体类型
在使用结构体之前必须先定义结构体类型, 因为C语言不知道你的结构体中需要存储哪些类型数据, 我们必须通过定义结构体类型来告诉C语言, 我们的结构体中需要存储哪些类型的数据
- 格式:
struct 结构体名{
类型名1 成员名1;
类型名2 成员名2;
……
类型名n 成员名n;
};- 示例:
struct Student {
char *name; // 姓名
int age; // 年龄
float height; // 身高
};
三、定义结构体变量
定义好结构体类型之后, 我们就可以利用我们定义的结构体类型来定义结构体变量
格式: struct 结构体名 结构体变量名;
- 先定义结构体类型,再定义变量
struct Student {
char *name;
int age;
};
struct Student stu;- 定义结构体类型的同时定义变量
struct Student {
char *name;
int age;
} stu;- 匿名结构体定义结构体变量
struct {
char *name;
int age;
} stu;第三种方法与第二种方法的区别在于,第三种方法中省去了结构体类型名称,而直接给出结构变量,这种结构体最大的问题是结构体类型不能复用
四、结构体成员的访问
一般对结构体变量的操作是以成员为单位进行的,引用的一般形式为:结构体变量名.成员名
struct Student {
char *name;
int age;
};
struct Student stu;
// 访问stu的age成员
stu.age = 27;
printf("age = %d", stu.age);五、结构体的三种定义赋值方法
#include <stdio.h>
#include <string.h>
struct student
{
int englishScore;
int mathScore;
int chineseScore;
char name[128];
};//此处分号易漏
int main()
{
//一、在结构体变量定义的时候就赋值,此时要全部赋值
struct student stu1={100,100,100,"张三"};
//二、先定义,后赋值,不需要全部赋值
struct student stu2;
stu2.englishScore = 90;
//stu2.name = "李四";
strcpy(stu2.name,"李四");
//三、常用的部分赋值方式,多见于内核源码对结构体的定义
struct student stu3={
.name = "周浩杰",
.englishScore = 90,
.mathScore = 80, //此处是逗号
};//分号易漏
printf("stu1的名字是:%s,分数:%d\n",stu1.name,stu1.englishScore);
printf("stu2的名字是:%s,分数:%d\n",stu2.name,stu2.englishScore);
printf("stu3的名字是:%s,分数:%d\n",stu3.name,stu3.englishScore);
return 0;
}运行结果:
stu1的名字是:张三,分数:100
stu2的名字是:李四,分数:90
stu3的名字是:周浩杰,分数:90为什么使用
strcpy?如果不在结构体变量初始化的时候就对具有数组类型的表达式赋值,则要使用strcpy,即不能直接赋值。
六、结构体类型作用域
- 结构类型定义
- 从定义的那一行开始, 直到遇到return或者大括号结束为止
- 结构类型定义在函数外部的作用域与全局变量的作用域是相同的
- 从定义的那一行开始,直到本文件结束为止
#include "stdio.h"
//定义一个全局结构体,作用域到文件末尾
struct Person{
int age;
char *name;
};
void test();
int main(int argc, const char * argv[])
{
//定义局部结构体名为Person,会屏蔽全局结构体
//局部结构体作用域,从定义开始到“}”块结束
struct Person{
int age;
};
// 使用局部结构体类型
struct Person pp;
pp.age = 50;
//pp.name = "zbz";
printf("局部结构体类型:%d\n",pp.age);
test();
return 0;
}
void test()
{
//使用全局的结构体定义结构体变量p
struct Person p = {10,"sb"};
printf("全局的结构体:%d,%s\n",p.age,p.name);
}例题:输入两个学生的名字,学号,成绩,输出成绩高的学生的信息
#include "stdio.h"
#include "string.h"
struct Student
{
int num;
char name[32];
char sex;
int age;
double score;
char addr[32];
};
int main()
{
struct Student stu1 = {1,"李四",'g',17,95.5,"汕头"};
struct Student stu2 = {2,"张三",'b',18,99.5,"东莞"};
struct Student max;
max = stu1;
if(stu1.score < stu2.score)
{
max = stu2;
}
printf("成绩比较好的是:\n");
printf("学号:%d,年龄:%d,分数:%lf,名字:%s,地址:%s\n",
max.num,max.age,max.score,max.name,max.addr);
//if(stu1.score < stu2.score)
//{
// printf("成绩比较好的是:\n");
// printf("学号:%d,年龄:%d,分数:%lf,名字:%s,地址:%s\n",
// stu2.num,stu2.age,stu2.score,stu2.name,stu2.addr);
//}
//else
//{
// printf("成绩比较好的是:\n");
// printf("学号:%d,年龄:%d,分数:%lf,名字:%s,地址:%s\n",
// stu1.num,stu1.age,stu1.score,stu1.name,stu1.addr);
//}
return 0;
}七、结构体数组
做个简单应用就好:输入4个学生的名字成绩,找出最高分。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student
{
char* name;
int score;
};
int main()
{
int i;
struct student stu[4] = {0};
for(i=0;i<4;i++)
{
printf("请输入第%d个学生的名字\n",i+1);
stu[i].name = (char* )malloc(sizeof(char)*16);
memset(stu[i].name,0,sizeof(char)*16);
scanf("%s",stu[i].name);
printf("请输入他的成绩\n");
scanf("%d",&stu[i].score);
}
struct student stuMax = stu[0];//就像正常的变量一样,可以相互赋值
for(i=1;i<3;i++)
{
if(stu[i].score > stuMax.score){
stuMax = stu[i];
}
}
printf("最高分是%s:%d\n",stuMax.name,stuMax.score);
return 0;
}请输入第1个学生的名字
张三
请输入他的成绩
56
请输入第2个学生的名字
李四
请输入他的成绩
85
请输入第3个学生的名字
王五
请输入他的成绩
95
请输入第4个学生的名字
李六
请输入他的成绩
64
最高分是王五:95
选票系统
#include "stdio.h"
#include "string.h"
struct XuanMin
{
char name[32];
int tickets;
};
int main()
{
struct XuanMin xm[3];
struct XuanMin max;
int feipiao = 0;
int i;
int len;
int j;
int mark = 0;
int total = 5;
char tempName[32];
//初始化选民信息
len = sizeof(xm)/sizeof(xm[0]);
for(i=0;i<len;i++)
{
xm[i].tickets = 0;
printf("请输入第%d个选民的名字:\n",i+1);
scanf("%s",xm[i].name);
}
//唱票环节
for(i=0;i<5;i++)
{
mark = 0;
printf("请输入你投给谁:\n");
memset(tempName,'\0',sizeof(tempName));//每次清空一下
scanf("%s",tempName);//输入选中的选民名字,像拆开一个选票,看到名字一样
for(j=0;j<len;j++)//拿到名字,对应候选人票数加1
{
if(strcmp(tempName,xm[j].name) == 0)
{
xm[j].tickets++;
mark = 1;
}
}
if(mark == 0)
{
printf("没有此候选人,放弃\n");
feipiao++;
}
}
//公布结果
for(i=0;i<len;i++)
{
printf("名字:%s,票数:%d\n",xm[i].name,xm[i].tickets);
}
max = xm[0];
for(i=1;i<len;i++)
{
if(max.tickets < xm[i].tickets)
{
max = xm[i];
}
}
printf("%s以%d票当选!!废票是%d\n",max.name,max.tickets,feipiao);
}请输入第1个选民的名字:
aa
请输入第2个选民的名字:
bb
请输入第3个选民的名字:
cc
请输入你投给谁:
aa
请输入你投给谁:
bb
请输入你投给谁:
dd
没有此候选人,放弃
请输入你投给谁:
cc
请输入你投给谁:
cc
名字:aa,票数:1
名字:bb,票数:1
名字:cc,票数:2
cc以2票当选!!废票是1
八、结构体指针
- 一个指针变量当用来指向一个结构体变量时,称之为结构体指针变量
- 格式: struct 结构名 *结构指针变量名
- 示例:
// 定义一个结构体类型
struct Student {
char *name;
int age;
};
// 定义一个结构体变量
struct Student stu = {“lnj", 18};
// 定义一个指向结构体的指针变量
struct Student *p;
// 指向结构体变量stu
p = &stu;
/*
这时候可以用3种方式访问结构体的成员
*/
// 方式1:结构体变量名.成员名
printf("name=%s, age = %d \n", stu.name, stu.age);
// 方式2:(*指针变量名).成员名
printf("name=%s, age = %d \n", (*p).name, (*p).age);
// 方式3:指针变量名->成员名
printf("name=%s, age = %d \n", p->name, p->age);
return 0;- 通过结构体指针访问结构体成员, 可以通过以下两种方式
- (*结构指针变量).成员名
- 结构指针变量->成员名(用熟)
(pstu)两侧的括号不可少,因为成员符“.”的优先级高于“*”。
如去掉括号写作pstu.num则等效于(pstu.num),这样,意义就完全不对了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct STU
{
int score;
char name[128];
};
int main()
{
struct STU stu1 = {
.score = 99,
.name = "陈立臣",
};
//malloc为结构体指针开辟一块空间
struct STU *pstu = (struct STU *)malloc(sizeof(struct STU));
//结构体指针的赋值1:直接赋值,在此之前要开辟空间
pstu->score = 100;
strcpy(pstu->name,"周浩杰");
printf("%s:%d\n",pstu->name,pstu->score);
free(pstu);//释放指针,重新指向一段地址
//结构体指针的赋值2:指向结构体变量的地址
pstu = &stu1;
printf("%s:%d\n",pstu->name,pstu->score);
//指针偏移
printf("%p\n",pstu);
printf("%p\n",++pstu);
return 0;
}结果:结构体偏移了4+128个字节
周浩杰:100 陈立臣:99 0x7e905170 0x7e9051f4
实际应用例子:
用一个结构体指针做一个最简单的学生成绩管理。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stud
{
char* name;
int score;
};
int main()
{
int num;
int i;
printf("需要录入几个学生的成绩?\n");
scanf("%d",&num);
//这里开辟了num个结构体所需要的空间,动态分配内存
struct stud *pstu = (struct stud *)malloc(sizeof(struct stud)*num);
for(i=0;i<num;i++)
{
pstu->name = (char* )malloc(sizeof(char)*16);
memset(pstu->name,0,sizeof(char)*16);
printf("请输入第%d个学生的名字\n",i+1);
scanf("%s",pstu->name);
printf("请输入第%d个学生的成绩\n",i+1);
scanf("%d",&pstu->score);
pstu++;
}
pstu -= num;
for(i=0;i<num;i++)
{
printf("%s:%d\n",pstu->name,pstu->score);
pstu++;
}
return 0;
} 结果:
美羊羊:45 废羊羊:100 喜羊羊:60 灰太狼:76
因为呢结构体比较重要,搞个稍微复杂一点的练练手。
主要运用结构体指针,输入学生的学号,语文数学英语成绩。
要求封装功能函数(初始化学生成绩,找到分数最高的学生,算出班级平均分)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
char* name;
int chinese;
int math;
int english;
int total;
}STU,*PSTU;
PSTU initStu(int num)
{
int i;
//要想返回结构体指针,就要先创建并开创空间。
PSTU p = (PSTU)malloc(sizeof(STU) * num);
for(i=0;i<num;i++){
printf("请输入第%d个学生的名字\n",i+1);
p->name = (char* )malloc(16);
//为字符指针开辟空间才能赋值,否则就等着段错误吧。
memset(p->name,0,16);
scanf("%s",p->name);
printf("请分别输入语文,数学,英语成绩,以逗号隔开,以回车结束\n");
scanf("%d,%d,%d",&p->chinese,&p->math,&p->english);
p++;
}
return p-num;
}
PSTU findMax(PSTU stuSum,int num)
{
int i;
PSTU max = stuSum;
PSTU p = stuSum;
for(i=0;i<num;i++){
if(p->total > max->total){
max = p;
}
p++;
}
return max;
}
void getTotalAndAve(PSTU stuSum,int num,int* ave)
{
int i;
int sum = 0;
PSTU p = stuSum;
for(i=0;i<num;i++){
p->total = p->chinese + p->math + p->english;
p++;
}
p -= num;
for(i=0;i<num;i++){
sum += p->total;
p++;
}
*ave = sum / num;
// free(p-num);
// p=NULL;
}
void print(PSTU stuSum,PSTU stuMax,int ave,int num)
{
int i;
PSTU p = stuSum;//这样不会导致stuSum指针偏移
for(i=0;i<num;i++)
{
printf("%s>>>>语文:%d,数学:%d,英语:%d\n\n",
p->name,p->chinese,p->math,p->english);
p++;
}
printf("总分最高分是%s:%d\n",stuMax->name,stuMax->total);
printf("班级平均分是:%d\n",ave);
// free(p-num);
// p = NULL;
}
int main()
{
int num;//学生人数
int ave;//班级均分
printf("需要录入几人的成绩?\n");
scanf("%d",&num);
PSTU stuSum = initStu(num);//初始化学生信息
getTotalAndAve(stuSum,num,&ave);//计算各个学生的总分以及班级均分
PSTU stuMax = findMax(stuSum,num);//找到总分最高的学生
print(stuSum,stuMax,ave,num);//打印学生信息,最高分的人,班级均分
return 0;
}选票系统
#include "stdio.h"
#include "string.h"
#include <stdlib.h>
struct XuanMin
{
char name[32];
int tickets;
};
struct XuanMin* initXm(struct XuanMin *p,int *pn)
{
int i;
if(p == NULL)
{
printf("请输入有几个人参选:\n");
scanf("%d",pn);
p = (struct XuanMin*)malloc(*pn * sizeof(struct XuanMin));
}
for(i=0;i<*pn;i++)
{
p->tickets = 0;
printf("请输入第%d个选民的名字:\n",i+1);
scanf("%s",p->name);
p++;
}
return p-*pn;
}
void printXm(struct XuanMin *p,int len)
{
int i;
for(i=0;i<len;i++)
{
printf("名字:%s,票数:%d\n",p->name,p->tickets);
p++;
}
}
int dovot(struct XuanMin *p,int len)
{
int i;
int j;
int feipiao = 0;
int mark;
char tempName[32];
struct XuanMin *pbak = p;
//唱票环节
for(i=0;i<5;i++)
{
mark = 0;
printf("请输入你投给谁:\n");
memset(tempName,'\0',sizeof(tempName));//每次清空一下
scanf("%s",tempName);//输入选中的选民名字,像拆开一个选票,看到名字一样
p = pbak;
for(j=0;j<len;j++)//拿到名字,对应候选人票数加1
{
if(strcmp(tempName,p->name) == 0)
{
p->tickets++;
mark = 1;
}
p++;
}
if(mark == 0)
{
printf("没有此候选人,放弃\n");
feipiao++;
}
}
return feipiao;
}
struct XuanMin* getMax(struct XuanMin* p,int len)
{
struct XuanMin* max;
int i;
max = p;
for(i=0;i<len;i++)
{
if(max->tickets < p->tickets)
{
max = p;
}
p++;
}
return max;
}
int main()
{
struct XuanMin *xm = NULL;
struct XuanMin *final;
int total = 0;
xm = initXm(xm,&total);
printXm(xm,total);
int feip = dovot(xm,total);
printf("废票数是:%d\n",feip);
printXm(xm,total);
final = getMax(xm,total);
printf("%s以%d票当选!!废票是%d\n",final->name,final->tickets,feip);
return 0;
}二级指针

边栏推荐
- Analysis of network security level protection 2.0 standard
- The wave of the meta universe is shocking. Seize the opportunity and work together
- Sequence model (2) - natural language processing and word nesting
- The difference between sprite and overridesprite in unity image (Reprint)
- Leetcode skimming -- bit by bit record 023
- Chrome selenium uses the default profile without emptying it every time
- Chapter 4 Executing Commands
- 数据湖:Delta Lake介绍
- UNITY VFX syntax error: unexpected token ‘#‘ at kernel CSMain
- 12 个适合做外包项目的开源后台管理系统
猜你喜欢

ANTLR4 入门学习(一):下载和测试

The safe distance between you and personal information leakage may be decided by a laptop!

SVG、canvas、绘制线段和填充多边形、矩形、曲线的绘制和填充

XSSGAME小游戏(XSS学习)level1-15

数据湖:从数据仓库看数据湖

微信小程序封装wx.request

PowerBI入门指南

Flutter 运行flutter pub get 报错“客户端没有所需特权“

Redis pseudo cluster one click deployment script - pro test available

0 basic career change software test, the necessary skills with a monthly salary of 6000 and 11000 are quite different
随机推荐
Add trust list
kex_ exchange_ Identification: read: connection reset by peer imperfect solution (one)
C# EventHandler观察者模式
PyQt5_QListWidget分页多选控件
Leetcode skimming -- bit by bit record 022
hbv参数提取和拟合[草稿]
Naming rules of MySQL database table names -- convenient for automatic conversion tools
SVG、canvas、绘制线段和填充多边形、矩形、曲线的绘制和填充
Operator usage and scheduling process of 31 spark
牛客刷题篇——剑指offer (第二期)
写驱动程序的时候warning LNK4210报错
Kubernetes technology and Architecture (VI)
Kubernetes技术与架构(六)
TZC 1283: simple sort - heap sort
mysql的索引的操作
软件测试基础篇—测试用例的设计方法
跳转语句与调试程序
网线水晶头接法图解8根顺序
理解ASP.NET Core - 基于Cookie的身份认证(Authentication)
China Economic Net: "Yuan universe" is hot