读一行字符串。
第一个参数是,读到的字符串,将会被放到str指向的这个位置,第二个参数是都几个字符,第三个是读取的位置流。
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE* p = fopen("test.txt", "r"); if (p == NULL) { printf("%s", strerror(errno)); return 1; } /*fputc('a', p);*/ /*int e = 0; if ((e = fgetc(p)) != EOF) { printf("%c", e); }*/ /*fputs("qweqwe", p);*/ char arr[10] = { 0 }; fgets(arr, 4, p); printf("%s", arr); fclose(p); p = NULL; }
这里我们发现只有三个字符,这是因为第四个的位置上会放一个’\0‘,所以才打印出来三个。
格式化就代表可以输入结构体这种类型的信息了。
这个函数对比printf函数多了一个参数,是写入流的位置。
这里额外介绍一个函数:
这个也是报错的函数,参数是字符串,一般都是用来写是哪个地方出错了。
如果在里面输入fopen,那么这个函数一旦报错就会在屏幕上的打印出:
fopen:No such file or directory//多了原因和一个:号
这个函数还是很方便的。
#include <stdio.h> #include <stdlib.h> #include <string.h> struct person { char name[20]; int age; float weight; }; int main() { struct person s = { "baiye",25,75.0f }; FILE* p = fopen("test.txt", "w"); if (p == NULL) { perror("fopen"); return 1; } fprintf(p, "%s %d %f", s.name, s.age, s.weight); fclose(p); p = NULL; return 0; }
这个能展示格式化信息。
也和scanf函数差不多,多出来的参数是第一个,也是流的位置。
#include <stdio.h> #include <stdlib.h> #include <string.h> struct person { char name[20]; int age; float weight; }; int main() { struct person s = { 0 };//我们并没有初始化任何值 FILE* p = fopen("test.txt", "r"); if (p == NULL) { perror("fopen"); return 1; } //fprintf(p, "%s %d %f", s.name, s.age, s.weight); fscanf(p, "%s %d %f", s.name, &(s.age), &(s.weight)); printf("%s %d %f", s.name, s.age, s.weight); fclose(p); p = NULL; return 0; }
我们从文件中读到了之前存入的信息。
流是这个,如果让外部设备和内存之间有联系,那么就需要各种类型的操作,每种不同的硬件都是不一样的,所以就有了流,我们只需要将信息放到流里面就可以读或写到各种外部设备上了。
在任何一个C语言的程序中,只要运行起来就会默认打开三个流:
FILEstdin - 标准输入流(键盘)
FILEstdout - 便准输出流(屏幕)FILE*stderr - 标准错误流(屏幕)
二进制方式写。
第一个参数是你要写的数据的地址,第二个参数是数据大小,第三个参数是一次写几个,第四个是流。
#include <stdio.h> #include <stdlib.h> #include <string.h> struct person { char name[20]; int age; float weight; }; int main() { struct person s = { "baiye",25,75.00 }; FILE* p = fopen("test.txt", "wb"); if (p == NULL) { perror("fopen"); return 1; } fwrite(&s, sizeof(struct person), 1, p); fclose(p); p = NULL; return 0; }
因为是二进制写进去的,所以看不懂。
第一个参数是接收数据的位置,第二个是数据大小,第三个是个数,第四个是流。
返回参数是读取到的数据有多少个。
#include <stdio.h> #include <stdlib.h> #include <string.h> struct person { char name[20]; int age; float weight; }; int main() { struct person s = { 0 }; FILE* p = fopen("test.txt", "rb"); if (p == NULL) { perror("fopen"); return 1; } //fwrite(&s, sizeof(struct person), 1, p); fread(&s, sizeof(struct person), 1, p); printf("%s %d %f", s.name, s.age, s.weight); fclose(p); p = NULL; return 0; }
这个函数就能看得懂,还是要用魔法打败魔法。
4.1 对比一组函数:
scanf/fscanf/sscanf
printf/fprintf/sprintf
第一个参数是你要存放的位置,后面的就和printf函数的参数没区别了。
把一个格式化的数据转换成字符串。
#include <stdio.h> #include <stdlib.h> #include <string.h> struct person { char name[20]; int age; float weight; }; int main() { struct person s = { "baiye",25,75.00 }; char arr[100] = { 0 }; sprintf(arr, "%s %d %f", s.name, s.age, s.weight); printf("%s", arr);//原理是让结构体里面的数据变成了这样子"baiye 25 75.00" return 0; }
这个是把字符串获取格式化后放在第二个参数中。
第一次参数是你要读取字符串的位置,第二个参数是你要储存的位置。
#include <stdio.h> #include <stdlib.h> #include <string.h> struct person { char name[20]; int age; float weight; }; int main() { struct person s = { "baiye",25,75.00 }; struct person s1 = { 0 }; char arr[100] = { 0 }; sprintf(arr, "%s %d %f", s.name, s.age, s.weight); printf("字符串:%s\n", arr);//原理是让结构体里面的数据变成了这样子"baiye 25 75.00" sscanf(arr, "%s %d %f", s.name, &(s.age), &(s.weight)); printf("格式化:%s %d %f\n", s.name, s.age, s.weight); return 0; }