栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

结构、联合、枚举、文件相关操作

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

结构、联合、枚举、文件相关操作

1、结构

​ 结构是一种由程序员自己设计的数据类型,用于描述一个 事务的各项特征数据,由若干个不同的基础类型组成

​ 设计:

​ struct 结构类型名

​ {

​ 类型 成员名1;

​ 类型 成员名;

​ …

​ };

​ 定义结构变量:

​ struct 结构类型名 结构变量名 ;

​ 注意:struct在C语言中,定义结构变量时不能省略

​ 定义结构变量并初始化:

​ struct 结构类型名 结构变量名 ={v1,v2,v3,…};

​ 初始化顺序一定要与成员顺序一致

​ struct 结构类型名 结果变量名 ={.成员名2=v2,.成员名1=v1,…};

​ 顺序不考虑 ,只初始化某些成员,顺序无序一致

​ 注意:同类型的结构变量可以直接给另一个结构变量 初始化

​ 注意:这种赋值方式只能在定义时使用

​ 访问成员 :

​ 结构变量名.成员名;

​ 由于结构变量的字节数一般都比较大,普通的值传递,效率非常低,因此传递结构变量的地址,也即是传递结构指针变量,此时想要通过结构指针变量访问成员时借助 -> ,如果不需要修改指针变量的成员值,可以使用const保护

​ 结构指针变量名 -> 成员名 ;

练习一:设计一个 教师结构体类型,类型中要有成员 :姓名、性别、工号、工龄,定义一个教师结构变量,使用scanf输入每个成员的值并显示(day14 struct)

​ typedef 重定义结构类型名:

​ typedef struct 结构类型名 结构类型名;

​ typedef struct 结构类型名

​ {

​

​ }结构类型名;

​ 之后定义结构类型,可以不加struct

​ 如何计算结构体的总字节数:(下标0开始,编号计算,对齐后加自己大小,计算字节数时要加一)

​ **注意:**结构成员顺序会影响它 的总字节数,如果能够在设计结构体时合理地安排成员顺序 ,可以大大地节约内存

​ 内存对齐:

​ 假设第一个成员从零地址开始,存储 每个成员的地址编号必须能被该成员的 字节类型整除,如果不能整除则填充空白字节

​ 内存补齐:

​ 结构体的总字节数,必须是它最大成员字节数的整数倍,如果不能整除,则在末尾补充空白字节

​ 注意:在Linux系统下计算结构体的对齐补齐时,如果成员的字节数超过四,则按照4字节计算对齐补齐

​ windows是按实际字节数对齐补齐

​ #pragma pack(n) 可以设置对齐、补齐的最大字节数为n但n<=4(1,2,4)

​ **注意:**结构体适合使用堆内存存储

​


2、联合union

​ 联合与结构使用方法几乎一致,与结构的区别是联合所有的成员共用一块内存,一个成员的值发生改变,其他成员也随之改变

​

​ 联合的效果 就是使用少量的内存对应多个标识符 ,以此达到节约内存的目的,但现在几乎不使用

	union Data
    {
    char ch[5];
    int num;
	};

​ sizeof(union Data)==8

注意:计算联合总字节数时,不需要考虑内存对齐,但需要考虑内存补齐

如何判断系统的大端小端?

​ 假设 十六进制 0x01020304 存储在以0x0A~0x0D的四字节内存中(一个字节可以存两位)

​ 大端系统:高位数据存储在低位地址(例:0x0D存0x04、…、0x0A存0x01)

​ 小端系统:高位数据存储在高位地址(例:0x0D存0x01、…、0x0A存0x04)

​ 个人计算机一般都是小端系统 (大存大),而UNIX服务器和网络设备都是大端,网络字节序也是大端模式数据,本地字节序就是小端 模式的数据

​ 序列化和反序列化

常考编程题:实现一个程序,判断系统是大端还是小端

union Data
{
    char ch; 
    int num;
};
//给num赋值,因为共享内存,所以查看ch的值可以知道大端还是小端
3、枚举enum

​ 枚举就是一种数据类型,把可能出现的所有的值罗列出来,并起一个有意义的名字表示这些值,除此之外给该类型的变量赋其他值是非法的(愿望)

enum Direction
{
    up=183,
    down=184,
    right=185,
    left=186
};

​ 枚举可以看做一种值受限的int类型,但C编译器为了效率不检查(超出没关系),所以在C中枚举就相当于int类型变量

​ 如果不给成员值,那么枚举中的值第一个默认从0开始,逐渐加1,如果设置了某个值,后面的成员在它的 基础上逐渐加1

​

为什么用枚举:

​ 为无意义 的值取一个有意义的名字,提高代码的可读性,提高安全性(比变量安全)

作业1:通讯录更改为使用结构存储、使用堆内存存储

文件分类:

​ 文本文件:存储ASCII码的二进制 ‘2‘ ’5‘ ’5‘ 50 53 53

​ 二进制文件:存储的是数据的补码 255 1111 1111

文件IO:

	FILE *fopen(const char *path, const char *mode);
	FILE*fp=fopen("failename","打开模式");//可以命名fwp提示自己只写
​	FILE*fp=fopen("failename","打开模式");
	perror("fopen");打开失败可以用来代替printf显示错误

​ 功能:打开或创建文件

​ path:文件的路径

​ mod:文件打开的模式

​ r 以只读权限打开文件,如果文件不存在则失败

​ r+ 在r的基础上,增加写权限

​ w 以只写权限打开文件,如果文件存在则清空打开,如果文件不存在则新建

​ w+ 在w的基础上,增加读权限

​ a 以只写权限打开文件,如果文件存在则在末尾追加,如果文件不存在则新建

​ a+ 在a的基础上,加读权限

​ 返回值:文件指针,不需要关心有什么数据,只需要知道它是一个针对已打开文件的凭证,打开失败会返回NULL

二进制方式的读写:

	size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
		功能:把内存中的数据写入到文件中
        ptr:待写入的内存的首地址
        size:一次写入的字节数
        nmemb:写入的次数
        stream:文件指针,fopen的返回值,表示往哪个文件写入数据
        返回值:成功写入的次数
 	size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
		例:fread(&tea,sizeof(tea),1,frp);
		功能:从文件读取数据到内存中
        ptr:接收文件数据的内存首地址
        size:一次读取多少字节数
        nmemb:读取的次数
        stream:文件指针,表示从哪个文件读取数据
        返回值:成功读取的次数

练习2:设计并定义一个教师结构变量并初始化,以二进制方式写入到文件中(m-day15,t-day16)

练习3:从文件中读取教师结构体数据到变量中并显示(m-day15,t-day16)

文本方式读写文件:

int fprintf(FILE *stream,const char *format,...);
	功能 :以文本
int fscanf(FILE *stream, const char *format, ...);
	fscanf(frp,"%数据类型 %数据类型... ",& ,& ...);
	功能:从文件中读取数据到变量中
	stream:要读的文件
	format:占位符(数据格式)
    ...:变量返回的地址
    返回值:成功读取的变量个数

练习4:设计并定义一个教师结构变量并初始化,以文本方式写入到文件中(m-day15,t-day16)

练习5:从文件中读取教师结构体数据到变量中并显示(m-day15,t-day16)

关闭文件:

​ int fclose(FILE *stream);

​ 功能:关闭一个打开的文件

​ 返回值 :成功0,失败-1

​ 注意:如果需要立即修改文件的内容,最好先关闭文件

文件的位置指针:

​ 每个通过fopen打开的文件都有一个文件位置指针来记录着接下来要读写的位置,以r、r+、w、w+方式打开文件,位置指针在文件的开头,以a以及a+打开文件,位置指针自动在末尾

​ 如果想要随意读写文件的位置,那么可以通过手动设置文件位置指针的位置

​ fseek

   int fseek(FILE *stream, long offset, int whence);
	功能:手动设置位置指针位置
    stream:文件指针
    offset:偏移值
    whence:基础位置
        SEEK_SET	文件开头
        SEEK_CUR	当前位置
        SEEK_END	文件末尾
    返回值:成功(调整后位置指针还在文件中)返回0,失败返回-1
   long ftell(FILE *stream);
	功能:把文件位置指针设置到文件开头
   void rewind(FILE *stream);
	功能:获取当前文件位置指针的位置
    返回:在第几个字节
   int fgetc(FILE *stream);
	功能:从一个文件中读取一个字符
    返回值:失败、读取完毕返回EOF(-1)
   char *fgets(char *s, int size, FILE *stream);
	功能:读取一个字符串到s中,最多读size-1个
    返回值:成功返回非负整数,失败返回-1
        
   int fputc(int c, FILE *stream);

   int fputs(const char *s, FILE *stream);
	功能 :写入一个字符串到文件中
    返回值:成功返回非负整数,失败返回-1

   int remove(const char *pathname);
	功能:删除文件
    pathname:文件路径
    返回值:成功返回0,失败返回-1
        
   int rename(const char *oldpath, const char *newpath);
	功能:重命名文件
    返回值:成功返回0,失败返回-1

命令行参数:main函数的参数

​ 是为了获取./a.out 命令行中的参数

​ argc 代表了命令行参数的行数

​ argv 每个参数字字符串的首地址

​ 注意:./a.out是argv[0]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1033531.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号