c语言第18天笔记

news2024/9/22 3:55:50

构造类型

结构体类型

结构体数组

案例:

需求:对候选人得票的统计程序。设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出 各人得票结果。

​
/**
* 结构体数组案例:对候选人得票的统计程序。设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出各人
得票结果。
*/
#include <stdio.h>
#include <string.h>
/**
* 定义一个候选人结构体(对象)
*/
struct Person
{
char name[20];// 名字
int count; // 票数
};
// 定义候选人数组,并初始化
struct Person persons[3] = {
{"张月",0},
{"李湘",0},
{"第五名",0}
};
void main()
{
int i,j;
char leader_name[20];// 用来接收被投票的候选人姓名
// 使用一个循环,完成10次投票
for(i = 0; i < 10; i++)
{
printf("请输入您要投票的候选人姓名:\n");
scanf("%s",leader_name);
// 给被投票的候选人+1票
for(j = 0; j < 3; j++)
{
// 如何判断两个字符串相等
if(strcmp(leader_name,persons[j].name) == 0)
{
persons[j].count++;
}
}
}
printf("\n投票结果:\n");
for(i = 0; i < 3; i++)
{
printf("%5s:%d\n",persons[i].name,persons[i].count);
}
}

​

结构体指针

定义:

结构体类型的指针变量指向结构体变量或者数组的起始地址。

语法:

struct 结构体名 *指针变量列表;

举例:

struct Dog
{
char name[20];
int age;
};
struct Dog dog;
struct Dog *p = &dog;

结构体成员访问

结构体成员访问

结构体数组名访问结构体成员

格式:

结构体数组名 -> 成员名;

结构体成员访问符

. :左侧是结构体变量(结构体对象/实例),也可以叫做结构体对象访问成员符;右侧是结 构体成员。

-> :左侧是一个指针,可也以叫结构体指针访问成员符;右侧是结构体成员。

访问结构体成员有两种类型,

三种方式:

类型1:通过结构体对象访问成员

struct Stu
{
int id;
char name[20];
} stu;
// 访问成员
stu.name;

类型2:通过结构体指针访问成员

1. 指针引用访问成员

struct Stu
{
int id;
char name[20];
} stu;
struct Stu *p = &stu;
// 指针引用访问成员
p -> name;

2. 指针解引用间接访问成员

struct Stu
{
int id;
char name[20];
} stu;
struct Stu *p = &stu;
// 指针解引用间接访问成员
(*p).name;

结构体数组中元素的访问

struct Stu
{
int id;
char name[20];
float scores[3];
} stus[3] = {
{1,"张三",{86,88,56}},
{2,"李四",{75,66,78}},
{3,"王五",{70,99,90}}
};
// 取数据 --- 下标法
printf("%s,%2f\n",stus[1].name,stus[1].scores[2]);// 李四,78
// 结构体成员引用符号:-> 指针法
printf("%s,%2f\n",stus -> name,stus -> scores[2]);// 张三,56
printf("%s,%2f\n",(stus + 1)-> name,(stus + 1)-> scores[2]);// 李四,78
printf("%s,%2f\n",(*(stus + 1)).name,(*(stus + 1)).scores[2]);// 李四,78

小贴士:

结构体是自定义数据类型,它是数据类型,用法类似于基本类型的int;

结构体数组它是存放结构体对象的数组,类似于int数组存放int数据;

基本类型数组怎么用,结构体数组就怎么用--->可以遍历,可以作为形式参数,也 可以做指针等;

结构体类型的使用案例

代码:

#include <stdio.h>
// 定义结构体
struct Cat
{
char *name;// 姓名
int age;// 年龄
char color[20];// 颜色
}
// 1.结构体类型作为形式参数
void test1(struct Cat c);
// 2.结构体类型作为形式参数,结构体类型作为返回值类型
struct Cat test2(struct Cat c);
// 3.结构体数组作为形式参数
void test3(struct Cat cats[],int len);
// 4.结构体数组作为形式参数,结构体指针作为返回值数据类型
struct Cat *test4(struct Cat cats[],int len);

测试:

int main()
{
// 定义结构体对象
struct Cat cat = {"小黑",8,"baise"};
// 结构体对象作为实际参数
test1(cat);
// 定义结构体类型对象
struct Cat cat1 = {"小白",8,"heise"};
// 调用函数并接收返回值
struct Cat c1 = test2(cat1);
// 通过返回值访问结构体对象的成
printf("%s==%d==%s\n",c1.name,c1.age,c1.color);
// 定义结构体数组
struct Cat cats[3] = {
{"汤姆",16,"蓝色"},
{"杰瑞",18,"褐色"},
{"唐老鸭",19,"白色"}
};
// 结构体数组名作为实际参数
test3(cats,3);
// 定义结构体数组并初始化
struct Cat cats1[3] = {
{"汤姆",16,"蓝色"},
{"杰瑞",18,"褐色"},
{"唐老鸭",19,"白色"}
};
// 调用函数
struct Cat *p = test4(cats1,3);
struct Cat *w;
// 通过指针运算遍历数组
for(w = p; w < p + 3; w ++)
{
// p[i][j] = *(p[i]+j) = *(*(p+i)+j) 三者等价
// 通过结构体指针访问符访问结构体的成员
printf("%s----%d----%s\n",w -> name,w -> age,w -> color);
}
}

结构体类型求大小

规则:

字节对齐(默认,数据在内存中存储在其类型大小的整数倍上)

1. 首先保证结构体中的成员存储在自身的对齐边界(类型大小的整数倍);

2. 在满足1的条件下,最终大小要满足 最大成员 所占存储单元的整数倍;

为什么要使用字节对齐:

节省内存,提高访问效率。

在GNU标准中,可以在定义结构体时,指定对齐规则:

__attribute__((packed)); 结构体所占内存大小是所有成员所占内存大小之和
__attribute__((aligned(n))); 设置结构体占n个字节,如果n比默认值小,n不起作用;n必须是2的次方

柔性数组:

struct st { ... char a[0]; }

柔性数组不占有结构体的大小。

案例:

/**
* 求结构体数据类型的大小
*/
#include <stdio.h>
// 定义测试结构体
struct TEST1
{
char a;// 1
int b; // 4
};
struct TEST1_1
{
char a;// 1
int b;// 4
}__attribute__((packed));// 取消字节对齐,取消之后,结构体数据类型大小就等于其所有成员的数据类型之和
struct TEST1_2
{
char a __attribute__((aligned(2)));
int b;
};
struct TEST2
{
char a;// 1
short c; // 2
int b; // 4
};
struct TEST3
{
int num;// 4
char name[10];// 10
char sex;// 1
int age;// 4
double score;// 8
};
struct TEST4
{
int num;// 4
short name[5];// 10
char sex;// 1
int age;// 4
int scores[2];// 8
};
int main()
{
// 创建结构体变量
struct TEST1 test1;
struct TEST2 test2;
struct TEST3 test3;
struct TEST4 test4;
struct TEST1_1 test1_1;
struct TEST1_2 test1_2;
// 计算大小
printf("%lu\n",sizeof(test1));
printf("%lu\n",sizeof(test2));
printf("%lu\n",sizeof(test3));
printf("%lu\n",sizeof(test4));
printf("%lu\n",sizeof(test1_1));
printf("%lu\n",sizeof(test1_2));
}

推导过程:

快速计算结构体大小:

共用体/联合体类型

定义:

使几个不同的变量占用同一段内存的结构。

共用体按定义中需要存储空间最大的成员来分配存储单 元,其他成员也是用该空间,他们的首地址是相同。

定义格式:

union 共用体名称
{
数据类型 变量名;
数据类型 变量名;
...
};

共用体的定义和结构体类型类似:

1. 可以有名字,也可以匿名;

2. 共用体在定义时也可以定义共用体变量;

3. 共用体在定义时也可以初始化成员;

4. 共用体也可以作为形参和返回值类型使用;

5. 共用体也可以定义共用体数组 ... 也就是说,结构体的语法,共用体都支持。

注意: 共用体弊大于利,尽量少用,一般很少用;

共用体变量在某一时刻只能存一个数据,并且也只能取出一个数。

公用题和结构体都是自定义数据类型,用法类似于基本数据类型

共用体可以是共用体的成员,也可以是结构体的成员。

结构体可以是共用体的成员,也可以是共用体的成员。

案例:

/**
* 共用体
*/
#include <stdio.h>
// 定义共用体
union S
{
char a;
float b;
int c;
};
// 共用体作为共用体的成员
union F
{
char a;
union S s;
};
// 共用体作为结构体的成员
struct G
{
int a;
union S s;
};
// 定义一个结构体
struct H
{
int a;
char b;
};
// 结构体作为结构体成员
struct I
{
int a;
int b;
struct H h;
};
// 共用体作为结构体成员
struct J
{
int a;
char b;
union S s;
};
void test1()
{
// 定义共用体类型
union Stu
{
int num;
char sex;
double score;
};
// 定义匿名共用体:匿名共用体一般作为结构体成员或者其他共用体成员
union
{
int a;
char c;
} c;
printf("%lu,%lu\n",sizeof(union Stu),sizeof(c));
}
void test2()
{
union C
{
int a;
char b;
};
// 定义变量
union C c;
// 存数据
c.a = 10;
c.b = 'A';
printf("%d---%d\n",c.a,c.b);// 取数据
c.a += 5;
printf("%d---%d\n",c.a,c.b);// 取数据
union E
{
char *f;
long a;
int b;
} e = {"hello world!"};
printf("%s,%p---%ld,%p---%d\n",e.f,&(e.f),e.a,&(e.a),e.b);
}
int main()
{
test1();
test2();
}

枚举类型

定义:

我们一般情况下,定义常量使用宏定义(#define 宏名称 值),宏定义非常适合没有关联关系的常 量;但是有时候我们可能需要对一组拥有关联关系的量进行定义,比如 周一~周日 、 1月~12月 等, 那么使用宏定义,就不是很清晰在,这个时候就需要使用到枚举。

枚举的存在就是将多个拥有关联关系的常量组合到一起,提高代码的可读性。

说明:

枚举类型定义了一组常量,我们在开发中直接使用这些常量。(常用)

当然枚举类型也可以类似于结构体一样定义变量等操作。(不常用)

枚举常量有默认值,从0开始依次加1;我们可以在定义时指定它的值,如果个别没有赋值,可以根 据赋值依次加1推导。

特点:

定义了一组常量,类似于定义了多个自定义常量(宏定义)

提供了代码的可读性(避免了魔术数字)

定义语法:

定义枚举类型名以后就可以定义该枚举类型的变量

enum 枚举类型名 变量表;

在定义枚举类型的同时定义该枚举类型的变量。

enum 枚举类型名{ 枚举元素列表 }变量表;

直接定义枚举类型变量。

enum { 枚举元素列表 }变量表;

案例:

/**
* 枚举类型
*/
#include <stdio.h>
// 常量-宏定义
// 常量的命名:大写英文字母+下滑下,举例:MAX_VALUE
#define PI 3.1415926
void test1()
{
// 定义枚举类型
enum Week
{
SUN=10,MON,TUE,WED,THU,FRI,SAT
};
printf("%d,%d,%d\n",SUN,WED,SAT);
// 定义枚举类型的变量(先定义变量,后赋值)
enum Week w;
// 初始化
w = MON;
printf("%d\n",w);
// 定义枚举类型的变量同时赋值(定义变量的同时赋值)
enum Week w1 = THU;
printf("%d\n",w1);
enum H
{
A,B,C
} x,y;
x = B;
y = C;
printf("x=%d,y=%d\n",x,y);// 1,2
}
void test2()
{
// 定义枚举
enum CaiQuan
{
SHI_TOU,JIAN_DAO,BU
};
printf("请输入0~2之间的整数:\n[0-石头,1-剪刀,2-布]\n");
int number;
scanf("%d",&number);
switch(number) // switch和enum是天生的搭档
{
case SHI_TOU:
printf("石头\n");
break;
case JIAN_DAO:
printf("剪刀\n");
break;
case BU:
printf("布\n");
break;
}
}
int main()
{
test1();
test2();
}

typedef

说明:

给类型重命名,不会影响到类型本身

作用:

给已有的类型起别名

格式:

typedef 已有类型名 新别名;

使用:

// 定义结构体
struct Student
{
int id;
char *name;
char sex;
int age;
};
// 类型重命名
typedef struct Student Stu;
// 定义变量
struct Stu stu = {1,"张甜",'M',21};
// 定义结构体的同时类型重命名
typedef struct PersonInfo
{
int a;
double b;
} Per;
// 定义变量
struct Per per = {2,5};

应用场景

1. 数据类型复杂(结构体,共用体,枚举,结构体指针)时使用

2. 为了跨平台兼容性,例如:

1. size_t:类型重命名后的数据类型, typedef unsigned long size_t;

2. unit_16:类型重命名后数据类型

案例:

//类型重命名
#include <stdio.h>
struct Student
{
int age;
char* name;
double score;
int arr[3];
};
typedef struct Student Stu_t;
typedef Stu_t* pStu_t;
void test1()
{
Stu_t s1 = {23, "zhangsan", 23.33, {11, 22, 33}};
printf("%d, %s, %f, %d\n", s1.age, s1.name, s1.score, s1.arr[0]);
//Stu_t *p = &s1;
Stu_t* p;
p = &s1;
pStu_t p2;
p2 = p;
printf("%d, %s, %f, %d\n", p2->age, p2->name, p2->score, p2->arr[0]);
}
int main()
{
test1();
return 0;
}

章节作业

1. 设计一个结构体,存放一个学员信息并显示,存放两个学员信息,算他们的平均分。

2. 设计一个描述商品的结构体,存放一个商品信息,并显示。

3. 作业2的基础之上完成以下功能:

(1)存储多个商品的信息,后显示

(2)查询价格最高的商品的信息

(3)用静态分配(结构体变量)和动态分配分别实现。

4. 开发一个简易的成绩管理系统: 存储多个学员信息并处理 要求如下:

(1)申请多个空间,存入学员信息

(2)求分数最高学员姓名

(3)求总分和平均分

(4)统计查询 查询平均分以上学员的姓名

(5)按照成绩排序

5. 确认电脑的主机字节序。大端(高字节的数据存放在低地址上,低字节的数据存放在高地址上), 小端(高字节的数据存放在高地址上,低字节的数据存放在低地址上)

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

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

相关文章

主机组装笔记

参考资源&#xff1a;B站【装机教程】全网最好的装机教程&#xff0c;没有之一&#xff0c;仅供探讨学习 9大部件一览 其中得到固态和机械&#xff0c;是硬盘&#xff0c;存储空间&#xff0c;可以只选固态 CPU&#xff0c;主要有 AMD 和 Intel (AMD&#xff0c;基板的背面布…

力扣 58. 最后一个单词的长度

题目描述 思路 下意识想到先以空格作为分割符对字符串进行分割得到若干个子字符串&#xff0c;然后用字符串长度计算函数计算最后一个子字符串的长度。 该思路代码如下&#xff1a; class Solution:def lengthOfLastWord(self, s: str) -> int:s_array s.split()last_le…

全新在线客服系统源码(pc+h5+uniapp+公众号小程序+抖音)附搭建接入教程

全新在线客服系统源码介绍 一、系统概述与优势 本系统是一款基于PHP的开源在线客服系统&#xff0c;支持PC端、移动端(小程序)、H5页面以及Uniapp多端接入。系统利用网络技术和人工智能技术&#xff0c;实现用户与客服人员的即时聊天沟通&#xff0c;有效提升服务质量和用户满意…

Python+Selenium+Pytest+POM自动化测试框架封装详解

1、测试框架简介 1&#xff09;测试框架的优点 代码复用率高&#xff0c;如果不使用框架的话&#xff0c;代码会显得很冗余。可以组装日志、报告、邮件等一些高级功能。提高元素等数据的可维护性&#xff0c;元素发生变化时&#xff0c;只需要更新一下配置文件。使用更灵活的…

透明加密软件排行榜前十名(2024年10大好用的透明加密软件推荐)

在当今数字化的时代&#xff0c;数据的安全性和保密性已经成为了企业和个人最为关注的问题之一。随着信息技术的飞速发展&#xff0c;各种数据泄露事件层出不穷&#xff0c;给企业和个人带来了巨大的损失。在这样的背景下&#xff0c;透明加密软件应运而生&#xff0c;成为了保…

商家转账到零钱申请必过教程2024

在微信作为重要的营销场景的当下&#xff0c;微信支付的商家转账到零钱功能对于众多企业来说具有重要意义。要顺利开通该接口&#xff0c;需要注意以下几个要点。 首先&#xff0c;需要公司主体资质。申请主体必须是公司&#xff0c;个体工商户暂无法申请。同时&#xff0c;要确…

8.15成都市计量院面试问答

&#x1f416; Q&#xff1a;为什么要选择计量检定测试院&#xff1f; A&#xff1a;市计量院具备多项资质认定和计量认证项目&#xff0c;选择成都市计量检定测试院&#xff0c;意味着接触前沿技术&#xff0c;积累丰富经验&#xff0c;服务社会公益&#xff0c;参与创新研发&…

spring揭秘01-spring容器启动过程分析

文章目录 【README】【1】Spring容器根据配置元素组装可用系统的过程【2】BeanFactoryPostProcessor-Bean工厂后置处理器【2.1】属性占位符配置器使用场景代码【2.2】CustomerEditorConfigurer-自定义编辑器配置器【2.3】自定义编属性编辑器案例代码 【README】 本文总结自《s…

为什么electron占用空间大,而Tauri占用小,他们不都是封装Chromium吗

Electron 和 Tauri&#xff08;使用 WebView&#xff09;的确都涉及嵌入浏览器引擎来渲染 HTML、CSS 和 JavaScript&#xff0c;但它们的架构和设计有显著不同&#xff0c;这导致了它们在应用程序体积和资源占用上的差异。以下是一些关键的原因&#xff1a; 1. 嵌入的浏览器引…

【中等】 猿人学web第一届 第6题 js混淆-回溯

文章目录 请求流程请求参数 加密参数定位r() 方法z() 方法 加密参数还原JJENCOde js代码加密环境检测_n("jsencrypt")12345 计算全部中奖的总金额请求代码注意 请求流程 请求参数 打开 调试工具&#xff0c;查看数据接口 https://match.yuanrenxue.cn/api/match/6 请…

MySQL运维-分库分表

介绍 问题分析 拆分策略 垂直拆分 水平拆分 实现技术 Mycat概述 介绍 概念介绍 Mycat配置 schema.xml schema标签 schema标签&#xff08;table&#xff09; datanode标签 datahost标签 rule.xml sever.xml system标签 user标签 Mycat分片 分片规则-范围 分片规则-取模 分…

linux部署elasticserch单节点

简介 Elasticsearch概述&#xff1a;Elasticsearch是一个建立在Apache Lucene之上的分布式、实时文档存储搜索引擎&#xff0c;它能够胜任上百个服务节点的扩展&#xff0c;并支持PB级别的结构化或非结构化数据。 Lucene与Elasticsearch&#xff1a;简要介绍Lucene作为搜索引擎…

分布式中的CAP理论是什么?BASE理论是什么?看完你就彻底懂啦

CAP 理论 CAP理论是分布式系统理论中的一个重要概念&#xff0c;它阐述了在分布式计算环境中&#xff0c;一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和分区容错性&#xff08;Partition Tolerance&#xff09;三者之间的权衡关系…

深化解析:企业内耗的解决之道

在缺乏有效的冲突解决机制下&#xff0c;企业内部冲突难以得到妥善处理&#xff0c;这加剧了内耗&#xff0c;破坏了团队协作的和谐氛围。而当工作环境充满紧张和压力时&#xff0c;员工容易陷入焦虑和疲劳的困境&#xff0c;进而影响工作效率和团队士气。 当员工感受不到应有…

拯救中医 刻不容缓

文&#xff5c;琥珀食酒社 作者 | 积溪 “真是毫无底线” “这是挂羊头卖狗肉” “这钱也赚&#xff0c;华为太让人失望了” 看到网上的这些评论 我的拳头都硬了 华为进军中医药产业 给咱中医药打造独一无二的人工智能大模型 让中医彻底摆脱西方的围剿 这是多好的事情…

如何提取PDF其中的一页或多页?推荐4种方法!

工作中&#xff0c;我们经常需要用到PDF文件&#xff0c;如果需要提取PDF文件中的其中一页或多页内容&#xff0c;要如何做呢&#xff1f;下面小编分享4种方法&#xff0c;看下哪种适合你&#xff01; 方法1&#xff1a;使用复制粘贴 如果PDF文件中需要提取的内容是纯文字&am…

一起学习LeetCode热题100道(42/100)

42.将有序数组转换为二叉搜索树(学习) 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0…

python连接mysql+mycat读写分离实现

python连接mysql >>>import pymysql >>>connpymysql.connect(host"192.168.118.57",port3306,database"test",user"root",password"root") >>> cursorconn.cursor() >>> cursor.execute(&quo…

ISO 13485认证:医疗器械行业的质量护航者

在医疗器械行业&#xff0c;产品质量关乎生命。为确保每一件医疗器械的安全与可靠&#xff0c;ISO 13485认证作为全球公认的质量管理体系标准&#xff0c;正为无数企业提供强大的质量保障。对于企业来说&#xff0c;获得这一认证不仅是质量管理的提升&#xff0c;更是开拓全球市…

FFmpeg源码:av_log2函数分析

一、av_log2函数的声明 av_log2函数声明在FFmpeg源码&#xff08;本文演示用的FFmpeg源码版本为7.0.1&#xff09;的头文件libavutil/common.h中&#xff1a; #ifndef av_log2 av_const int av_log2(unsigned v); #endif 该函数作用是&#xff1a;求形参v是2的多少次幂&#…