zoukankan      html  css  js  c++  java
  • EOF NULL 之间的区别

    是换行符

    是字符串的结束标志

    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(" End of file reached.");

      } else {

        printf(" 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-D,这句话存疑,应该是错的,不区分是中间输入的还是开头输入的,都是一样的,都代表eof

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

     

     

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

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

     
     
     
     
     
    ————————————————————————————————————————————————————————————————————————————
     
     
     
     
     
    EOF就是文件尾的意思,一般被编译器定义为-1  倒不是说文件自己会自动生成一个EOF标志,而是你在用函数读入文件数据的时候,函数总会返回一个状态,是读取成功还是失败,那么这个状态怎么表示呢,所以就约定俗成定义一个标识符表示这个状态,就有了EOF,BOF等等EOF不是文件中有的。只不过是一个文件操作函数,在文件结尾操作时候返回的错误码。不要认为文件中含有EOF。  换行和回车是在文件中都有的,分别是/n和/r在UNIX和DOS中的文本中有不同的表达。  EOF在UNIX中输入是ctrl+d,在win中是ctrl+z。也就是说,标准输入/输出在处理文本流时,若取不到字符,即返回错误码EOF,代表文件结束
     
     
     
     
     
    ———————————————————————————————————————————————————————————————————————————————
     
     
     
     
    头文件:#include <stdio.h>

    feof()函数用来检测当前文件流上的文件结束标识,判断是否读到了文件结尾,其原型为:
        int feof(FILE * stream);

    【参数】stream为文件流指针。

    【返回值】检测到文件结束标识返回1,否则返回0。

    文件结束标识一般由上次的读写操作来设置,当然也可以手动设置。

    当文件内部的位置指针指向文件结束时,并不会立即设置FILE结构中的文件结束标识,只有再执行一次读文件操作,才会设置结束标志,此后调用feof()才会返回为真。

    文件结束标识可以由 clearerr()rewind()fseek()fsetpos() 和 freopen() 函数清除;如果这时位置指针未被重置,那么将在下次 I/O 操作时进行设置。

    更多信心请参考:C语言FILE结构体

    注意,feof()与EOF不同:feof()是函数,用来检测文件的结束;EOF是 End Of File 的缩写,是C语言中标准库中定义的宏,定义为:#define  EOF  (-1)。

    EOF的值为-1,是 int 类型数据,在32位系统中,可以表示为0xFFFFFFFF;EOF 不是一个字符,也不是文件中实际存在的内容。EOF不但能表示读文件到了结尾这一状态,它还能表示 I/O 操作中的读、写错误(可以用 ferror() 来检测)以及其它一些关联操作的错误状态。

    fgetc() 或getc() 等函数返回EOF并不一定表示文件结束,当读取文件出错时也会返回EOF,仅凭返回 -1 就认为文件结束是错误的;正因为如此,我们需要feof()来判断文件是否结束,当然用feof()来判断文件结束时也需要判断读取操作是否出错,这时可以用ferror()来判断,当其为真时表示有错误发生。在实际的程序中,应该每执行一次文件操作,就用用ferror()函数检测是否出错。

    例如,有一个文件指针fp,文件中有字符串“hello world”:
    1. int c=0;
    2. while( !feof(fp) )
    3. {
    4. int c=fgetc(fp);
    5. printf("%c: %x ", c, c);
    6. }
    上面的代码除了输出 hello 外,还会输出一个结束字符EOF(EOF是fgetc函数的返回值,并不是文件中存在EOF)。其原因就是当内部位置指针指向结尾时,还要执行一次读操作,文件结束标识才会被设置。

    对上面代码进行更改:
    1. int c;
    2. c=fgetc(fp);
    3. while( !feof(fp) )
    4. {
    5. printf("%c: %x ", c, c);
    6. c=fgetc(fp);
    7. }
    上面的代码只输出“hello”不输出文件结束符EOF。当文件内部位置指针指向结束位置时,先执行一次读操作,设置文件结束标识,while循环立即结束。

    【实例】读取一个文件直到结束,然后回到开头重新读取。
    1. #include<iostream.h>
    2. #include<stdio.h>
    3. void main(void)
    4. {
    5. FILE* stream;
    6. long l;
    7. float fp;
    8. char s[81];
    9. char c;
    10. stream = fopen("fscanf.txt","w+");
    11. if(stream == NULL) /*打开文件失败*/
    12. {
    13. printf("the file is opeaned error! ");
    14. }
    15. else
    16. {
    17. fprintf(stream,"%s %ld %f %c","a_string",6500,3.1415,'x');
    18. fseek(stream,0L,SEEK_SET); /*定位读写指针*/
    19. fscanf(stream,"%s",s);
    20. printf("%ld ",ftell(stream));
    21. fscanf(stream,"%ld",&l);
    22. printf("%ld ",ftell(stream));
    23. fscanf(stream,"%f",&fp);
    24. printf("%ld ",ftell(stream));
    25. fscanf(stream," %c",&c);
    26. printf("%ld ",ftell(stream));
    27. fgetc(stream); /*使指针到结尾*/
    28. if(!ferror(stream))
    29. {
    30. if(feof(stream)) /*如果不是结束*/
    31. {
    32. printf("We have reached end-of-file ");
    33. rewind(stream);
    34. fscanf(stream,"%s",s);
    35. printf("%s ",s);
    36. }
    37. }
    38. fclose(stream);
    39. }
    40. }
    运行结果:
    8
    13
    22
    24
    We have reached end-of-file
    a_string

    程序先创建一个文件,写入4个类型的数据,然 后把读/写指针定位到文件开头逐个读取并输出当前指针的位置, 如果到了文件结尾则提示已经到达文件结尾,重新定位文件到开头并读取一个字符串。
     
  • 相关阅读:
    Fedora13下真正能用的源(2015-5-16亲测)
    Shellcoding教程:介绍ASM(译)
    Shellcoding教程:介绍ASM
    ubuntu解决pppoeconf和network-manager冲突时,可能问题的解决方法
    vue_router-link传参
    js_window.postMessage往不同窗口里面发送数据
    iframe_iframe引入其它页面
    css_去掉默认样式
    vue_常用组件install
    js_正则表达式
  • 原文地址:https://www.cnblogs.com/saolv/p/7628101.html
Copyright © 2011-2022 走看看