zoukankan      html  css  js  c++  java
  • fgets(),fscanf()的输入测试与FILE中的当前指针

    fgets(string,int,fp)

    回车读入测试

     1 #include <stdio.h>
     2 int main()
     3 {
     4     FILE *fp;
     5     char ch1[12],ch2[12],ch3[12],ch4[13];
     6     fp=fopen("case1.in","r");
     7     fgets(ch1,10,fp);
     8     fseek(fp,0,0);
     9     fgets(ch2,11,fp);
    10     fseek(fp,0,0);
    11     fgets(ch3,12,fp);
    12     fseek(fp,0,0);
    13     fgets(ch4,13,fp);
    14     fseek(fp,0,0);
    15     printf("10:%s;
    ",ch1);
    16     printf("11:%s;
    ",ch2);
    17     printf("12:%s;
    ",ch3);
    18     printf("13:%s;
    ",ch4);
    19     fclose(fp);
    20     return 0;
    21 }

    case1.in内容:

    ottffssent
    abcdefghij
    kl

    运行结果:

    10:ottffssen;
    11:ottffssent;
    12:ottffssent
    ;
    13:ottffssent
    ;

    结论:

    字符串要留空位给'',如果有回车的话要再预留空位给回车'13',即字符数量为10的字符串则用fgets时要取n=12

    如果fgets中n的数量过少而读不入回车,会导致输出时没有换行

    如果fgets中n的数量过多,那么回车已经停止了读入字符了,即回车符后紧跟''

    空格读入测试

    代码同上

    case1.in有修改:

    ottff sent
    abcde ghij
    kl

    运行结果:

    10:ottff sen;
    11:ottff sent;
    12:ottff sent
    ;
    13:ottff sent
    ;

    结论:

    空格被视为普通字符处理,不能中止字符的读入.而回车可以


    代码增加一点

    1     fscanf(fp,"%s",ch5);
    2     fscanf(fp,"%s",ch6);
    3     fscanf(fp,"%s",ch7);
    4     fscanf(fp,"%s",ch8);
    5     printf("fscanf1:%s;
    ",ch5);
    6     printf("fscanf2:%s;
    ",ch6);
    7     printf("fscanf3:%s;
    ",ch7);
    8     printf("fscanf4:%s;
    ",ch8);

    case1.in有修改:

    ottff sent
    abcde,ghij
    kl

    运行结果:

    fscanf1:ottff;
    fscanf2:sent;
    fscanf3:abcde;
    fscanf4:ghij;

    结论:fscanf中,空格,回车,标点符号都可以中止输入


    FILE指针中的当前位置

    //--------------------------------------------------------------------------------------------

    FILE 是 I/O 系统用的。不同编译器结构不完全相同。
    char* _ptr; 文件指针当前位置,缓冲区内 马上读和写的位置。
    int _cnt; 缓冲区内 现有可以读的字符个数
    char* _base; 缓冲区
    int _flag; 文件流 特征标志,例如:只读,只写,读写,错误,文件结束,2进制文件。
    int _file; 系统里文件属性,例如:谁可以读写(用户自己,用户组,管理员)。
    int _charbuf; -- 供 ungetc() 使用的缓冲存储单元。
    int _bufsiz; 已分配的缓冲区的大小。
    char* _tmpfname; 临时文件名

    //--------------------------------------------------------------------------------------------
    typedef struct{
    short level; 缓冲区使用量
    unsigned flags; 文件状态标志
    char fd; 文件描述符
    short bsize; 缓冲区大小
    unsigned char *buffer; 文件缓冲区首地址
    unsigned char *curp; 指向文件缓冲区的工作指针
    unsigned char hold; 其他信息
    unsigned istemp;
    short token;
    }FILE;

    //--------------------------------------------------------------------------------------------
    struct __sFILE64 {
    # if !defined _AEABI_PORTABILITY_LEVEL || _AEABI_PORTABILITY_LEVEL == 0
    unsigned char *_p; /* current position in (some) buffer */
    int _r; /* read space left for getc() */
    int _w; /* write space left for putc() */
    short _flags; /* flags, below; this FILE is free if 0 */
    short _file; /* fileno, if Unix descriptor, else -1 */
    struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
    int _lbfsize; /* 0 or -_bf._size, for inline putc */

    struct _reent *_data;

    /* operations */
    _PTR _cookie; /* cookie passed to io functions */

    _READ_WRITE_RETURN_TYPE _EXFUN((*_read),(struct _reent *, _PTR,
    char *, int));
    _READ_WRITE_RETURN_TYPE _EXFUN((*_write),(struct _reent *, _PTR,
    const char *, int));
    _fpos_t _EXFUN((*_seek),(struct _reent *, _PTR, _fpos_t, int));
    int _EXFUN((*_close),(struct _reent *, _PTR));

    /* separate buffer for long sequences of ungetc() */
    struct __sbuf _ub; /* ungetc buffer */
    unsigned char *_up; /* saved _p when _p is doing ungetc data */
    int _ur; /* saved _r when _r is counting ungetc data */

    /* tricks to meet minimum requirements even when malloc() fails */
    unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
    unsigned char _nbuf[1]; /* guarantee a getc() buffer */

    /* separate buffer for fgetline() when line crosses buffer boundary */
    struct __sbuf _lb; /* buffer for fgetline() */

    /* Unix stdio files get aligned to block boundaries on fseek() */
    int _blksize; /* stat.st_blksize (may be != _bf._size) */
    int _flags2; /* for future use */

    _off64_t _offset; /* current lseek offset */
    _fpos64_t _EXFUN((*_seek64),(struct _reent *, _PTR, _fpos64_t, int));

    # ifndef __SINGLE_THREAD__
    _flock_t _lock; /* for thread-safety locking */
    # endif
    # endif /* _AEABI_PORTABILITY_LEVEL */
    _mbstate_t _mbstate; /* for wide char stdio functions. */
    };

    //--------------------------------------------------------------------------------------------

    不同的编译器有不同的stdio.h,也对应着定义的不同

    codeblocks使用第一种定义,当前指针为fp->_ptr

    学校教材上使用第二种,当前指针为fp->curp

    学校oj系统用第三种定义,编译器G++,当前指针为fp->_p

    然而cb上和学校oj系统上的当前指针有点不同

    执行ch=fgetc(fp)是ch读入fp->_ptr指向的内容,然后指针自动前进一位

    即case1.in中有:abcd

    第一步执行ch=fgetc(fp)后,ch='a',而fp->_ptr已经指向b了,*(fp->_ptr)=b

    但在学校oj系统上,ch=fgetc(fp)是指针前进一位,然后读入内容到ch

    即case1.in中:abcd,执行ch=fgetc(fp)后,ch='a',此时fp->_p还是在a上,再执行ch=fgetc(fp),fp->_p移动到b,ch=b

    这时*(fp->_p)=b,*(fp->_p+1)=c,

    换做cb上这样执行两次ch=fgetc(fp)后,*(fp->_ptr)=c了

    按照教材上的说法,教材的指针原理和cb上的相同..

    妈蛋..学校那题错了6次才猜出来是这个原因,测试后pase.

  • 相关阅读:
    近期前端中的 一些常见的面试题
    一道前端学习题
    前端程序员容易忽视的一些基础知识
    web前端工程师入门须知
    Web前端知识体系精简
    面试分享:一年经验初探阿里巴巴前端社招
    抽象类、抽象函数/抽象方法详解
    C#语法-虚方法详解 Virtual 虚函数
    面向对象语言:继承关系教程
    C#动态创建Xml-LinQ方式
  • 原文地址:https://www.cnblogs.com/someblue/p/3373692.html
Copyright © 2011-2022 走看看