当前位置: 首页 > news >正文

C语言高级(构造数据类型)

1.构造体

        1.1类型定义

#include<stdio.h>struct date{int year;int mon;int day;};struct time{int hour;int min;int sec;};struct datetime{struct date d;struct time t;};struct students{char name[32];char sex;int age;int score;};int main(void){struct date d;struct time t;struct students stu;                                                                                                                                       return 0;}

        1.2结构体变量定义:

存储类型 数据类型 变量名;

        1.3结构体元素初始化

                全部初始化:

struct student stu={"syf",'m',18,90};

                局部初始化:

struct student stu={
.name ={"zhangsan"},
.score =90,
};

        1.4结构体成员访问

                1).   :结构体变量类型访问成员变量

                2)-> :  结构体指针类型访问成员变量

结构体访问成员变量最终的类型由成员变量的类型决定

对成员的各种访问:

#include <stdio.h>struct date {int year;int mon;int day;};struct time {int hour;int min;int sec;};struct datetime {struct date d;struct time t;};struct student {char name[32];char sex;int age;int score;};int main(void){struct datetime dt = {{2025, 7, 29}, {13, 30,0 },};struct datetime dt1 = {.t = {.hour = 15,.min = 10,},};struct student stu = {"zhangsan", 'm', 19, 100};//全部初始化struct student s = {.name = "lisi",.score = 80,};//局部初始化struct student *pstu = NULL;struct datetime *pdt = NULL;printf("%04d-%02d-%02d\n", dt.d.year, dt.d.mon, dt.d.day);//对dt中变量d的变量year,mon,day访问printf("%02d:%02d:%02d\n", dt.t.hour, dt.t.min, dt.t.sec);//对dt中变量t的变量hour,min,sec访问printf("%04d-%02d-%02d\n", dt1.d.year, dt1.d.mon, dt1.d.day);//对dt1中变量d的变量year,mon,day访问printf("%02d:%02d:%02d\n", dt1.t.hour, dt1.t.min, dt1.t.sec);//对dt1中变量t的变量hour,min,sec访问 printf("姓名:%s\n", stu.name);//对stu中name变量进行访问printf("性别:%c\n", stu.sex);//对stu中sex变量进行访问printf("年龄:%d\n", stu.age);//对stu中age变量进行访问printf("成绩:%d\n", stu.score);//对stu中score变量进行访问pstu = &s;printf("姓名:%s\n", pstu->name);//结构体指针类型访问s中的变量nameprintf("性别:%c\n", pstu->sex);//结构体指针类型访问s中的变量sexprintf("年龄:%d\n", pstu->age);//结构体指针类型访问s中的变量ageprintf("成绩:%d\n", pstu->score);//结构体指针类型访问s中的变量scorepdt = &dt;printf("%04d-%02d-%02d %02d:%02d:%02d\n", pdt->d.year, pdt->d.mon, pdt->d.day, pdt->t.hour, pdt->t.min, pdt->t.sec);//用指针对d和t中的各个变量进行访问return 0;}

                                      

从终端接收数值为成员变量赋值并打印:

#include <stdio.h>
#include <string.h>
struct student 
{char name[32];char sex;int age;int score;
};
int main(void)
{	struct student s;struct student *pstu = NULL;pstu = &s;gets(pstu->name);scanf(" %c", &pstu->sex);scanf("%d", &pstu->age);scanf("%d", &pstu->score);//指针访问
#if 0gets(s.name);	scanf(" %c", &s.sex);scanf("%d", &s.age);scanf("%d", &s.score);
#endif//变量访问printf("姓名:%s\n", s.name);printf("性别:%c\n", s.sex);printf("年龄:%d\n", s.age);printf("成绩:%d\n", s.score);return 0;
}

                                                       

        1.5结构体的存储

                内存对齐:保证cpu一次性把数据拿完。结构体成员必须存放在内存地址为自身类型长度整数倍的内存单元中。结构体的大小必须为自身最大类型长度的整数倍。

                我们对结构体取sizeof计算内存大小,运行结果为44。

#include <stdio.h>struct student {char name[32];char sex;int age;int score;
};int main(void)
{printf("%ld\n", sizeof(struct student));return 0;
}

struct studrnt{char name[32];32字节char sex;1字节,空出三字节int age;4字节int score;4字节
};该构造体一共44字节。
struct aa{
char a;一个字节,空一个字节
short b;两个字节
char c;一个字节
char d;一个字节,空两个字节
int f;四个字节
};该构造体一共12个字节
struct{
char a;一个字节,空一个字节
short b;两个字节
double c;八个字节
short d;两个字节
};一共14个字节,但必须为最大类型的整数倍,这里最大类型为int,因为double为两个int的字节长度,所以向后补上两个字节,一共16个字节

        1.6.结构体传参

              分为值传递和地址传递,但结构体传参一般选择地址传递,值传递拷贝数据导致产生大量内存空间的使用,效率过低。因此选择仅仅拷贝八个字节的地址传递效率更高。

                1.6.1值传递

封装函数选择值传递从终端接收信息和打印信息:

#include <stdio.h>
#include <string.h>//封装函数选择值传递从终端接收信息和打印信息。struct student {char name[32];char sex;int age;int score;};struct student GetStuInfo(void){struct student tmp;gets(tmp.name);scanf(" %c", &tmp.sex);scanf("%d", &tmp.age);scanf("%d", &tmp.score);return tmp;                                                                                                                                                                                                                      }int PutStuInfo(struct student tmp){printf("姓名:%s\n", tmp.name);printf("性别:%c\n", tmp.sex);printf("年龄:%d\n", tmp.age);printf("成绩:%d\n", tmp.score);return 0;}int main(void){struct student ret;memset(&ret, 0, sizeof(ret));//对构造类型初始化ret = GetStuInfo();PutStuInfo(ret);return 0;}

                                              

                1.6.2地址传递

封装函数选择地址传递从终端接收信息和打印信息:

#include <stdio.h>#include <string.h>//封装函数选择地址传递从终端接收信息和打印信息struct student {char name[32];char sex;int age;int score;};void GetStuInfoByPoint(struct student *pstu){gets(pstu->name);scanf(" %c", &pstu->sex);scanf("%d", &pstu->age);scanf("%d", &pstu->score);return;}                                                                                                                                                                                                                                    void PutStuInfoByPoint(struct student *pstu){printf("姓名:%s\n", pstu->name);printf("性别:%c\n", pstu->sex);printf("年龄:%d\n", pstu->age);printf("成绩:%d\n", pstu->score);return;}int main(void){struct student ret;memset(&ret, 0, sizeof(ret));GetStuInfoByPoint(&ret);PutStuInfoByPoint(&ret);return 0;}

                                             

定义一个结构体保存年份信息,判断其是否为闰年,以及这是今年的第几天,今年还剩下多少天:

#include <stdio.h>#include <string.h>struct date {int year;int mon;int day;};void GetDateInfo(struct date *pret){scanf("%d", &pret->year);scanf("%d", &pret->mon);scanf("%d", &pret->day);return;}int  PanDuanDateInfo(struct date *pret){if(pret->year% 400 == 0 || pret->year % 4 == 0 && pret->year % 100 !=0){return 1;}else{return 0;}}int DiJiTian(struct date *pret, int IsRun){int a = 0;int b = 0;int day[]={31,29,31,30,31,30,31,31,30,31,30,31};if(IsRun == 1){for(int i = pret->mon - 1;i != 0;i--){a = day[i];b += a;}b += pret->day;}else{day[1] =28;for(int i = pret->mon - 1;i != 0;i--){a = day[i];b += a;}b += pret->day;}return b;}int ShengJiTian(int ShengXiaDay,int IsRun ){if(IsRun == 1)return 366 - ShengXiaDay;elsereturn 365 - ShengXiaDay;}int main(void){struct date ret;memset(&ret, 0, sizeof(ret));GetDateInfo(&ret);printf("这是今年第%d天\n",DiJiTian(&ret,PanDuanDateInfo(&ret)));printf("今年还剩下%d天\n",ShengJiTian(DiJiTian(&ret,PanDuanDateInfo(&ret)),PanDuanDateInfo(&ret)));return 0;                                                                                                                                                                                                                                                                                                                                                                                                        }

                                              

构造一个函数,将输入的字符串如“ how are you”转变为"you are how":

#include <stdio.h>#include <string.h>void Exchange(char *ptmp){int len = strlen(ptmp);int head = 0;int tail = 0;int i = 0;char trans = '0';for(i = 0;i < len / 2;i++){trans = ptmp[i];ptmp[i] = ptmp[len - i - 1];ptmp[len - 1 - i] = trans;}i = 0;while (i < len){while (i < len && ptmp[i] == ' ')i++;head = i;while (i < len && ptmp[i] != ' ')i++;tail = i - 1;while (head < tail){trans = ptmp[head];ptmp[head] = ptmp[tail];ptmp[tail] = trans;                                                                                                                                                                                                      head++;tail--;}}printf("%s\n", ptmp);}int main(void){char str[100] = {0};gets(str);Exchange(str);return 0;}

也可以这样:

#include <stdio.h>
#include <string.h>int strswap(char *phead, char *ptail){char tmp = 0;while (phead < ptail){tmp = *phead;*phead = *ptail;*ptail = tmp;phead++;ptail--;}return 0;}int wordswap(char *pstr){char *pstart = NULL;char *pend = NULL;//先对整体交换strswap(pstr, pstr+strlen(pstr)-1);pstart = pstr;while (1){pend = strchr(pstart, ' ');if (pend != NULL){strswap(pstart, pend-1);}else{strswap(pstart, pstart + strlen(pstart) - 1);break;}pstart = pend + 1;}#if 0pstart = pstr;pend = pstart;while (*pend != '\0'){pend = pstart;while (*pend != '\0' && *pend != ' '){pend++;}strswap(pstart, pend-1);pstart = pend + 1;}#endif                                                                                                                                                                                                                                                                                                                                                                                                               return 0;}int main(void){char str[256] = {0};gets(str);wordswap(str);printf("str = %s\n", str);return 0;}

                                             

        1.7结构体数组

                数组元素个数必须是常量。

      定义形式:

数据类型 数组名[元素个数];

        1.8结构体数组初始化

全部初始化:struct student s[3] = {{"zhangsan", 'm', 19, 100},{"lisi", 'f', 18, 90},{"wanger", 'm', 19, 60},};
部分初始化: struct student s[3] = {[1] = {.name = "zhangsan",.score = 90,},};

        1.9结构体数组传参

传递形式:

struct student{char name;int age;int scoure[5];
};
int fun(struct student *pstu, int len);
struct student stu [2]= {
{"syf",18,{100,100,100,100,100}},
{"ccc",18,{99,99,99,99,99}}
};
fun(stu,2)

也可以只传数组名

struct student{char name;int age;int scoure[5];
};
int fun(struct student stu[]);
struct student stu [2]= {
{"syf",18,{100,100,100,100,100}},
{"ccc",18,{99,99,99,99,99}}
};
fun(stu)

应用:有一个班的4个学生,有5门课程。
1、求第一门课的平均分;
2、找出有两门以上课程不及格的学生,输出他们的学号和全部课程成绩及平均分                            3、找出平均分在90分以上或全部课程成绩在85分以上的学生。
分别编写三个函数来实现以上三个要求

#include <stdio.h>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           #include <stdlib.h>struct student {char name[32];int no;int score[5];};void AveragScore1(struct student stus[]){float sum = 0;for(int i = 0;i < 4;i++){sum += stus[i].score[0];}printf("第一门课程的平均分为:%lf\n",sum / 4);return;}void FailedScoreTwo(struct student stus[]){int i = 0;float sum = 0;while(i < 4){int j = 0;int cont = 0;while(j < 5){if(stus[i].score[j] < 60){cont++;}j++;}if(cont > 2){for(int k = 0;k < 5;k++){sum += stus[i].score[k];}printf("不及格两门以上学生学号:%d\n",stus[i].no);printf("各科成绩:%d %d %d %d %d\n",stus[i].score[0],stus[i].score[1],stus[i].score[2],stus[i].score[3],stus[i].score[4]);printf("他的平均分为:%lf\n",sum / 5);}i++;sum = 0;}return;}void NBstudent(struct student stus[]){int i = 0;for(i = 0;i < 4;i++){float sum = 0;for(int k = 0;k < 5;k++){sum += stus[i].score[k];}int j = 0;int cont = 0;while(j < 5){if(stus[i].score[j] >= 85){cont++;}j++;}if(cont == 5||sum / 5 >= 90){printf("各科都在85以上或者平均90分的学生:%s \n ",stus[i].name);}}}int main(void){struct student stus[] = {{"XiGua", 101, {78, 75, 88, 82, 99}},{"PingGuo", 102, {90, 59, 89, 39, 42}},{"XiangJiao", 103, {60, 100, 100, 100, 100}},{"Li", 104, {85, 85, 86, 87, 88}}};AveragScore1(stus);FailedScoreTwo(stus);NBstudent(stus);return 0;
}

              

实现接收和打印功能:

#include <stdio.h>struct student {char name[32];char sex;int age;int score;
};int GetAllStuInfo(struct student *pstu, int len)
{int i = 0;for (i = 0; i < len; i++){gets(pstu->name);scanf(" %c", &pstu->sex);scanf("%d", &pstu->age);scanf("%d", &pstu->score);pstu++;
#if 0gets((pstu+i)->name);scanf(" %c", &(pstu+i)->sex);scanf("%d", &(pstu+i)->age);scanf("%d", &(pstu+i)->score);gets(pstu[i].name);
//		scanf("%s", pstu[i].name);scanf(" %c", &pstu[i].sex);scanf("%d", &pstu[i].age);scanf("%d", &pstu[i].score);
#endifgetchar();}	return 0;
}
int PutAllStuInfo(struct student *pstu, int len)
{int i = 0;for (i = 0; i < len; i++){printf("姓名:%s\n", pstu[i].name);printf("性别:%c\n", pstu[i].sex);printf("年龄:%d\n", pstu[i].age);printf("成绩:%d\n", pstu[i].score);}	return 0;
}
int main(void)
{struct student s[3];GetAllStuInfo(s, 3);PutAllStuInfo(s, 3);return 0;
}

2共用体

        2.1共用体的定义

                共用体也称为联合体,其内部成员共享空间。而结构体内部成员空间独立。多用于函数传递不同类型的参数。

        2.2共用体数据类型定义

union 共用体名{
数据类型1 成员变量1;
数据类型2 成员变量2;
数据类型3 成员变量3;
};
#include <stdio.h>union common{char a;short b;int c;};int main(void){union common c1;c1.a = 'A';printf("a = %c\n",c1.a);c1.b = 100;printf("b = %d\n",c1.b);c1.c = 1000;printf("c = %d\n",c1.c);printf("b = %d\n",c1.b);                                                                             return 0;}

                                                    

        可以看出b被c覆盖掉了,因为共用体使用同一个空间,给一个变量赋值会覆盖掉其他变量。

        2.3使用共用体判断内存大小端

                内存低地址存放低数据位,内存高地址存放高数据位,为内存小端

                内存低地址存放高数据位,内存高地址存放低数据位,为内存大端

我们先通过指针判断内存大小端:

#include <stdio.h>
int main(void)
{int Num = 0;char *p = NULL;Num = 0x11223344;p = (char *)&Num;if (0x11 == *p){printf("大端存储\n");}else if (0x44 == *p){printf("小端存储\n");}return 0;
}

             

定义一个int类型的变量Num为其赋值为0x11223344

再定义一个指针p指向Num的首地址,若其首地址存储的数据为0x11,则为大端存储

若为0x44则为小端存储。

图例:

接下来试试共用体判断:

#include <stdio.h>
union s {char a;int b;
};
int main(void)
{union s s1;s1.b = 1;if(s1.a){printf("小端存储\n");}else {printf("大端存储\n");}return 0;
}

定义一个共用体s,为b赋1,由于a占四个字节中的第一个字节,则如果a!=0时则将低数据存放在高数据位,其为大端存储,反之为小端存储。

图例:

3.枚举

形式:
enum Letter {A,B,C,D,E,
};其相当于:
define A 0
define B 1
define C 2
define D 3
define E 4

                枚举常量均为int类型,且第一个枚举常量的值默认为0,后续枚举常量的值总是前一个常量的 值+1 枚举常量可以在定义时被赋值

enum Letter {A,B = 5,C,D,E,
};此时 A = 0B = 5C = 6D = 7 E = 8

枚举的应用:

#include <stdio.h>enum weekday {MONDAY = 1,TUESDAY,WEDNESDAY,THURDAY,FRIDAY,SATURSDAY,SUNDAY,
};int main(void)
{enum weekday day;printf("请输入今天是周几:\n");scanf("%d", (int *)&day);switch (day){case MONDAY:printf("尾号1和6限行\n");break;case TUESDAY:printf("尾号2和7限行\n");break;case WEDNESDAY:printf("尾号3和8限行\n");break;case THURDAY:printf("尾号4和9限行\n");break;case FRIDAY:printf("尾号5和0限行\n");break;case SATURSDAY:case SUNDAY:printf("不限行\n");}return 0;
}

http://www.lryc.cn/news/605245.html

相关文章:

  • 2020 年 NOI 最后一题题解
  • REST、GraphQL、gRPC、tRPC深度对比
  • 订阅区块,部署合约,加载合约
  • 颐顿机电携手观远BI数据:以数据驱动决策,领跑先进制造智能化升级
  • 流程制造的数字孪生:从黑箱生产到全息掌控
  • Linux c网络专栏第四章io_uring
  • Linux零基础Shell教学全集(可用于日常查询语句,目录清晰,内容详细)(自学尚硅谷B站shell课程后的万字学习笔记,附课程链接)
  • Baumer工业相机堡盟工业相机如何通过YoloV8的深度学习模型实现汽车牌照的位置识别(C#代码,UI界面版)
  • 大厂主力双塔模型实践与线上服务
  • SSRF漏洞基础
  • 爬虫验证码处理:ddddocr 的详细使用(通用验证码识别OCR pypi版)
  • Redis 中 key 的过期策略 和 定时器的两种实现方式
  • cocos打包web端需要注意的地方
  • Apache HTTP Server 2.4.50 路径穿越漏洞(CVE-2021-42013)
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现裂缝的检测识别(C#代码UI界面版)
  • 生成式推荐网络架构汇总
  • Java注解与反射:从自定义注解到框架设计原理
  • CHI - Transaction介绍(4) - 原子操作
  • 工厂方法模式:从基础到C++实现
  • Spring Boot 数据源配置中为什么可以不用写 driver-class-name
  • 1. ESP开发之实体按键(KEYPADBUTTON)控制LVGL控件
  • 一文掌握最新版本Monocle3单细胞轨迹(拟时序)分析
  • 【Unity】在构建好的项目里创建自定义文件夹
  • Thales靶机
  • Redis知识点(1)
  • 【力扣热题100】哈希——字母异位词分组
  • 【c++】leetcode763 划分字母区间
  • LeetCode热题100--148. 排序链表--中等
  • 限流算法详解:固定窗口、滑动窗口、令牌桶与漏桶算法全面对比
  • 力扣-543.二叉树的直径