三、文件的顺序读写:
1.字符的读与写 fgetc 与 fputc:
字符的读取函数 fputc :
描述 :把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动;
参数 int char :这是要被写入的字符。该字符以其ASCII 值进行传递;
参数 FILE *stream : 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流;
返回值:该函数以无符号 char 强制转换为 int 的形式(即字符的ASCII值)返回写入的字符,如果发生错误则返回 EOF.
int main() { FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { perror("fopen"); return 1; } //写文件 /*fputc('a', pf); fputc('b', pf); fputc('c', pf); fputc('d', pf);*/ char ch = 0; for (ch = 'a'; ch <= 'z'; ch++) { fputc(ch, pf); } //关闭文件 fclose(pf); pf = NULL; return 0; }
运行结果:
这就是字符的写入,大家会在该项目找到这个文件。
字符的读取函数 fgetc :
参数 FILE *stream :这是指向 FILE 对象的指针,该 FILE 对象标识了要在上面执行操作的流;
返回值:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。
我们在上面代码的基础下展示文件的读取。
int main() { FILE* pf = fopen("test.txt", "r"); if (NULL == pf) { perror("fopen"); return 1; } //读文件 int ch = fgetc(pf); printf("%c\n", ch); ch = fgetc(pf); printf("%c\n", ch); ch = fgetc(pf); printf("%c\n", ch); //关闭文件 fclose(pf); pf = NULL; return 0; }
运行结果:
注意:
getc函数对于字符的读取,每读取一个字符,该函数内的指针会自动将指向的位置向后移动,指向下一个字符;
组合应用:
int main() { FILE* pf = fopen("test.txt", "w"); //以只写的方式打开文件 if (pf == NULL) { perror("fopen"); return 0; } char ch = 0; for (ch = 'a'; ch <= 'z'; ch++) //向文件写入26个小写英文字母 { fputc(ch, pf); } fclose(pf); pf = NULL; pf= fopen("test.txt", "r"); //以只读的方式打开文件 if (pf== NULL) { perror("fopen"); return 0; } while (ch != EOF) //判断是否读取到文件末尾 { ch = fgetc(pf); //从文件中读取字符 printf("%c", ch); //打印读取字符 } fclose(pf); pf = NULL; return 0; }
代码结果:
2.文本行的读与写 fgets 与 fputs
fputs读取字符串:
参数 const char *str : 这是一个字符串,有’\0’结尾。
参数 FILE *stream : 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流;
返回值:该函数返回一个非负值,如果发生错误则返回 EOF。
int main() { FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { perror("fopen"); return 1; } //写文件 //测试写一行数据 fputs("hello world\n", pf); fputs("hello bit\n", pf); return 0; }
运行结果:
fgets读取字符串:
描述: 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。
参数 char *str :这是指向一个指针,该指针指向了要读取的字符串;
参数 int n : 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度;
参数 FILE *stream :这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流;
返回值:如果成功,该函数返回相同的 str 参数;如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针;如果发生错误,返回一个空指针;
特殊情况:
当读取 (n-1) 个字符时,会自动在第n个位置补’\0’
读取到换行符时,会把’\n’之前的字符读取出来然后补’\0’,但是不会读到’\n’,具体情况在后面的缓冲区部分知识里会提到。此时的’\n’会在保存在下一个fgets函数的第一个字符
到达文件末尾时,它会停止,具体视情况而定.
int main() { FILE* pf = fopen("test.txt", "r"); if (NULL == pf) { perror("fopen"); return 1; } //读文件 //测试一行数据 char buf[20] = {0}; fgets(buf, 20, pf); printf("%s", buf); fgets(buf, 20, pf); printf("%s", buf); //关闭文件 fclose(pf); pf = NULL; return 0; }
代码结果:
3.格式化输出函数 fscanf和fprintf:
fprintf的格式化写入:
其实该函数和printf函数一模一样,只是前面多了一个指向文件的指针! 这里的意思其实是将后面的数据以不同的格式写入指针指向的文件信息中。
struct S { char name[20]; int age; float score; }; int main() { struct S s = { "zhangsan", 20, 95.5 }; FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { perror("fopen"); return 1; } //格式化的写入文件 fprintf(pf, "%s %d %f\n", s.name, s.age, s.score); //关闭文件 fclose(pf); pf = NULL; return 0; }
运行结果:
fscanf的格式化读取:
一样的,都是多了一个文件指针而已,其他都是一模一样的!这里的意思是将文件指向的文件消息以不同格式读出并且保存在不同类型的变量中。
int main() { struct S s = { 0 }; FILE* pf = fopen("test.txt", "r"); if (NULL == pf) { perror("fopen"); return 1; } //格式化的读取文件 fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score)); //打印看数据 printf("%s %d %f\n", s.name, s.age, s.score); //关闭文件 fclose(pf); pf = NULL; return 0; }
运行结果: