什么会导致 fgets() 不断等待输入?

What will cause fgets() to continuously wait for input?

我正在尝试编写一个程序,该程序将要求用户输入要以随机顺序打印的曲目列表的歌曲名称。该程序使用 fgets() 获取歌曲标题。也是用内存分配的方式把每首歌曲放进去,类似于:

 argv[0] = song1, argv[1] = song2, argv[2] = song3 (etc.)

我运行遇到的问题是程序执行时fgets()一直在等待输入,此时一共只有五首歌曲需要输入。我想知道什么会导致 fgets() 不断等待输入?感谢您的帮助。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>


int main( void ){

  printf("\tPlease enter the songs you want to play!\n");
  printf("\tI will create the set list and randomize it for you!\n");
  printf("\t(enter all songs with a space in between each and then press 'enter')\n");


  int s = 5; //Here we declare number of songs to be entered
  int set = 5;//This is set list size
  char input[100];
  char *argv[ s ];
  char *token;

  /* get the input and perform memory allocation */
  fgets(input, s, stdin);

  token = strtok(input, " ");

  int i=0;

  while( token != NULL ) {

    argv[i] = malloc(strlen(token) + 1);
    memcpy(argv[i], token, strlen(token)+1);
    i++;
    token = strtok(NULL, " ");
  } 
  argv[i] = NULL; //argv ends with NULL

  unsigned int setList[ s ];
  memset( setList, 0, s*sizeof(unsigned int) );//Must manually initalize array
  srand( time( NULL ) ); // seed random-number generator

  /*Begin Randomize Code*/
  size_t column;
  size_t c;
  size_t c1;
  size_t column1;

  for ( c = 1; c <= set; ++c ) {
    do {
      column = rand() % s;

    } while( setList[ column ] != 0 );

    setList[ column ] = c;

  }//end of for
  /*End Randomize Code*/

  /*Begin Code to Print SetList*/
  for ( c1 = 1; c1 <= set; ++c1 ) {

    for ( column1 = 0; column1 < s; ++column1 ) {

      if ( setList[ column1 ] == c1 ) {

        printf( "%s\n", argv[ column1 ]); 

      }//end of for  (oops if)
    }//end of for
  }//end of if  (oops for)
  /*End Code to Print SetList*/

}//end of main

其实问题就在这里:

fgets(input, s, stdin); <-- 你告诉fgets只读5个字符(实际上只有4个,第五个字符是空终止符);这意味着您的标记化将失败,并且不会为 argv 的所有五个元素分配内存,导致稍后在您的 printf 调用中发生访问冲突。

改为: fgets(input, sizeof(input), stdin); 你会得到这个:

代码的一些其他问题:

  • argv 按照惯例,是传递给 main 函数的标记化命令行字符串的名称,所以不要这样命名变量,这会造成混淆
  • 不要对某物的最大尺寸等使用变量,而是使用 #define,例如#define MAX_SONGS 5
  • 它有很多错误,如果输入错误会崩溃,你应该验证它(例如,如果我输入超过 5 首歌曲,你会溢出你的缓冲区并且很可能会崩溃)