9. 其他

九、其他

1. 共用体(联合体)

  • 联合union是一个能在同一个存储空间存储不同类型数据的类型;

  • 联合体所占的内存长度等于其最长成员的长度倍数,也有叫做共用体;

  • 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只有一种起作用;

  • 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖;

  • 共用体变量的地址和它的各成员的地址都是同一地址。

#include <stdio.h>

//共用体也叫联合体
union Test{
	unsigned char a;
	unsigned int b;
	unsigned short c;
};
int main(){
//定义共用体变量
union Test tmp;
//1、所有成员的首地址是一样的
printf("%p, %p, %p\n", &(tmp.a), &(tmp.b), &(tmp.c));
//2、共用体大小为最大成员类型的大小
printf("%lu\n", sizeof(union Test));
//3、一个成员赋值,会影响另外的成员
//左边是高位,右边是低位
//低位放低地址,高位放高地址
tmp.b = 0x44332211;
printf("%x\n", tmp.a); //11
printf("%x\n", tmp.c); //2211
tmp.a = 0x00;
printf("short: %x\n", tmp.c); //2200
printf("int: %x\n", tmp.b); //44332200
return 0;
}

2. 枚举

枚举:将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。

枚举类型定义:

enum 枚举名{

​ 枚举值表

};

  • 在枚举值表中应列出所有可用值,也称为枚举元素。

  • 枚举值是常量,不能在程序中用赋值语句再对它赋值。

  • 举元素本身由系统定义了一个表示序号的数值从0开始顺序定义为0,1,2 …

#include <stdio.h>
enum weekday
{
	sun = 2, mon, tue, wed, thu, fri, sat
};

enum bool
{
	flase, true
};

int main()
{
	enum weekday a, b, c;
	a = sun;
	b = mon;
	c = tue;
	printf("%d,%d,%d\n", a, b, c);
	enum bool flag;
	flag = true;
	if (flag == 1){
		printf("flag为真\n");
	}
	return 0;
}

3. typedef

typedef为C语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型。

  • 与#define不同,typedef仅限于数据类型,而不是能是表达式或具体的值

  • #define发生在预处理,typedef发生在编译阶段

#include <stdio.h>
	typedef int INT;
	typedef char BYTE;
	typedef BYTE T_BYTE;
	typedef unsigned char UBYTE;
	typedef struct type{
		UBYTE a;
		INT b;
		T_BYTE c;
	}TYPE, *PTYPE;
int main()
{
	TYPE t;
	t.a = 254;
	t.b = 10;
	t.c = 'c';
	PTYPE p = &t;
	printf("%u, %d, %c\n", p->a, p->b, p->c);
	return 0;
}

十、文件操作

1. 概述

  • 磁盘文件

    ​ 指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上,使用时才调入内存。

  • 设备文件

    ​ 在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输入、输出等同于对磁盘文件的读和写。

2. 磁盘文件的分类

计算机的存储在物理上是二进制的,所以物理上所有的磁盘文件本质上都是一样的:以字节为单位进行顺序存储。

从用户或者操作系统使用的角度(逻辑上)把文件分为:

  • 文本文件:基于字符编码的文件

  • 二进制文件:基于值编码的文件

1)文本文件

  • 基于字符编码,常见编码有ASCII、UNICODE等

  • 一般可以使用文本编辑器直接打开

  • 数5678的以ASCII存储形式(ASCII码)为:00110101 00110110 00110111 00111000

2)二进制文件

  • 基于值编码,自己根据具体应用,指定某个值是什么意思

  • 把内存中的数据按其在内存中的存储形式原样输出到磁盘上

  • 数5678的存储形式(二进制码)为:00010110 00101110

3. 文件的打开和关闭

文件指针: 指向文件的指针变量

typedef struct{
	short level; //缓冲区"满"或者"空"的程度
	unsigned flags; //文件状态标志
	char fd; //文件描述符
	unsigned char hold; //如无缓冲区不读取字符
	short bsize; //缓冲区的大小
	unsigned char *buffer;//数据缓冲区的位置
	unsigned ar; //指针,当前的指向
	unsigned istemp; //临时文件,指示器
	short token; //用于有效性的检查
}FILE;

FILE是系统使用typedef定义出来的有关文件信息的一种结构体类型,结构中含有文件名、文件状态和文件当前位置等信息。

声明FILE结构体类型的信息包含在头文件“stdio.h”中,一般设置一个指向FILE类型变量的指针变量,然后通过它来引用这些FILE类型变量。通过文件指针就可对它所指的文件进行各种操作。

C语言中有三个特殊的文件指针由系统默认打开,用户无需定义即可直接使用:

  • stdin:标准输入,默认为当前终端(键盘),我们使用的scanf、getchar函数默认从此终端获得数据。

  • stdout:标准输出,默认为当前终端(屏幕),我们使用的printf、puts函数默认输出信息到此终端。

  • stderr:标准出错,默认为当前终端(屏幕),我们使用的perror函数默认输出信息到此终端。

4. 文件的打开

任何文件使用之前必须打开:

#include <stdio.h>

FILE * fopen(const char * filename, const char * mode);

功能:打开文件

参数:

filename:需要打开的文件名,根据需要加上路径

mode:打开文件的模式设置

返回值:

成功:文件指针

失败:NULL

//相对路径:
FILE *fp_passwd = fopen("passwd.txt", "r");

//打开当前目录test下passwd.txt文件
fp_passwd = fopen(". / test / passwd.txt", "r");

//打开当前目录上一级目录(相对当前目录)passwd.txt文件
fp_passwd = fopen(".. / passwd.txt", "r");

//绝对路径:
//打开C盘test目录下一个叫passwd.txt文件
fp_passwd = fopen("c:/test/passwd.txt","r");

第二个参数的几种形式(打开文件的方式):

打开模式含义
r或rb以只读方式打开一个文本文件(不创建文件,若文件不存在则报错)
w或wb以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
a或ab以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件
r+或rb+以可读、可写的方式打开文件(不创建新文件)
w+或wb+以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
a+或ab+以添加方式打开可读、可写的文件。若文件不存在则创建文件;
如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留。

注意:

  • b是二进制模式的意思,b只是在Windows有效,在Linux用r和rb的结果是一样的

  • Unix和Linux下所有的文本文件行都是\n结尾,而Windows所有的文本文件行都是\r\n结尾

  • 在Windows平台下,以“文本”方式打开文件,不加b:

    • 当读取文件的时候,系统会将所有的 “\r\n” 转换成 “\n”

    • 当写入文件的时候,系统会将 “\n” 转换成 “\r\n” 写入

    • 以"二进制"方式打开文件,则读写都不会进行这样的转换

  • 在Unix/Linux平台下,“文本”与“二进制”模式没有区别,"\r\n"
    作为两个字符原样输入输出

int main(void)
{
	FILE *fp = NULL;
	// "\\"这样的路径形式,只能在windows使用
	// "/"这样的路径形式,windows和linux平台下都可用,建议使用这种
	// 路径可以是相对路径,也可是绝对路径
	fp = fopen("../test", "w");
	//fp = fopen("..\\test", "w");
	if (fp == NULL){ //返回空,说明打开失败
	//perror()是标准出错打印函数,能打印调用库函数出错原因
	perror("open");
	return -1;
	}
	return 0;
}

5. 文件的关闭

任何文件在使用后应该关闭:

  • 打开的文件会占用内存资源,如果总是打开不关闭,会消耗很多内存

  • 一个进程同时打开的文件数是有限制的,超过最大同时打开文件数,再次调用fopen打开文件会失败

  • 如果没有明确的调用fclose关闭打开的文件,那么程序在退出的时候,操作系统会统一关闭。

#include <stdio.h>

int fclose(FILE * stream);

功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。

参数:

stream:文件指针

返回值:

成功:0

失败:-1

FILE * fp = NULL;

fp = fopen(“abc.txt”, “r”);

fclose(fp);

4. 文件的顺序读写

1)写文件

#include <stdio.h>

int fputc(int ch, FILE * stream);

功能:将ch转换为unsigned char后写入stream指定的文件中

参数:

​ ch:需要写入文件的字符

​ stream:文件指针

返回值:

​ 成功:成功写入文件的字符

​ 失败:返回-1

2)文件结尾

EOF作为文本文件的结束标志

在文本文件中,数据都是以字符的ASCII代码值的形式存放。ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。

#define EOF (-1)当把数据以二进制形式存放到文件中时,就会有-1值的出现,因此不能采用EOF作为二进制文件的结束标志。为解决这一个问题,ANSIC提供一个feof函数,用来判断文件是否结束。

feof函数既可用以判断二进制文件又可用以判断文本文件。

int feof(FILE * stream);

功能:检测是否读取到了文件结尾。判断的是最后一次“读操作的内容”,不是当前位置内容(上一个内容)。

参数:

​ stream:文件指针

返回值:

​ 非0值:已经到文件结尾

​ 0:没有到文件结尾

3)读文件

#include <stdio.h>

int fgetc(FILE * stream);

功能:从stream指定的文件中读取一个字符

参数:

​ stream:文件指针

返回值:

​ 成功:返回读取到的字符

​ char ch;

//检测文件结束字符
while ((ch = fgetc(fp)) != EOF){
	printf("%c", ch);
}
	printf("\n");

//文件没有结束,则执行循环
while (!feof(fp)){ 
	ch = fgetc(fp);
	printf("%c", ch);
}
printf("\n");

1)写文件

#include <stdio.h>

int fputs(const char * str, FILE * stream);

功能:将str所指定的字符串写入到stream指定的文件中,字符串结束符 ‘\0’

参数:

​ str:字符串

​ stream:文件指针

返回值:

​ 成功:0

​ 失败:-1

2)读文件

#include <stdio.h>

char * fgets(char * str, int size, FILE * stream);

功能:从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size

  • 1个字符为止,最后会自动加上字符 ‘\0’ 作为字符串结束。

参数:

​ str:字符串

​ size:指定最大读取字符串的长度(size - 1)

​ stream:文件指针

返回值:

​ 成功:成功读取的字符串

​ 读到文件尾或出错: NULL

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆羽飘扬

如果有用,请支持一下。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值