------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
预处理指令、文件操作及其他
以"#"号开头的预处理指令,如命令#include,宏定义命令#define等。在源程序中这么命令都放在函数之外,而且都放在源文件前面,他们称为预处理部分
所谓预处理是指在进行编译的第一遍(词法扫描和语法分析)之前的工作。
x 语言多种预处理指令功能:宏定义、文件包含、条件编译
.o .out
源程序->预处理(宏替换)-> 编译 -> 链接-> 执行程序
一、预处理指令
1、宏定义
宏:在c语言中我们自定义的标示符,习惯大写
#include 宏名 宏字符串 (可以是常量、变量、表达式)
注意:预处理指令,经常写在函数之前
宏替换:源程序在编译之前,由预处理程序对我们写的源代码进行处理:会把源代码中所出现 宏名 的地方一律使用 宏的字符串 去替换
宏使用的注意事项:
1.宏是有作用域的 #undef 宏名 可以取消宏定义
#include R 4
int a= R
#define R M 这里取消宏定义,下面的代码用不了宏了
2.在字符串中出现的宏名不会被替换
3.宏定义可以嵌套使用
#define R 4
#define PI 3.14
#define AREA PI*R*R //嵌套定义
4,使用宏起别名
#include INT1 int
这样就可以 这么定义整型
INT1 a=10;
5.有参数宏和无参数宏
无参数宏 #include M 10
有参数宏 #define SUM(a) a+a
有参数宏的使用注意事项:
宏的形参之间可以出现空格 ,但是宏名和形参之间不能空格
有参数宏 宏的参数最好用括号括起来
应用使用有参宏求最大值
#include
//定义一个有参宏 求两个数的最大值
#define MAX(a,b) a>b?a:b
int main(int argc, const char * argv[]) {
// 调用宏
int c =MAX(3, 4);
printf("最大值是%d",c);
return 0;
}
6 typedef 和#include 的区别
当 #include INT1 int
typedef int INT2;
这里 INT1 a,b a,b都是定义的整型变量
INT2 a,b 也一样是整型变量
定义指针时
#include INT3 int*
typedef int* INT4 ;
INT1 f1,f2 =NULL; 这里f1 是zhiz 而f2只是个整型变量 说明宏的定义知识单纯的文本复制的替换
INT4 f1,f2 = NULL; 这里 f1,f2 都是指针。
2.条件编译指令
1. #if -#elseif
条件编译 :
发生在预处理阶段 ,在编译之前做的事情
核心:根据条件编译指定的代码
条件不同,编译的部分也不同,生成的目标文件(.o)大小也不一样
传统方式
int score =76;
判断成句属于哪个成绩
if(score<60){
printf("E\n");
}else if(score<= 69){
printf("d\n");
}else if(score<= 79){
printf("c\n");
}else if(score<= 89){
printf("b\n");
}else {
printf("A\n")
}
#if score <60
printf("E\n");
#elif scoe <=69
printf("d\n");
#elif scoe <=79
printf("c\n");
#elif scoe <=89
printf("b\n");
#else
printf("a\n");
#endif
这里只选择一个符合要求的score 进行一段代码的预编译
2.#ifdef 有来判断某个宏是否定义
#include DEBUG1 1
int a=0;
#ifdef DEBUG1 DEBUG1为1是执行 a=10 ;
a=10; 否则执行 a=100;
#else
a=100;
#endif
3.使用条件编译指令调试bug
#if DEBUG1 ==1 1或0 1显示调试信息 0不显示调试信息
//显示调试信息
#define Log(format,....)printf(format,##__VA_ARGS__);
#else
#define Log(format,.......)
//不显示调试信息
#endif
二、文件操作
1。文件概念
文件; 指存储在外部介质上数据的集合,这个数据有一个名称,叫做文件名
文件的分类 从用户角度 文件分为普通文件和设备文件
从文件编码 文件分ascii码文件和二进制文件
文件操作的步骤
1)引入头文件
2)定义文件指针
3)打开文件
4)文件读写
5)关闭文件
对文件读和写是最常用的文件操作,在c语言中提供了多种文件读写的函数
字符读写函数 fgetc和fputc
读写字符串函数 fgets和fputs
数据快读写函数 fread 和fwrite
格式化读写 fscanf 和fprintf
c语言文件指针
在c语言中用一个指针变量指向一个文件,这个指针称为文件指针
文件指针
FILE *指针变量表示符;
2。文件的打开和关闭函数
文件操作步骤
1)引入头文件 stdio.h
2)建立文件指针 FILE *fp =NULL;
3)打开文件 fopen(文件名,操作方式);
如果文件打开成功返回文件收地址,失败返回NULL
4)操作文件
5)关闭文件 fclose(文件指针);
#include
int main(int argc, const char * argv[]) {
//定义文件指针
FILE *fp =NULL;
//打开文件 是文件操作方式
fp =fopen("a.txt", "r");
//fopen成功,返回的是文件首地址
//fopen失败 返回NULL
if(fp!=NULL){
//文件操作
printf("文件打开成功\n");
}else{
//给用户提示
printf("文件打开失败,请任意键退出\n");
//按任意键推出
getchar();//要求从键盘接受一个字符
//退出
exit(1);//非正常退出
}
//文件关闭
fclose(fp);
return 0;
}
3文件使用的方式及注意事项
文件使用方式
4字符读写函数 fgetc和putc
字符读写函数是以字符(字节)为单位的读写函数。每次可以从文件读出或向文件写入一个字符
fputc() 写入一个字符到文件中
假设把 ch写到 fputc1.txt 文件中
char ch ='x''
#include
void test(){
char ch ='x';
//打开文件 打开fputc1.txt 以w方式(写,如果文件不存在可创建)
FILE *fp=fopen("fputc1.txt", "w");
//判断文件是否打开成功
if (fp != NULL) {
//将ch 要写入的字符 文件指针
//写到fput1.txt文件中
fputc(ch,fp);
printf("写入成功\n");
}
//关闭文件
fclose(fp);
}
int main(int argc, const char * argv[]) {
FILE *fp=fopen("fputc1.txt", "r");
//判断文件是否打开成功
c = fgetc(fp);
if (fp != NULL) {
//字符文件要读取到的位置 c 文件指针
//写到fput1.txt文件中
printf("%c\n",c);
printf("文件打开成功\n");
}
//关闭文件
fclose(fp);
return 0;
}
使用 fgetc 和fputc 读取和写入字符串
#include
#include
int main(int argc, const char * argv[]) {
//定义文件指针,打开文件 futcString.txt 以w写入
FILE *fp=fopen("fputcString.txt","r");
if(fp!=NULL){
// char ch[]="i love china";
// for(int i=0;i
int main(int argc, const char * argv[]) {
FILE *fp =fopen("string1.txt","w+");
if (fp!=NULL) {
printf("请输入一个字符串\n");
char ch;
ch = getchar();
5.字符串读写函数 fgets 和fputs
#include
int main(int argc, const char * argv[]) {
//把字符串写入到文件中去
char str[]="welcome to yilake";
FILE *fp = fopen("fputsstring.txt", "w+");
if (fp!=NULL) {
int count =0;
// 写入字符串到文件中 ,count 返回读取的字符数
count = fputs(str,fp );
printf("写入成功,本次写入%d个字节]\n",count);
rewind(fp);
char str1[20];
//从文件中读取字符到字符数组str1中
// 数组名 长度 文件指针
fgets(str1, sizeof(str1),fp);
// fgets读取的时候,当文件读取完会自动的给字符后面加'\0'
//fgets读取的时候,遇到\n或者EOF ,读取完毕
printf("输入的字符串是%s",str1);
}
//关闭文件指针
fclose(fp);
return 0;
}
6.数据快的读写函数fread 和fwrite
一般形式fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
buffer时指针用来存放数据输入的首地址 表示存放数据输出的首地址
size 表示数据块字节数
count 表示要读写的数据块块数
fp 表示文件指针
#include
#include
int main(int argc, const char * argv[]) {
//fwrite 写一个数据块
//先写一个字符串
FILE *fp =fopen("fwrite.txt", "w+");
if (fp!=NULL) {
// 写文件
char *str ="helloworld!";
//fwrite(地址,块大小,数据,文件指针);
fwrite(str,strlen(str),1,fp);
printf("文件写入成功\n");
rewind(fp);
char str1[12];
//读出一个到字符数组str1中
fread(str1, sizeof(str1), 1, fp);
printf("%s",str1);
}
fclose(fp);
return 0;
}
应用读写结构体
#include
struct Student{
char name[21];
int age;
float score;
};
int main(int argc, const char * argv[]) {
struct Student stu[2]={{"李白",18,88.88f},{"杜甫",23,99.99f}};
FILE *fp =fopen("studentScore.data","wb+");
if (fp!=NULL) {
for (int i=0; i<2; i++) {
//从文件中读取一个元素(32)到stu中去
//每次都写入一个元素
fwrite(&stu[i], sizeof(struct Student), 1,fp);
}
printf("写入成功\n");
printf("————————————————— ii\n");
rewind(fp);
struct Student stu1[2];
//从文件循环读取
for (int i=0; i<2; i++) {
//从文件中读取一个元素(32)到stu中去
fread(&stu1[i], sizeof(struct Student), 1,fp);
}
//查看读取数据
for (int i = 0; i<2; i++) {
printf("姓名%s 年龄%d 成绩%.2f\n",stu1[i].name,stu1[i].age,stu1[i].score);
}
}
fclose(fp);
return 0;
}
7.格式化读写函数 fscanf和 fprintf
两个函数调用的格式
fscanf(文件指针,格式字符串,输入列表);
fprintf(文件zhiz,格式化字符串,输出列表);
列如要求 把数据照这个样格式
0#1;
1#2;
2#3;
#include
int main(int argc, const char * argv[]) {
FILE *fp =fopen("fprintf.txt", "w+");
if (fp!=NULL) {
int a= 3,b=4;
fprintf(fp,"%d#%d;",a,b );
printf("写入成功\n");
rewind(fp);//指针回到文件首地址
int m=0,n=0;
//从文件中读取数据到变量中
fscanf(fp, "%d#%d;",&m,&n);
printf("%d,%d",m,n);
}
fclose(fp);
return 0;
}
8.读取和写入一个二维数组
#include
int main(int argc, const char * argv[]) {
int a[3][2]={1,2,3,4,5,6};
FILE *fp =fopen("arr.txt", "w+");
if (fp!=NULL) {
for (int i=0; i<3; i++) {
fprintf(fp, "%d,%d#", a[i][0],a[i][1]);
}
printf("写入成功\n");
rewind(fp);
int c[3][2];
for (int i=0; i < 3; i++) {
fscanf(fp, "%d,%d#",&c[i][0],&c[i][1]);
}
for (int i=0; i<3; i++) {
for (int j=0; j <2 ;j++ ) {
printf("%d\t",c[i][j]);
}
}
}
fclose(fp);
return 0;
}
9文件的随机读写实现
fseek(文件zhiz,位移量 ,起始点);
位移量 表示移动的字节数,要求位移量是long类型数据,要求加后缀“L”
起始点 表示从何处开始计算位移量,规定的起始点有三种,文件首,当前位置和文件尾。
文件首 SEEK_SET 0
当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2
只输出第二个人的信息
#include
struct Student{
char*name;
int age;
float score;
};
int main(int argc, const char * argv[]) {
struct Student gril[3]={{"zsf",18,34.55f},{"lzl",23,88.88f},{"lzz",22,99.99f}};
FILE *fp =fopen("student.data", "w+");
if (fp!=NULL) {
for (int i =0; i<3; i++) {
fwrite(&gril[i], sizeof(struct Student), 1, fp);
}
printf("写入成功\n");
rewind(fp);
// 移动的字节数 起始点
struct Student gril1;
// 文件定位 从起始点开始移动(32个字节)
fseek(fp, sizeof(struct Student), SEEK_SET);
fread(&gril1, sizeof(struct Student),1, fp);
printf("姓名 %s 年龄%d 成绩%.2f\n",gril1.name,gril1.age,gril1.score);
}
return 0;
}
10.文件结束检函数feof
feof(fp)也就是找文件结束的标志。
读写出错函数 ferror (文件指针);
能检查文件在输入输出时读写是否出错 如果ferror返回的时0就表示没有出错,否则表示文件有错。
文件出错标志和文件结束标志函数
clearerr(文件指针) 用于清除错误标志和文件结束标志,使他们为0值