您的位置:首页 > 其它

要点3:输入函数对比与自定义输入方式

haotielili 2020-08-18 00:16 120 查看 https://www.cnblogs.com/lxmwb/

读取输入的方式

相关函数原型(从控制台获取输入,不考虑宽字符):

int scanf( const char *format, ... );
int getchar(void);
char *gets( char *str );
char *gets_s( char *str, rsize_t n );
char *fgets( char *str, int count, FILE *stream );
  • scanf 如果解析错误,内容继续留在缓冲区供下次使用;
  • 解析失败返回0,成功返回解析的参数个数,不会超过占位符个数,读到文件尾返回EOF(-1);
  • 读取字符串,一次只能读取一个词,不能用scanf读取一行;
  • getchar
      可以读取到换行符;
    • 常用于暂停程序,或丢弃缓冲区剩余字符;
  • gets
      读取一行,遇到换行符,直接丢弃换行符;
    • 会自动在字符串末尾添加
      \0
    • 返回字符串指针,读取失败返回null;
  • gets_s
      可以设置读取的字符串长度;
    • 读到换行符,将换行符丢弃;
    • 如果读取到最大字符数,还没有读取到换行符或文件结尾,读取并丢弃随后的输入直至遇到换行符或EOF;
    • 返回字符串指针,读取失败返回null;
    • c11的可选函数
  • fgets
      可以设置读取的字符串长度;
    • 读到换行符不丢弃存到数组里;
    • 不会自动清除行缓冲区剩余数据;
    • 返回字符串指针,读取失败返回null;

    scanf

    该函数可以从标准输入读取内容,返回值为读取的参数个数,例如:

    #include <stdio.h>
    
    int main()
    {
    int seed;
    printf("%d\n", scanf("%d %d", &seed, &seed));
    }

    运行程序,输入 两个整数,打印为 2,测试输入3个值仍然打印2,是因为这个"%d %d"指定了只解析两个int,多余的将留在缓冲区中,如果后面再写一个scanf,将从缓冲区中继续解析。

    现在多加一个

    scanf

    #include <stdio.h>
    
    int main()
    {
    int seed;
    printf("%d\n", scanf("%d %d", &seed, &seed));
    printf("%d\n", scanf("%d %d", &seed, &seed));
    }

    case1:读取到文件尾部返回EOF

    1

    输出:

    1-1

    scanf从缓冲区中解析,返回解析成功的参数个数,因为只有一个1,所以第一个给scanf解析,第一行打印1,第二行解析的时候因读取到了文件结束表示

    EOF
    返回-1。

    case2:解析失败返回0

    f

    输出:

    0
    0

    这说明,解析失败的内容还留在缓冲区给下次scanf用,所以两个scanf都返回的0。

    因为无法解析的值会继续留在缓冲区供下次使用,所以如果是循环

    scanf
    ,程序就会跑飞,让你没有输入的机会,可以使用综上一节提供的示例测试一下,运行后直接输入
    f

    case3:返回值最大为占位符个数

    1 2 3 4 5 6 7

    输出:

    2
    2

    这表明,返回值最大是占位符的个数,剩下的内容还留在缓冲区。

    综上

    scanf
    判断输入结束,只能在文件输入模式下利用
    EOF
    判断,例如:

    // qwer.c
    #include <stdio.h>
    
    int main()
    {
    int a;
    while(scanf("%d", &a) != EOF)
    {
    printf("%d\n", a);
    }
    return 0;
    }

    输入文件

    test.txt
    内容:

    12
    3
    4
    

    编译:

    gcc qwer.c -o main -std=c11

    运行:
    ./main < test.txt

    getchar

    这个函数可以从输入缓冲区仅读取一个字符,返回int,后面结合

    fgets
    使用。

    gets

    在读取字符串时,

    scanf()
    和转换说明
    %s
    只能读取一个单词,可是程序中经常要读取一整行输入。
    gets
    函数简单易用,它读取整行输入,直到遇到换行符,然后丢弃换行符,存储其余字符,并在这些字符的末尾添加一个空字符使其成为一个c字符串。它经常和
    puts
    函数配对使用,该函数用于显示字符串,并在末尾添加换行符。

    #include <stdio.h>
    #define STLEN 81int main()
    {
    char words[STLEN];
    puts("Enter a string, please.");
    gets(words);   // 典型用法
    printf("Your string twice:\n");
    printf("%s\n", words);
    puts(words);
    puts("Done.");
    return 0;
    }
    

    printf("%s\n", words);
    puts(words);
    效果相同,但是编译的时候会产生警告,因为
    gets
    读取整行输入,并不知道
    words
    能存多少,如果输入字符串过长,会导致缓冲区溢出。

    例如将

    STLEN
    设置成
    5
    ,程序依然可以运行,尝试输入过长的数据就可能会发成溢出,最直观的就是可以看到发生段溢出后程序异常退出。

    gets_s

    该函数是c11才有的,且为拓展函数,使用方式除了可以设置读取的字符数之外和

    gets
    函数用法一样。

    fgets

    这个函数除了可以从标准输入读取字符串之外,还可以从文件中读取,而且可以指定读取字符个数,比

    gets_s
    更加灵活易用,利用
    fgets
    ,但是
    fgets
    不会自动丢弃超过字符个数之外的行缓冲区数据,所以要配合
    getchar
    将剩余的缓冲数据丢弃,否则可能造成程序运行以异常。

    s_gets【自定义输入】

    为满足以下几点编写自定义输入:

    • 从标准输入读取数据;
    • 能够指定读取字符个数;
    • 丢弃换行符;
    • 丢弃行缓冲区剩余数据;
    char *s_gets(char *str, int n)
    {
    char *ret_var;
    int i = 0;
    ret_var = fgets(str, n, stdin);
    if(ret_var)
    {
    while(str[i] != '\n' && str[i] != '\0')
    {
    i++;
    }
    if(str[i] == '\n')
    str[i] = '\0';
    else
    while(getchar() != '\n')
    continue;
    }
    return ret_var;
    }

    使用方式

    #include <stdio.h>
    #define STLEN 8
    
    int main()
    {
    char words[STLEN];
    while(s_gets(words, STLEN) && words[0] != '\n') // 没有输入数据会自动退出程序
    {
    puts(words);
    }
    return 0;
    }
  • 标签: 
    相关文章推荐