【问题标题】:Read for inputs individually in C在 C 中单独读取输入
【发布时间】:2018-01-27 21:03:38
【问题描述】:

我想单独读取输入。这意味着我输入一个字符,按回车键,然后要求输入第二个字符。问题是当程序要求我输入它同时要求输入的字符时。

这是我的代码:

#include <stdio.h>

int main(){
    printf("Enter a character \n");

    char a = 0;
    a = getchar();

    printf("You entered: %c \n",a);

    putchar(a);

    printf("\n");

    char b[2];
    puts(b);
    gets(b);

    printf("You entered: %c \n",b[0]);

    puts(b);
}

【问题讨论】:

  • 不要使用gets,这是等待发生的意外。请改用fgets
  • 关注Why gets() is so dangerous it should never be used! 上的完整故事的链接 将其与char b[2]; 一起使用实在是太鲁莽了。
  • 1.计算机完全按照您的指示行事。不多也不少。如果您想一次获取一个字符,则必须使用正确的代码来执行此操作。 2. getchar() 只读取一个字符。当用户键入一个字符然后按回车键时,输入中有 两个 字符:您想要的字符加上一个“换行符”字符。您必须使用此换行符才能继续其他输入。
  • 注意第一个puts(b);输出的是不确定的数据;数组b 没有初始化,所以你不知道会打印什么。还要注意getchar() 返回一个int,而不仅仅是一个char。将值分配给char 会导致问题。

标签: c input bufferedinputstream


【解决方案1】:

在while循环中使用for循环

char b[2];
int x;

while(b)
{
    for(x=0;x<2;x++)
    {
    printf("Enter a character: ");
    scanf("%c",b[x]);
    printf("%c",b[x]);
    }
 b++;
}return;

【讨论】:

    【解决方案2】:

    您的代码中有几个错误。

    首先,这非常重要:不要再使用gets()。这是一个 危险函数:Why is the gets function so dangerous that it should not be used?

    除了gets 不再包含在C11 中。

    其次,您需要了解使用 键盘。当您输入文本时,您必须按 ENTER 读取路由以继续。 ENTER 也存储在输入中 缓冲区作为换行符 ('\n') 字符。所以如果你输入 abc 缓冲区将包含1:

    +---+---+---+----+
    | a | b | c | \n |
    +---+---+---+----+
    

    记住这一点很重要,因为例如fgets 停止从 遇到换行符2时的缓冲区。其他功能 像scanf 可能会根据使用的转换说明符读取换行符。

    你使用getchar

    man getchar

    #include <stdio.h>
    
    int fgetc(FILE *stream);
    
    int getc(FILE *stream);
    

    int getchar(void);

    描述

    fgetc() 从流中读取下一个字符并将其作为 unsigned char 强制转换为 intEOF 在文件结尾或错误时返回。

    getc() 等价于fgetc(),不同之处在于它可以实现为不止一次评估流的宏。

    getchar() 等价于getc(stdin)

    从文档中可以清楚地看出,getchar() 读取 one 字符 只要。在这一点上,重要的是要注意所有的阅读功能,如 fgetsscanf 等将首先尝试从输入缓冲区中读取,并且仅 当输入缓冲区为空并且他们仍然需要继续阅读时,他们 将等待用户输入。这意味着如果先前的读取函数留下字符 在输入缓冲区中,下一个读取函数可能不会等待用户输入, 因为它可能会从输入缓冲区中读取。

    假设您输入了 aENTER。输入缓冲区将 看起来像这样:

    +---+----+
    | a | \n |
    +---+----+
    

    输入缓冲区中至少有 2 个字符,'a' 和换行符。 getchar 读取第一个并返回。输入缓冲区现在看起来像这样:

    +----+
    | \n |
    +----+
    

    然后你执行gets(b);,会看到里面还有字符 输入缓冲区,因此它将从中读取。它读取换行符和gets 停止阅读,因为gets 停止阅读,因为换行符 在输入缓冲区中。 gets 不需要等待用户输入。作为 您认为gets 调用被跳过的用户。

    最后:

    char b[2];
    puts(b);
    

    这是未定义的行为,因为 b 是一个未初始化的数组,这意味着 b[0]b[1] 的值是未定义的(未知,它们可能是 0、-2323 或 2829281,没人知道)。 puts 需要一个字符串。在 C 中,字符串是序列 以值 0 结尾的非零字节(所谓的 '\0'-terminating 字节)。 b 不是字符串,所以 puts(b) 会产生未定义的行为。


    脚注

    1不知道输入缓冲区是否也存储了'\0'-terminating 换行符后的字节。无论如何,这里并不重要。

    2前提是目标缓冲区足够大。如果没有 目标缓冲区中有更多空间,fgets 无论如何都停止阅读。

    【讨论】:

      【解决方案3】:

      使用安全的fgets 而不是gets

      #include <stdio.h>
      #include <stdlib.h>
      
      int main(){
      
          char a[16];
      
          printf("1) Enter a character: \n");
          fgets ( a, sizeof (a), stdin );
          printf("1) You entered: %c \n",a[0]);
          puts(a);
      
      
          printf("2) Enter a character: \n");
          char b[16];
          fgets(b, sizeof(b), stdin);
          printf("2) You entered: %c \n",b[0]);
      
          puts(b);
      }
      

      输入:

      1
      B
      

      输出:

      1) Enter a character: 
      1) You entered: 1 
      1
      
      2) Enter a character: 
      2) You entered: B 
      B
      

      【讨论】:

      • fgets(b, sizeof b, stdin); 更安全。如果出于某种原因您更改了b 的尺寸(假设为10)并且不记得更改fgetss(因为它们相隔几行),您可能会遇到缓冲区溢出。还有fgets总是存储'\0'-终止的字符串,少读1个字节是没有意义的。
      • @Pablo 谢谢!很好的一点!我已经编辑了示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      • 2022-12-13
      • 1970-01-01
      • 2016-03-25
      • 1970-01-01
      • 1970-01-01
      • 2014-05-20
      相关资源
      最近更新 更多