fgets() doesn't function as expected [duplicat

2019-09-21 09:18发布

This question already has an answer here:

This is my code

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;
}

Given inputs are:

N = 3
red 50,
50 green,
blue 50

Here the problem is fgets inside for loop gets executed only twice if N is 3. This problem doesn't arise if I comment the scanf statement. Can somebody explain me what is causing this problem and how it can be solved?

标签: c scanf fgets
3条回答
闹够了就滚
2楼-- · 2019-09-21 09:21

After a few hours of scratching my head, I realized the following:

  • Avoid using scanf. Managing buffer overflows is not easy.
  • Always try to use fgets to get user inputs.

Try this code here:

#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;
}

Notice that I first input a number inside a char array. Convert that into a number using strtoul(string to unsigned long). Now inside the for loop I again use fgets to take inputs. The problem was, if you enter a string greater than 19 chars, the remaining part will be left inside the input buffer and shall be assigned to the subsequent input. To manage that I used getchar inside a while loop, which consumes all the unnecessary characters and the newline character from the input stream. Avoid using fflush as it may result in undefined behavior as answered here

-fflush(stdin) function does not work

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

Also note that you are using Variable Length Arrays which may not always be a good choice. Older versions of c compiler prohibit them. You had declared color[N][20] first before initializing N. That was wrong.

I suggest you to read this too

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

查看更多
Ridiculous、
3楼-- · 2019-09-21 09:24

After using scanf you'd need to clean the buffer. I suggest to never use scanf, just use fgets and then convert the output to a number:

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;
}
查看更多
等我变得足够好
4楼-- · 2019-09-21 09:46

Due to this reference: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm this will be correct:

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;
}

I changed scanf to scanf_s for VC++.

查看更多
登录 后发表回答