全国咨询/投诉热线:400-618-4000

c/c++培训C语言核心知识总结(九)

更新时间:2016年10月21日16时41分 来源:传智播客C++培训学院 浏览次数:

九、文件操作;
 
数据I/O流
 
#include <stdio.h>
 
1 fopen()函数:打开文件
函数原型:FILE *fopen(char restrict *filename, char restrict *mode);
// restrict C99标准才引进的,属于类型修饰符,表示修饰的这块内存空间只能被这个指针引用和修改,除此之外别无他法。
 
参数:
filename: 需要打开的文件
mode: 文件打开方式
 
r 以只读的方式打开文件,前提是这个文件必须存在(只写 r 默认是文本文件)
r+ 以可读可写的方式打开文件,前提是这个文件必须存在(默认是文本文件)。
rb 以只读的方式打开一个二进制文件,前提是这个文件必须存在。
rb+ 以可读可写的方式打开一个二进制文件,前提是这个文件必须存在。
 
w 以只写的方式打开文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则清空内容。
w+ 以可读可写的方式打开文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则清空内容。
wb 以只写的方式打开一个二进制文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则清空内容。
wb+ 以可读可写的方式打开一个二进制文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则清空内容。
 
a 以追加的方式打开只写文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则在文件尾部追加内容。
a+ 以追加的方式打开一个可读可写的文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则在文件尾部追加内容。
ab 以追加的方式打开一个二进制只写文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则在文件尾部追加内容。
ab+ 以追加的方式打开一个二进制可读可写文件,如果这个文件不存在,就创建这个文件;如果这个文件存在,则在文件尾部追加内容。
 
 
r(read): 读;
w(write):写;
a(append):追加;
+(plus):读或写,主要是配合r、w、a使用;
t(text):文本文件;
b(binary):二进制文件
 
返回值:如果文件顺利打开,则返回值是指向这个文件流的文件指针,
如果文件打开失败,返回 NULL (void*)0
 
一般来说,文件打开失败会做一个文件指针错误判断
FILE *fp = fopen("c:\\code\\text.c", "w+");
if(NULL == fp)
{
//code
//exit(-1);
}
 
2 fgetc(); 和 fputc();
1) fgetc() 文件字符读取函数
原型: int fgetc(FILE * stream);
参数: stream: 文件流
返回值: 成功返回获取的字符ASCII码,失败返回 EOF(-1);
举例:
char ch = fgetc(fp); // 从fp指向的文件流里接收文件流里的第一个字符
 
 
2) fputc() 文件字符写入函数
原型: int fputc(int ch, FILE * stream);
参数: ch :就是写入的字符,函数在执行的时候,会自动把 ch ASCII码 转换成一个 unsigned char 类型。
stream: 文件流
返回值: 成功返回输出的字符,失败返回 EOF(-1);
举例:
fputc(ch, fp); // 把字符ch写入到 fp 所指向的文件流里。
 
3 fgets(); 和 fputs();
1) fgets() 读取文件字符串函数
原型:char *fgets(char *str, int size, FILE* fp);
参数: str : 保存从fp指向的文件流里读取的一行字符串。
size: 从文件流里读取的字符串不超过 size 个字符。( 一般会使用size - 1,留一个字符位置给 '\0')
fp : 文件指针
返回值:成功返回读取的字符串所在的内存首地址,失败返回 NULL(0);
举例:
char str[20] = { 0 };
fgets(str, 20 - 1, fp); // 从fp指向的文件流的第一行里读取 19个字符,然后放到字符数组 str里。
 
2) fputs() 写入文件字符串函数
原型:int fputs(char *str, FILE* fp);
参数: str: 要写入到文件里字符串(不包括'\0')
fp: 文件指针,成功写入一个字符串后,文件指针会自动后移
返回值:成功为写入的字符个数,失败则返回 EOF(-1)。
举例:
char str[20] = "Hello Kitty!";
fputs(str, fp); // 向 fp 指向的文件流里写入一个字符串 str,具体怎么写,看 mode 属性。
 
4 fprintf(); 和 fscanf();
1) fprintf() 将格式化后的数据写入到文件流里
原型: int fprintf(FILE *stream, char *format, argument...);
举例:
int i = 10;
float f = 3.14;
char ch = 'C';
char str[10] = "haha";
fprintf(fp, "%d %f %c %s\n", i, f, ch, str); // 将各个数据按格式写入到文件流里
 
2) fscanf() 从文件流里获取数据格式化写入输入流里
原型: int fscanf(FILE *stream, char *format, argument... );
举例:
int i;
float f;
char ch;
char str[10];
fscanf(fp, "%d,%f", &i, &f);
// 如果不需要从文件里面写入字符串,那么就可以用逗号或者其他符号来分隔
 
fscanf(fp, "%s%c", str, &ch);
// 如果文件里需要写入字符串,那么字符串与其他数据之间只能用空格和回车来分隔
 
 
5 fread(); 和 fwrite(); 二进制文件读写函数
函数原型:
size_t fread(void *ptr, size_t size, size_t count, FILE* fp);
size_t fwrite(void *ptr, size_t size, size_t count, FILE* fp);
参数: ptr: 是一个指针,对应 fread()来说,是从文件里读入的数据存放的地址;
 对应 fwrite()来说,是写入到文件里的数据存放的地址。
size: 每次要读写的字节数
count : 读写的次数
fp: 文件指针
 
返回值: 成功读取/写入的字节数
 
举例:
char str[] = { 0 };
fread(str, sizeof(char) * 10, 1, fp);
// 每次从fp指向的文件中读取10个字节大小,放入字符数组 str 中,总共读1次
fwrite(str, sizeof(char) * 10, 1, fp);
// 每次从str里获取 10个字节大小,写入到 fp 指向的文件中,总共写1次
 
 
6 fseek(); 文件指针操作函数
函数原型: size_t fseek(FILE* fp, long offset, int whence);
参数: fp : 文件指针
offset:  偏移量,基于起始点偏移了 offset 个字节
whence : 起始点(三个):
SEEK_SET 0 文件开头位置
SEEK_CUR 1 当前位置
SEEK_END 2 文件结尾位置
 
举例
 fseek(fp, 0, SEEK_END);
 // 将文件指针指向文件结尾,并偏移了 0 个字节,也就是直接将文件指针指向文件结尾
 fseek(fp, -10, SEEK_CUR);
 // 将文件指针指向当前位置,并偏移了 -10 个字节,也就是将文件指针往前移动10个字节
 
7 ftell(); 文件指针操作函数
函数原型:  long ftell(FILE* fp);
参数: fp  文件指针
返回值:返回文件指针当前位置,基于文件开头的偏移字节数,
 
举例: long len = ftell(fp);
// 返回文件指针当前位置,基于文件开头的偏移字节数,保存到 len 里。
 
8 rewind(); 文件指针操作函数
函数原型: void rewind(FILE* stream);
参数: fp 文件指针
 
举例: rewind(fp);
// 将文件指针重新指向I/O流(文件流)的开头。
 
stream > istream / ostream -> fstream -> sstream
 
6\7\8 大例子
 
FILE *fp = fopen("C:\\code\\a.txt", "r+");
fseek(fp, 0, SEEK_END); // 将文件指针指向文件结尾
long len = ftell(fp); // 获取文件指针位置,得到文件的大小(Byte)
rewind(fp); // 将文件指针重新指向文件开头
 
9 fflush(); 清空数据流里的数据
 
函数原型:  void fflush(FILE* stream);
参数: stream 数据流
 
举例:
fflush(fp); // 清空文件流
fflush(stdin); // 清空输入流
fflush(stdout); // 清空输出流
 
 
10 int stat(const char *path, struct stat *buf);
// 自行补充
 
 
11 rename(); 和 remove();
 
rename(FILE* filename1, FILE* filename2);
rename("old_name.txt", "new_name.txt");
// 把old_name.txt 重命名为 new_name.txt
 
remove(FILE* filename);
remove("C:\\code\\a.txt");
// 将 绝对路径下的 a.txt 文件删除
 
12 feof();
原型: int feof(FILE* fp);
参数: fp  文件指针
返回值: 一旦文件指针指向文件结尾,就返回一个真值;否则返回非真值(0)
 
1. 这个函数达到文件结尾的时候,返回的是一个真值,所以在做判断的时候要注意 !feof(fp)
2. 这个函数必须对文件进行过一次读写操作才会生效,也就是说哪怕这个文件是空的,也必须读写一次,feof()才会返回真值。
文件结束是一个标识符,每次对文件读写都会修改这个标识符的位置,对文件读写一次,文件标识符才会被找到,feof()做出返回操作。
 
13 fclose();
原型: int flcose(FILE* fp);
参数: fp 文件指针
返回值: 如果成功释放,返回 0, 否则返回 EOF(-1);
 
fclose(fp); 表示释放文件指针和相关的文件缓冲区,文件指针不再合法指向那块区域,但是不代表清空对应的区域。

 
 
UTF-8 编码格式下 一个汉字 3 个字节
GBK 编码格式下 一个汉字 2 个字节
 
// UTF-8 下 汉字逆置原理
#include <stdio.h>
#include <string.h>
 
int main(void)
{
char str[] = "阿基米德";
int len = strlen(str);
 
// printf("%c%c\n", str[0], str[1]); // 打印"阿"
 
for (int i = len - 1; i > 0; i -= 3) // UTF-8 编码下是3个字节,GBK下是2个字节
{
printf("%c%c\n", str[i - 1], str[i]);
}
 
 
return 0;
}
 
不同操作系统的行尾标志:
CR LF \ CR \ LF
 
CR 是 '\r' 回车
LF 是 '\n' 换行
 
在DOS和NT内核的Windows下,采用的是 回车+换行(CR LF '\r''\n') 来表示下一行的开始
在Unix/Linux下,采用的是 换行(LF '\n') 来表示下一行的开始
在Macintosh下(OS X) ,采用的是 回车(CR '\r') 来表示下一行的开始
本文版权归传智播客C++培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:传智播客C/C++培训学院
首发:http://www.itcast.cn/c/