C语⾔基础之⽂件、宏定义规则
⽂件类型指针
C语⾔在stdio.h中定义了⼀个FILE⽂件结构体类型,包含管理和控制⽂件所需要的各种信息。在C程序中系统对⽂件进⾏的各种操作是通过指向⽂件结构体的指针变量来实现的。
定义⼀个指向⽂件结构体类型的指针变量的形式:
FILE *指针变量名;
⽂件的打开
C语⾔⽂件的打开是通过stdio.h函数库中的fopen()函数实现的。fopen()函数的原型是:
FILE *fopen(char *filename, char *mode);
其中filename是要打开的⽂件名,mode是说明处理⽂件的⽅式。它的调⽤⽅式⼀般为:
⽂件指针变量 = fopen(⽂件名,处理⽂件⽅式);
处理⽂件⽅式附图:
如果是⼆进制⽂件,在使⽤时在模式后添加字符b即可,如“rb”、“rb+”等分别表⽰读取⼆进制⽂件和以读取/写⼊打开⼆进制⽂件。如果由于⽂件不存在等原因造成不能打开⽂件,则调⽤fopen()后返回⼀个空指针NULL。
⽂件的关闭
当C语⾔⽂件使⽤完后,应该⽴即关闭⽂件,防⽌由于误操作等原因破坏已经打开的⽂件。⽂件的关闭通过fclose()⽅法实现。其具体⽤法是:
fclose(⽂件指针);
⽂件的读写操作
⽂件打开后,最常见的操作就是读取和写⼊。C语⾔提供多种对⽂件的读取和写⼊的⽅法,这⾥主要介绍四种常⽤的⽅法:1.按字符读写的函数fgetc()、fputc()
函数fputc()的作⽤是向⽂件中写⼊⼀个字符,其调⽤形式是:
fputc(字符, ⽂件指针);
如fputc('A', fp);是将字符常量A写⼊⽂件的当前位置,并且使⽂件位置指针下移⼀个字符。如果写⼊成功返回该字符,否则返回EOF。
函数fgetc()的作⽤是从⼀个⽂件中读取⼀个字符,其调⽤形式是:
fgetc(⽂件指针);
如fgetc(fp);该函数不仅返回⽂件当前位置的字符,并且使⽂件位置指针下移⼀个字符。如果遇到⽂件结束则返回EOF。
把1.txt中的⽂本写⼊到2.txt中的例⼦:
// fopen函数不安全,要加上该语句,且该语句要放到最前⾯
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void main() {
FILE *fp = fopen("D:\\1.txt", "r");
FILE *fp1 = fopen("D:\\2.txt", "a");
if (fp == NULL) {
printf("打开⽂件失败\n");
exit(1);
} else {
printf("打开⽂件成功!\n");
char c;
c = fgetc(fp);
while(EOF != c) {
char a = fputc(c, fp1);
if (EOF == a) {
/
/printf("写⼊失败!\n");
} else {
//printf("写⼊成功!%c\n", a);
}
c = fgetc(fp);
}
}
fclose(fp);
fclose(fp1);
system("pause");
}
⼀般exit(0)表⽰程序正常退出,exit(⾮0值)表⽰程序出错后退出。
2.按字符串读写的函数fgets()、fputs()
函数fputs()的作⽤是向⽂件中写⼊⼀个字符串,其调⽤形式是:
fputs(字符串, ⽂件指针);
其中字符串可以是字符串常量、执⾏字符串的指针变量、存放字符串数组的数组名。写⼊成功返回0,否则EOF。
注意:字符串的结束标志'\0'不写⼊。
函数fgets()的作⽤是从⼀个⽂件中读取⼀个字符串,其调⽤形式是:
fgets(字符数组, 字符数, ⽂件指针);
如fgets(str, n, fp);其作⽤是从fp指向⽂件的当前位置开始读取n-1个字符,并加上字符串结束标志'\0'⼀起放⼊字符数组str中。如果从⽂件读取字符时遇到换⾏符或⽂件结束标志EOF,则本次读取结束。函数返回字符数组str的⾸地址。
把1.txt中的⽂本写⼊到2.txt中的例⼦:
void main() {
FILE *fp_in = fopen("D:\\1.txt", "r");
fgets和fgetc的区别FILE *fp_out = fopen("D:\\2.txt", "w");
char str[200];
while (!feof(fp_in)) {
fgets(str, 200, fp_in);
fputs(str, fp_out);
}
fclose(fp_in);
fclose(fp_out);
system("pause");
}
3.按格式要求读写的函数fprintf()、fscanf()
函数fprintf()的作⽤与printf()相似,只是输出对象不是标准输出设备(显⽰器)⽽是⽂件,即按照格式要求将数据写⼊⽂件,其调⽤形式是:
fprintf(⽂件指针, 格式控制, 输出列表);
如fprintf(fp, "%d,%s", num, name);它的作⽤是将变量num、name按照%d、%s的格式写⼊fp指向的⽂件的当前位置。
函数fscanf()按照格式要求从⽂件中读取数据。
如fscanf(fp, "%d,%s", &num, name);它的作⽤是从fp指向的⽂件的当前位置开始,按照%d、%s的格式取出数据赋给变量num、name。
主要⽤于数据⽂件的读写,既可以使⽤ASCII⽂件也可以使⽤⼆进制⽂件。
把1.txt(内容是:zyf 25)中的⽂本写⼊到2.txt中的例⼦:
void main() {
FILE *fp_in = fopen("D:\\1.txt", "r");
FILE *fp_out = fopen("D:\\2.txt", "w");
int num;
char name[20];
// 读⼊时,字符串字段跟其后⾯的字段必须⽤空格隔开,否则后⾯跟什么都认为是字符串的⼀部分
fscanf(fp_in, "%s %d", name, &num);
// fscanf(fp_in, "%s,%d", name, &num); // 这样写的话会把“,”当成字符串的⼀部分⽽造成后续字段解析错误
printf("%s,%d\n", name, num);
fprintf(fp_out, "%s, %d", name, num);
fclose(fp_in);
fclose(fp_out);
system("pause");
}
4.按数据块读写的函数fread()、fwrite()
函数fwrite()的作⽤是将成批的数据块写⼊⽂件,其调⽤形式是:
fwrite(写⼊⽂件的数据块的存放地址, ⼀个数据块的字节数, 数据块的个数, ⽂件指针);
如果函数操作成功则返回写⼊⽂件的数据块的个数。
如fwrite(&stu[1], sizeof(struct student), 2, fp);从结构体数组元素stu[1]存放的地址开始,以⼀个结构体struct
student类型变量所占字节数为⼀个数据块,共写⼊⽂件类型指针fp指向的⽂件2个数据块,即stu[1]、stu[2]的内容写⼊⽂件,操作成功则返回2.
函数fread()的作⽤是从⽂件中读出成批的数据块,其调⽤形式是:
fread(从⽂件读取的数据块的存放地址, ⼀个数据块的字节数, 数据块的个数, ⽂件指针);
如果操作成功则返回读出数据块的个数。
如fread(&stu, sizeof(struct student), 1, fp);从⽂件类型指针fp指向的⽂件的当前位置开始,读取⼀个数据块,该数据块为结构体struct student类型变量所占字节数,然后将读取的内容放⼊变量stu中。
注意fwrite()和fread()函数读写⽂件时,只有使⽤⼆进制⽅式才可以读写任何类型的数据。最常⽤于读写数组和结构体数据类型。
先写⼊⽂件再从⽂件中读取的例⼦:
struct Student
{
char name[20];
int age;
};
void main() {
struct Student stu[3] = { {"zhangsan", 22}, {"lisi",24}, {"wangwu",21} };
FILE *fp_out = fopen("D:\\hehe", "wb+");
fwrite(stu, sizeof(struct Student), 3, fp_out);
fclose(fp_out);
fp_out = fopen("D:\\hehe", "rb+");
struct Student stu1[3];
fread(stu1, sizeof(struct Student), 3, fp_out);
for (int i = 0; i < 3; i++) {
printf("%s,%d\n", stu1[i].name, stu1[i].age);
}
fclose(fp_out);
system("pause");
}
读⽂件时最好⽤r⽽不⽤w+,w+是打开可读写⽂件,若⽂件存在则将⽂件长度清零,即该⽂件的内容会消失。
⼀般⽤于⼆进制⽂件的输⼊/输出。
⽂件的其它常⽤函数
feof()
函数feof()⽤来检测⼀个指向⽂件的指针是否已经指到了⽂件最后的结束标志EOF。
如feof(fp);如果fp指向的⽂件的当前位置是EOF,则函数返回⼀个⾮0值,否则返回0.
rewind()
函数rewind()将令指向⽂件的指针重新指向⽂件的开始位置。⽆返回值。如rewind(fp);
fseek()
函数fseek()可以将指向⽂件的指针指向⽂件的任何⼀个位置以实现随机读写⽂件。其调⽤形式是:
fseek(⽂件型指针变量, 偏移量, 起始位置);
函数fseek()将以⽂件的起始位置为基准,根据偏移量往前或往后移动指针。其中偏移量是⼀个长整型数,表⽰从起始位置移动的字节数,正数表⽰指针往后移、负数表⽰指针往前移,起始位置⽤数字0/1/2或者SEEK_SET、SEEK_CUR、SEEK_END代表⽂件开始、⽂件当前位置和⽂件结束位置。如果指针设置成功返回0,否则为⾮0.
ftell()
函数ftell()⽤于返回指向⽂件的指针的当前位置,执⾏成功时返回当前⽂件指针的值,否则返回-1L,⽤其可进⾏防错处理。如ftell(fp);
宏定义的规则
宏定义⼀般写在函数之外,其作⽤域为宏定义命令起到源程序结束。如要终⽌其作⽤域可使⽤#undef命令:
#include<stdio.h>
#define PI 3.14
float hehe(int);
void main() {
printf("%f\n", 2 * PI * 6);
// printf("%f\n", hehe(6));
system("pause");
}
#undef PI
float hehe(int r) {
// 由于上⾯终⽌了PI的作⽤域,故这⾥⽆效,会提⽰未定义标识符
// return 2 * PI * r;
}
带参数的宏定义
实参可以是任意表达式,且其数据类型不限
#include<stdio.h>
#define A(x) x*x
void main() {
printf("%d\n", A(3));
printf("%f\n", A(3.0));
system("pause");
}
输出结果:
9
9.000000
条件编译
通过某些条件控制源程序中的某段代码是否需要编译,这就是条件编译的功能。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论