EOF \n \0 NULL 之间的区别

\n 是换行符

\0 是字符串的结束标志

EOF是流的结束标志 FILE* 这种流

NULL 是指针为空

第一个问题是EOF

 它是end of file的缩写,表示"文字流"(stream)的结尾。这里的"文字流",可以是文件(file),也可以是标准输入(stdin)。


比如,下面这段代码就表示,如果不是文件结尾,就把文件的内容复制到屏幕上。

  int c;

  while ((c = fgetc(fp)) != EOF) {

    putchar (c);

  }

很自然地,我就以为,每个文件的结尾处,有一个叫做EOF的特殊字符,读取到这个字符,操作系统就认为文件结束了。

但是,后来我发现,EOF不是特殊字符,而是一个定义在头文件stdio.h的常量,一般等于-1。

  #define EOF (-1)

于是,我就困惑了。

如果EOF是一个特殊字符,那么假定每个文本文件的结尾都有一个EOF(也就是-1),还是可以做到的,因为文本对应的ASCII码都是正值,不可能有负值。但是,二进制文件怎么办呢?怎么处理文件内部包含的-1呢?

这个问题让我想了很久,后来查了资料才知道,在Linux系统之中,EOF根本不是一个字符,而是当系统读取到文件结尾,所返回的一个信号值(也就是-1)。至于系统怎么知道文件的结尾,资料上说是通过比较文件的长度。

所以,处理文件可以写成下面这样:

  int c;

  while ((c = fgetc(fp)) != EOF) {

    do something

  }

这样写有一个问题。fgetc()不仅是遇到文件结尾时返回EOF,而且当发生错误时,也会返回EOF。因此,C语言又提供了feof()函数,用来保证确实是到了文件结尾。上面的代码feof()版本的写法就是:

  int c;

  while (!feof(fp)) {

    c = fgetc(fp);

    do something;

  }

但是,这样写也有问题。fgetc()读取文件的最后一个字符以后,C语言的feof()函数依然返回0,表明没有到达文件结尾;只有当fgetc()向后再读取一个字符(即越过最后一个字符),feof()才会返回一个非零值,表示到达文件结尾。

所以,按照上面这样写法,如果一个文件含有n个字符,那么while循环的内部操作会运行n+1次。所以,最保险的写法是像下面这样:

  int c = fgetc(fp);

  while (c != EOF) {

    do something;

    c = fgetc(fp);

  }

  if (feof(fp)) {

    printf("\n End of file reached.");

  } else {

    printf("\n Something went wrong.");

  }

除了表示文件结尾,EOF还可以表示标准输入的结尾。

  int c;

  while ((c = getchar()) != EOF) {

    putchar(c);

  }

解决重复出现两次的办法就是不用feof,而是使用fgetc().

但是,标准输入与文件不一样,无法事先知道输入的长度,必须手动输入一个字符,表示到达EOF。

Linux中,在新的一行的开头,按下Ctrl-D,就代表EOF(如果在一行的中间按下Ctrl-D,则表示输出"标准输入"的缓存区,所以这时必须按两次Ctrl-D);Windows中,Ctrl-Z表示EOF。(顺便提一句,Linux中按下Ctrl-Z,表示将该进程中断,在后台挂起,用fg命令可以重新切回到前台;按下Ctrl-C表示终止该进程。)

那么,如果真的想输入Ctrl-D怎么办?这时必须先按下Ctrl-V,然后就可以输入Ctrl-D,系统就不会认为这是EOF信号。Ctrl-V表示按"字面含义"解读下一个输入,要是想按"字面含义"输入Ctrl-V,连续输入两次就行了。



getchar()-----读取输入的字符(%c)

它能读取任何 字符(只要是在ACSII上的)如回车(ACSII码值:10)、换行(13)、null(\0)都可以,所以我要做的是判断,而和gets(直至接受到换行符或EOF,换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串)和scanf(tab,空格,换行,回车都作为结束符)都不同,

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面的代码实现了在已有内容的之间插入新的内容,具体修改和注释见代码: ``` // 插入函数 void insert_file(FILE *fp, char *fname) { char ch; long int pos; int len = 0; // 获取用户输入的文件名 printf("\t请输入插入的文件名:\n\t"); // 从标准输入中获取文件名 fgets(fname, MAX_LEN, stdin); // 查找'\n'字符并替换为'\0' char *pos1 = NULL; if ((pos1 = strchr(fname, '\n')) != NULL) *pos1 = '\0'; // 添加后缀名".txt",如果没有输入 if (!strstr(fname, ".txt")) strcat(fname, ".txt"); // 打开文件并判断是否打开成功 if ((fp = fopen(fname, "r+")) == NULL) { // 打开文件方式改为"r+",即可读可写 printf("\t不能打开文件!\n"); exit(0); } // 获取文件长度 fseek(fp, 0, SEEK_END); len = ftell(fp); // 显示文件已有内容 printf("\t文件已有内容:\n"); rewind(fp); while ((ch = fgetc(fp)) != EOF) { putchar(ch); } // 获取用户输入的插入位置 printf("\n\t请输入插入的位置(从0开始):\n\t"); scanf("%ld", &pos); getchar(); // 读取换行符 // 将文件指针移动到指定位置 fseek(fp, pos, SEEK_SET); // 依次将后面的字符往后移动1个字符 for (int i = len; i >= pos+1; i--) { fseek(fp, i-1, SEEK_SET); ch = fgetc(fp); fseek(fp, i, SEEK_SET); fputc(ch, fp); } // 获取用户输入的插入内容并写入到文件中 printf("\t请输入要插入的内容:\n\t"); ch = getchar(); while (ch != '#') { fputc(ch, fp); ch = getchar(); } // 关闭文件 fclose(fp); printf("\n\t插入成功!\n"); } ``` 注:修改后的代码中,先获取了文件长度len,然后从后往前依次将字符往后移动1个字符,最后将新的内容写入到文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值