【问题标题】:fgets() doesn't function as expected [duplicate]fgets() 没有按预期运行 [重复]
【发布时间】:2017-06-04 20:57:24
【问题描述】:

这是我的代码

int main(){
   int N,i,radius,diameter,count =0;
   char str[20];
   char color[N][20];
   printf("Get the num : ");
   scanf("%d",&N);

   printf("Enter the mesage\n");
   for(i=0;i<N;i++){
      fgets(color[i],20,stdin);
   }
   for(i=0;i<N;i++){
      printf("%s",color[i]);
  }
  return 0;
}

给定的输入是:

N = 3
red 50,
50 green,
blue 50

这里的问题是,如果N 为3,则for 循环中的fgets 只会执行两次。如果我评论scanf 语句,则不会出现此问题。谁能解释一下是什么导致了这个问题以及如何解决?

【问题讨论】:

  • scanf("%d%*c", &amp;N); char color[N][20];
  • 告诉我你给 fputs 的确切三个输入
  • 问题是您使用scanf 进行用户输入。
  • 请不要那样做!不要在建议的修复中进行编辑。您刚刚使 cmets/answers 无效!有人应该回滚。
  • char color[N][20] N是什么值?

标签: c scanf fgets


【解决方案1】:

在摸索了几个小时后,我意识到以下几点:

  • 避免使用scanf。管理缓冲区溢出并不容易。
  • 始终尝试使用 fget 获取用户输入。

在这里试试这个代码:

#include<stdio.h>
#include<stdlib.h>
int main(){
   int N,i,radius,diameter,count =0;
   char str[20];

   printf("Get the num : ");

   char buffer[64];
   fgets(buffer, 64, stdin);
   N = strtoul(buffer,NULL,10); 
   char color[N][20];

   printf("%d\n",sizeof(color));

   printf("Enter the mesage\n");

   for(i=0;i<N;i++){
      fgets(color[i],20,stdin);
      if(color[i][strlen(color[i])-1]=='\n'){

     color[i][strlen(color[i])-1]='\0';
  }
  else{

     while((getchar())!='\n');//this is just to prevent an overflow for the size of char arrays
  }

   }
   for(i=0;i<N;i++){
      printf("%s\n",color[i]);
  }
  return 0;
}

请注意,我首先在 char 数组中输入了一个数字。使用 strtoul(string to unsigned long) 将其转换为数字。现在在 for 循环中,我再次使用 fgets 来获取输入。问题是,如果您输入的字符串大于 19 个字符,则剩余部分将留在输入缓冲区内,并应分配给后续输入。为了解决这个问题,我在 while 循环中使用了 getchar,它消耗了输入流中所有不必要的字符和换行符。避免使用 fflush,因为它可能导致此处回答的未定义行为

-fflush(stdin) function does not work

-http://www.geeksforgeeks.org/clearing-the-input-buffer-in-cc/

另外请注意,您使用的可变长度数组可能并不总是一个好的选择。旧版本的 c 编译器禁止它们。你在初始化 N 之前先声明了 color[N][20]。这是错误的。

我建议你也读一下

-C - scanf() vs gets() vs fgets()

【讨论】:

  • char color[N][20]; :您正在使用未初始化的变量。
  • 您正在使用N 而不设置值。 " %[^\n]" 也应该是 " %19[^\n]"
  • 你应该防止scanf(" %[^\n]",color[i]);中的缓冲区溢出
  • 一开始就不应该使用scanf 进行用户输入。
【解决方案2】:

使用 scanf 后,您需要清理缓冲区。我建议永远不要使用 scanf,只使用 fgets 然后将输出转换为数字:

int main(){
   int N,i,radius,diameter,count =0;
   char str[20];
   char color[N][20];
   printf("Get the num : ");

   char buffer[64];
   fgets(buffer, 64, stdin);
   N = atoi(buffer); // you need to include stdlib.h

   printf("Enter the mesage\n");
   for(i=0;i<N;i++){
      fgets(color[i],20,stdin);
   }
   for(i=0;i<N;i++){
      printf("%s",color[i]);
  }
  return 0;
}

【讨论】:

  • 在声明char color[N][20] 之前,您必须确保N 具有严格的正(非零、非负)值——它在未初始化时不会。跨度>
【解决方案3】:

由于此引用: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm 这是正确的:

int _tmain(int argc, _TCHAR* argv[])
{
    int N, i, radius, diameter, count = 0;
    char str[10];
    char color[20];
    printf("Get the num : ");
    scanf_s("%d", &N);

    printf("Enter the mesage\n");
    //for (i = 0; i<N; i++){
        fgets(color, 20, stdin);
    //}
    //for (i = 0; i<N; i++){
        printf("%s", color);
    //}
    return 0;
}

对于 VC++,我将 scanf 更改为 scanf_s

【讨论】:

  • 你的代码实际上在做另一件事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多