《C语言程序设计》笔记p9
文件操作
什么是文件
文件是一个用来长期存储数据的字节组成的数据集合。
文件的操作步骤:
- 打开文件
- 读/写文件
- 关闭文件
头文件: #include <stdio.h>
**打开文件: **fopen 函数
typedef struct file {} FILE;
FILE *fopen(const char *pathname, const char *mode);
文件操作的两种方式:
- 以文本文件的方式进行操作
- 以二进制文件的方式进行操作
fopen 的第二个参数(文件打开模式)
模式 | 含义 |
---|---|
"r" | 读文本文件 |
"w" | 写文本文件,没有文件则创建文件(清空文件内容) |
"a" | 写文本文件,没有文件则创建文件(不清空文件内容,在后面追加内容) |
"x" | 写文本文件,如果文件已经存才则报错 |
"rb" | 读二进制(binary)文件 |
"wb" | 写二进制文件,没有文件则创建文件(清空文件内容) |
"ab" | 写二进制文件,没有文件则创建文件(不清空文件内容,在后面追加内容) |
"xb" | 写二进制文件,如果文件已经存才则报错 |
关闭文件: fclose
int fclose(FILE *stream);
// 成功返回0 ,失败返回其他值
读文件: fscanf(文本模式),fread(二进制模式),
int fscanf(FILE *stream, const char *format, ...);size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
// 参数 size 是每个块的大小。
// 参数:nmemb 是要写入的块数。
// 返回值:成功写入的 nmemb 的个数,如果不等于nmemb则说明写入失败
fprintf 示例
写一个程序,创建一个文件me.txt
,写如一个人的姓名和年龄。
#include <stdio.h>int main(int argc, char * argv[]) {FILE *pf = NULL; // 用来保存打开文件的结构体地址。//* 打开文件pf = fopen("./me.txt", "w");if (pf == NULL) {printf("打开文件失败\n");return 1;}//* 读/写文件fprintf(pf, "%s\t", "laowei");fprintf(pf, "%d", 35);// 文件内容:name:laoweiage:35//* 关闭文件fclose(pf);return 0;
}
fscanf示例
#include <stdio.h>int main(int argc, char * argv[]) {char name[100];int age;int score;FILE *pf = NULL; // 用来保存打开文件的结构体地址。//* 打开文件pf = fopen("your.txt", "r");if (pf == NULL) {printf("打开文件失败\n");return 1;}//* 读/写文件int ret;ret = fscanf(pf, "%s%d%d", name, &age, &score);printf("ret: %d ", ret);printf("name:%s, age:%d, score:%d\n", name, age, score);ret = fscanf(pf, "%s%d%d", name, &age, &score);printf("ret: %d ", ret);printf("name:%s, age:%d, score:%d\n", name, age, score);ret = fscanf(pf, "%s%d%d", name, &age, &score);printf("ret: %d ", ret);printf("name:%s, age:%d, score:%d\n", name, age, score);//* 关闭文件fclose(pf);return 0;
}
写文件: fprintf(文本模式),fwrite(二进制模式)
int fprintf(FILE *stream, const char *format, ...);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
fwrite 示例
#include <stdio.h>int main(int argc, char * argv[]) {char name[50] = "laowei";int age = 35;int score = 60;FILE *pf = NULL; // 用来保存打开文件的结构体地址。//* 打开文件pf = fopen("./me_b.txt", "wb");if (pf == NULL) {printf("打开文件失败\n");return 1;}//* 读/写文件fwrite(name, 50, 1, pf);fwrite(&age, sizeof(age), 1, pf);fwrite(&score, sizeof(score), 1, pf);//* 关闭文件fclose(pf);return 0;
}
fread 示例
#include <stdio.h>int main(int argc, char * argv[]) {char name[50] = "xxxxxxxxxxxxxx";int age = 0;int score = 100;FILE *pf = NULL; // 用来保存打开文件的结构体地址。//* 打开文件pf = fopen("./me_b.txt", "rb");if (pf == NULL) {printf("打开文件失败\n");return 1;}//* 读/写文件int ret;ret = fread(name, 50, 1, pf);printf("ret: %d, name:%s\n", ret, name);ret = fread(&age, sizeof(age), 1, pf);printf("ret: %d, age:%d\n", ret, age);ret = fread(&score, 1, sizeof(score), pf);printf("ret: %d, score:%d\n", ret, score);//* 关闭文件fclose(pf);return 0;
}
xxd 命令
作用:用十六进制方式显示文件内容
命令格式:
xxd 文件路径
fseek 函数
用于重新设置文件的读写指针的位置。随机读取二进制文件的内容。
格式:
int fseek(FILE *stream, long offset, intwhence);
参数whence 的值:
- SEEK_SET: 从文件头开始计算。
- SEEK_CUR:从当前位置开始计算。
- SEEK_END:从文件末尾开始计算。
参数 offset:代表文件的偏移量(整数)。
- 0 不变。
- 正数,向后移动。
- 负数,向前移动。
编译预处理和宏
- 文件包含
- 条件编译
- 宏定义
文件包含
- #include <头文件>
- #include "头文件"
条件编译
- #if 常量表达式
- #elif 常量表达式
- #else
- #endif
- #ifdef 是否定义宏
- #ifndef 是否没有定义宏
示例代码
#include <stdio.h>int main(int argc, char * argv[]) {
#if 1printf("welcome to beijing!\n");
#elseprintf("欢迎来到北京!\n");
#endifreturn 0;
}
宏定义
宏是在预处理阶段,将一个名字和字符串相关连,在预处理阶段进行替换。
- 不带参数的宏定义
- 带有参数的宏定义
不带参数的宏定义
语法
#define 宏名 宏的内容
带有参数的宏定义
语法
#define 宏名(参数1, 参数2,...) 宏的内容
示例
#define PI 3.1415926#define AREA(rr) 3.14*rr*rrint main(int argc, char * argv[]) {float r = 10;//圆的半径float area = PI * r * r;float area2 = AREA(r);return 0;
}
宏中的特殊字符
# 用于将参数转成字符串
## 用于参数代码级别的拼接
示例
#include <stdio.h>#define TO_STR(a) #a
#define JOIN(a,b) a##bint main(int argc, char * argv[]) {int myscore = 100;printf("%s\n", TO_STR(XX)); // printf("%s", "XX");printf("%d\n", JOIN(my, score)); // printf("%s", myscore);return 0;
}
系统预定义的宏
__DATE__:当前源文件的编译日期,格式为 "Mmm dd yyyy"(如 "Aug 6 2023")。
__TIME__:当前源文件的编译时间,格式为 "hh:mm:ss"(如 "14:30:00")。
__FILE__:当前源文件的文件名(字符串形式)。
__LINE__:当前代码行的行号(十进制整数)。
__func__(C99 引入):当前所在的函数名(字符串形式)。
示例:
#include <stdio.h>void hello_c(void) {printf("当前函数名:%s\n", __func__);printf("当前行号:%d\n", __LINE__);
}int main(int argc, char * argv[]) {hello_c();return 0;
}
避免头文件重复包含的头文件写法
#ifndef TEST_H
#define TEST_Hvoid say_hello(void); #endif
示例
定义一个宏 名为 RECT_LENHTH(a, b) ..... 给出长和宽,返回周长的有参数的宏。
#include <stdio.h>#define RECT_LENHTH(a, b) (2 * (a) + 2 * (b))int main(int argc, char * argv[]) {printf("%d\n", 2 * RECT_LENHTH(5+1, 2+2));return 0;
}