嵌入式C语言笔记十七——构造数据类型

一.结构体:

1.类型定义:
struct 结构体名 {数据类型1 成员变量1;数据类型2 成员变量2;数据类型3 成员变量3;...
};struct student {char name[32];char sex;int age;int score;
};
2.结构体变量定义:

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

3.结构体元素初始化:

1.全部初始化:      

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

2.局部初始化:

struct student stu = {.name = {"zhangsan"},    //没有给定初值的元素都被赋值为0.score = 90,
};
4.结构体成员访问:

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

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

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

例:

#include <stdio.h>struct datetime {struct date {int year;int mon;int day;}d;struct time {int hour;int min;int sec;}t;
};struct student {char name[32];char sex;int age;int score;
};int main(void)
{struct datetime dt = {{2025, 7, 29}, {15, 9, 30},};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的日期和时间printf("%02d:%02d:%02d\n", dt.t.hour, dt.t.min, dt.t.sec);printf("%04d-%02d-%02d\n", dt1.d.year, dt1.d.mon, dt1.d.day); // 输出dt1的日期和时间printf("%02d:%02d:%02d\n", dt1.t.hour, dt1.t.min, dt1.t.sec);printf("姓名:%s\n", stu.name); // 输出stu的信息printf("性别:%c\n", stu.sex);printf("年龄:%d\n", stu.age);printf("成绩:%d\n", stu.score);pstu = &s;printf("姓名:%s\n", pstu->name); // 通过指针输出s的信息printf("性别:%c\n", pstu->sex);printf("年龄:%d\n", pstu->age);printf("成绩:%d\n", pstu->score);pdt = &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); // 通过指针输出dt的完整信息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;char str[32] = {0};char tmpsex = 0;int tmpage = 0;int tmpscore = 0;pstu = &s;gets(pstu->name);scanf(" %c", &pstu->sex);scanf("%d", &pstu->age);scanf("%d", &pstu->score);printf("姓名:%s\n", s.name);printf("性别:%c\n", s.sex);printf("年龄:%d\n", s.age);printf("成绩:%d\n", s.score);return 0;
}
5.结构体的存储:

内存对齐:        

struct student {char name[32];char sex;int age;int score; //32(name) + 1(sex) + 3(填充) + 4(age) + 4(score) = 44 字节
};

        结构体成员必须存放在内存地址为自身类型长度整数倍的内存单元中,

        结构体的大小必须为自身最大类型长度的整数倍。

6.结构体传参:

1.传值:

void fun(struct student tmp);

2.传地址:

void fun(struct student *ptmp);
#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;
}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);#if 0ret = GetStuInfo();PutStuInfo(ret);
#endifreturn 0;
}

        传地址更好,因为实参将8字节拷贝给形参,避免结构体大空间的拷贝。

7.结构体数组:

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

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,},
};
9.结构体数组传参:
int fun(struct student *pstu, int len);

二.共用体:

1.共用体也称为联合体:

        共用体每个成员变量的空间共享的,

        结构体每个成员变量的空间是独立的,

        多用于函数传参使用。

2.数据类型定义:
union 共用体名 {数据类型1 成员变量1;数据类型2 成员变量2;数据类型3 成员变量3;...
};
3.使用共用体判断内存大小端:

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

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

#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");}#if 0int Num = 0;char *p = NULL;Num = 0x11223344;p = (char *)&Num;if (0x11 == *p){printf("大端存储\n");}else if (0x44 == *p){printf("小端存储\n");}
#endifreturn 0;
}

三.枚举:

1. 枚举定义一些枚举常量。

2.定义形式:

enum 枚举类型 {常量1,常量2,常量3,...
};

3.特性:

        枚举常量均为int类型,且第一个枚举常量的值默认为0,后续枚举常量的值总是前一个常量的
值+1,

        枚举常量可以在定义时被赋值。

例:

#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;
}

四.练习:

1.计算并显示一个给定日期在当年是第几天,以及该年还剩余多少天:
#include <stdio.h>struct date {int year;int mon;int day;
};int GetDate(struct date *pday)
{scanf("%d-%d-%d", &pday->year, &pday->mon, &pday->day);return 0;
}int IsLeepYear(int tmpyear)
{if (((0 == tmpyear % 4) && (tmpyear % 100 != 0)) || (0 == tmpyear % 400)){return 1;}return 0;
}int GetDayOfYear(struct date *pday)
{int i = 0;int sum = 0;for (i = 1; i < pday->mon; i++){switch (i){case 1:case 3:case 5:case 7:case 8:case 10:case 12:sum += 31;break;case 4:case 6:case 9:case 11:sum += 30;break;case 2: sum += (IsLeepYear(pday->year) ? 29 : 28);}}sum += pday->day;return sum;
}int GetLeftDayOfYear(struct date *pday)
{int total = 0;if (IsLeepYear(pday->year)){total = 366;}else {total = 365;}return total - GetDayOfYear(pday);
}int main(void)
{struct date day;int cnt = 0;GetDate(&day);cnt = GetDayOfYear(&day);printf("%04d-%02d-%02d为该年的第%d天\n", day.year, day.mon, day.day, cnt);cnt = GetLeftDayOfYear(&day);printf("该年剩余%d天\n", cnt);return 0;
}
2.单词顺序反转,并保持内部的顺序不变(不使用逆序算法):
#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, ' '); //使用strchr找到下一个空格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; //合法但危险}
#endifreturn 0;
}int main(void)
{char str[256] = {0};gets(str);wordswap(str);printf("str = %s\n", str);return 0;
}
3.学生信息录入 + 输出:
#include <stdio.h>struct student {char name[32];char sex;int age;int score;
};int GetAllStuInfo(struct student *pstu, int len)
{int i = 0;int n = 0;printf("请输入学生个数:\n");scanf("%d", &n);getchar(); // 读取掉输入个数后的回车,避免后续 gets 被跳过for (i = 0; i < n; 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);    //\n会导致后续输入乱掉scanf("%s", pstu[i].name);scanf(" %c", &pstu[i].sex);scanf("%d", &pstu[i].age);scanf("%d", &pstu[i].score);
#endifgetchar();}return n;
}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[100]; // 最多int curlen = 0; // 实际curlen = GetAllStuInfo(s, 100);PutAllStuInfo(s, curlen); // 接多少输出多少return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95892.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95892.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入实践G1垃圾收集器调优:Java应用性能优化实战指南

深入实践G1垃圾收集器调优&#xff1a;Java应用性能优化实战指南 一、技术背景与应用场景 随着微服务和海量并发请求的普及&#xff0c;Java应用在生产环境中对低延迟和高吞吐的需求日益显著。传统的CMS和Parallel GC 在大内存场景下常出现Full GC 停顿时间长、吞吐下降等问题…

【JobScheduler】Android 后台任务调度的核心组件指南

JobScheduler 是 Android 平台上原生支持在直接启动模式&#xff08;Direct Boot Mode&#xff09;下执行任务的调度器。 相比 WorkManager 需要复杂的配置才能勉强支持直接启动&#xff0c;JobScheduler 在这方面有着天生的优势和明确的 API 支持。如果你面临的硬性要求是必须…

c# 调用basler 相机

目录 一联合halcon&#xff1a; 二 c# 原生 一联合halcon&#xff1a; 环境配置 下载安装pylon软件 下载安装halcon 创建 winform项目 test_basler 添加引用 打开pylon可以连接相机 可以看到我的相机id为23970642 &#xff08; c#联合halcon的基础教程&#xff08;案例…

《2025年AI产业发展十大趋势报告》四十六

《2025年AI产业发展十大趋势报告》四十六随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;作为引领新一轮科技革命和产业变革的战略性技术&#xff0c;正逐步渗透到各个行业和领域&#xff0c;成为推动经济社会发展的重要引擎。2023年&#xff0c;生成式AI的…

c++ 杂记

1. 为什么返回*this?2. 3. 友元函数的使用&#xff1a;需要头文件中类内外声明&#xff0c;cpp文件中实现定义哦// Sales_data.h #ifndef SALES_DATA_H #define SALES_DATA_H#include <string>class Sales_data {std::string bookNo;int units_sold 0;double revenue …

PDF文件基础-计算机字体

计算机字体的原理包含了字符编码、字形渲染和字体文件存储三个关键技术。 字符编码负责将每个字符映射到一个唯一的数字码&#xff1b;字形渲染则将这些数字码转换成屏幕或纸张上可识别的图形&#xff1b;字体文件存储则包含了字符的编码、图形描述信息以及字体的其他属性&…

华为IP(9)

OSPF的基本配置OSPF路由计算前言&#xff1a;1)同一区域内的OSPF路由器拥有完全一致的LSDB&#xff0c;在区域内部&#xff0c;OSPF采用SPF算法完成路由计算。2&#xff09;随着网络规模不断扩大&#xff0c;路由器为了完成路由计算所消耗的内存、CPU资源也越来越多。通过区域划…

java.nio.file.InvalidPathException异常

一.问题概述 本人在ubuntu22.04的操作系统上&#xff0c;运行java程序时创建一个文件时&#xff0c;由于文件名称中包含了中文&#xff0c;所以导致了程序抛出了java.nio.file.InvalidPathException的异常。 java.nio.file.InvalidPathException: Malformed input or input co…

Next系统总结学习(一)

下面我按题号逐条 详细 解释并给出示例与最佳实践。为便于阅读&#xff0c;我会同时给出关键代码片段&#xff08;伪代码/实用例子&#xff09;&#xff0c;并指出常见坑与解决方案。 1. 你是如何理解服务端渲染&#xff08;SSR&#xff09;的&#xff1f;它的核心工作流程是怎…

房屋安全鉴定需要什么条件

房屋安全鉴定需要什么条件&#xff1a;专业流程与必备要素解析房屋安全鉴定是保障建筑使用安全的重要环节&#xff0c;它通过对建筑结构、材料性能及使用状况的全面评估&#xff0c;为房屋的安全使用、改造或维护提供科学依据。随着城市建筑老化及自然灾害频发&#xff0c;房屋…

现代C++:现代C++?

C语言正在走向完美&#xff0c;所以&#xff0c;C语言值得学习&#xff08;甚至研究&#xff09;&#xff0c;这些知识可以成为一切编程的基础。然而在实践中&#xff0c;不必全面的使用C语言的各种特性&#xff0c;而应根据工程项目的实际情况&#xff0c;适当取舍&#xff08…

【C++】哈希表实现

1. 哈希概念 哈希(hash)又称散列&#xff0c;是⼀种组织数据的方式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希 函数把关键字Key跟存储位置建立一个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进行快速查找 1.1 直接定址法…

ai 玩游戏 llm玩街霸 大模型玩街霸 (3)

1. 开源代码地址&#xff1a; https://github.com/OpenGenerativeAI/llm-colosseum 2. 架构&#xff1a; 3. 图片&#xff1a; 4. 感觉还是下面的步骤&#xff1a; a. 实时理解游戏当前环境&#xff0c;英雄角色&#xff0c;英雄状态 b. 根据当前状态感知&#xff0c;生成英雄…

2025年渗透测试面试题总结-59(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 一、SQL注入全解 二、XSS与文件漏洞 三、服务端漏洞专题 四、职业经验与能力评估 1、注入攻击原理是什么…

GPT系列--类GPT2源码剖析

无需多言&#xff0c;大家应该都用过了&#xff0c;如今都更新到GPT-5了。1. GPT-1回到2018年的NLP&#xff0c;神仙打架&#xff0c;BERT与GPT不分先后。GPT是“Generative Pre-Training”的简称&#xff0c;生成式的预训练。BERT和GPT肯定是GPT难训练&#xff0c;引用量也是B…

这是一款没有任何限制的免费远程手机控制手机的软件

这是一款没有任何限制的免费远程手机控制手机的软件支持安卓和苹果1.安装1.1被控制端安装airdroid1.2控制端air mirror2.登录账号控制端和被控制端登录同一个账号3.控制打开控制端软件选择要控制的机器直接点“远程控制“

Observability:更智能的告警来了:更快的分诊、更清晰的分组和可操作的指导

作者&#xff1a;来自 Elastic Drew Post 探索 Elastic Stack 告警的最新增强功能&#xff0c;包括改进的相关告警分组、将仪表盘链接到告警规则&#xff0c;以及将调查指南嵌入到告警中。 在 9.1 版本中&#xff0c;我们对告警进行了重大升级&#xff0c;帮助 SRE 和运维人员更…

数智之光燃盛景 共同富裕创丰饶

8月29日&#xff0c;2025数博会“一带一路”国际大数据产业发展暨数智赋能新时代、共同富裕向未来的会议在贵阳国际生态会议中心隆重举行。作为全球大数据领域的重要盛会&#xff0c;此次活动吸引了来自联合国机构、国际组织、科研院所、知名企业等社会各界的百余位代表&#x…

【网络编程】recv函数的本质是什么?

一、为什么说recv函数的本质是 “copy”&#xff1f; recv是用于从网络连接&#xff08;或其他 IO 对象&#xff09;接收数据的函数&#xff0c;它的核心动作不是 “从网络上拉取数据”&#xff0c;而是 “把已经到达内核缓冲区的数据复制到用户程序的缓冲区”。 具体流程拆解&…

JSP程序设计之输入/输出对象 — out对象

目录1、out对象概述2.实例&#xff1a;out对象方法运用输入/输出对象&#xff0c;可以控制页面的输入和输出&#xff0c;用于访问与所有请求和响应有关的数据&#xff0c;包括out、request和response对象。 1、out对象概述 out对象是JspWriter类的一个实例&#xff0c;是一个…