【问题标题】:Why does scanf skip getting string input? [duplicate]为什么 scanf 跳过获取字符串输入? [复制]
【发布时间】:2017-11-14 05:11:53
【问题描述】:

我正在尝试将多个单词输入和多行输入到一个数组中。但是代码在某处跳过获取输入并跳过结束程序。我尝试在“%s”(或“%s”)之前和之后添加空格,但它不起作用(可能是因为它在循环内?)。非常感谢任何人的帮助!如果我输入超过两三个词,它也会开始表现得很奇怪:( 我的目标是找出一个特定字母在所有这些单词和行中出现了多少次。

#include <stdio.h> //include standard library

int main(){
  int lineCount, occuranceCount;
  printf("How many lines are you going to enter?");
  scanf("%d", &lineCount);

  char input[lineCount][100], searchChar;

  for(int i=0; i<lineCount; i++){
    printf("Please enter line #%d (100 characters of less):",i+1);
    scanf("%s", &input[i]);
  }

  printf("What letter do you want to check the frequence in those lines? ");
  scanf("%c", &searchChar);

  for(int j=0; j<lineCount; j++){
    for(int k=0; k<100; k++){
      if(input[j][k] != '\0'){
        if(input[j][k]==searchChar)
          occuranceCount++;
      }
    }
  }

  printf("The letter occurs for %d time", occuranceCount);

  return 0;
}

【问题讨论】:

  • 这是推荐使用fgets(或POSIX getline)而不是scanf的主要原因之一您使用的函数,您必须验证返回以确保在下次尝试访问您尝试访问的内容时不会调用Undefined Behavior阅读。
  • scanf("%s", &amp;input[i]); -> scanf("%99s", input[i]);
  • 为什么会出现 skps 的摘要? (1)您使用scanf ("%d"...) 阅读,留下'\n'(来自用户在stdin 中按Enter。(2)您调用scanf ("%s"...),因为"%s" format specifier 从头读取到第一个 whitepace'\n' 是空白),它没有从stdin 中删除;(3)你很高兴地调用scanf ("%c"...)接受 '\n' 作为其输入的 字符 并且 (4) 您未能检查所有调用的返回。
  • “寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误以及重现所需的最短代码它在问题本身。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建minimal reproducible example!"
  • 您的问题缺少您输入程序并从中接收的确切输入/输出

标签: c char scanf getchar


【解决方案1】:
  scanf(" %c", &searchChar);
         ^

您需要这里的空间来消耗来自stdin 的任何\n

scanf() 也会像你想的那样读取一个单词而不是一行(空格分隔的单词)。

而且最好使用strlen(input[j]) 来了解您应该阅读多少。

另外,在循环中使用size_t 而不是int

occuranceCount 初始化为0

还要避免buffer overrun 漏洞利用在您的代码中使用scanf("%99s", input[i]);

要读取一行,您可以使用fgets()

【讨论】:

    【解决方案2】:

    1) 改变

      scanf("%c", &searchChar); -->   scanf(" %c", &searchChar);
    

    从先前的scanf 中删除输入缓冲区中留下的任何\n

    2) 改变

    for(int k=0; k<100; k++){ --> for(int k=0; k<strlen(input[j]); k++){
    

    避免阅读超出实际用户输入的内容。

    除此之外:

    永远不要使用scanf("%s", &amp;input[i]);,因为用户可能会溢出您的输入缓冲区。至少将其更改为:scanf("%99s", &amp;input[i]);,但考虑改用fgets

    使用fgets,您的程序可能是:

    #include <stdio.h> 
    
    int main(){
      size_t lineCount = 0, occuranceCount = 0;
      printf("How many lines are you going to enter?");
      scanf("%zu ", &lineCount);
      if (lineCount == 0) return 0;  // Input error
    
      char input[lineCount][100], searchChar;
    
      for(size_t i=0; i<lineCount; i++){
        printf("Please enter line #%zu (100 characters of less):",i+1);
        fgets(input[i], 100, stdin);
      }
    
      printf("What letter do you want to check the frequence in those lines? ");
      scanf("%c", &searchChar);
    
      for(size_t j=0; j<lineCount; j++){
        for(size_t k=0; k<strlen(input[j]); k++){
            if(input[j][k]==searchChar) occuranceCount++;
        }
      }
    
      printf("The letter occurs for %zu time", occuranceCount);
    
      return 0;
    }
    

    【讨论】:

    • scanf("%zu ", &amp;lineCount); 直到在行数之后输入一行非空白文本后才会返回。将scanf()fgets() 混合使用具有挑战性。最好只使用fgets()
    【解决方案3】:

    使用 %s 的 scanf 始终读取直到遇到 ' '(空格)或 '\n'(新行),因此您始终只能使用 scanf("%s", s1)... 读取一个单词

    如果你想读取空格或换行符,你必须使用gets,或者fgets(比gets更安全)

    【讨论】:

      猜你喜欢
      • 2017-08-12
      • 2021-03-19
      • 2012-06-11
      • 1970-01-01
      • 2014-08-06
      • 2022-11-24
      • 1970-01-01
      • 2021-07-31
      • 1970-01-01
      相关资源
      最近更新 更多