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

时间:2015-05-28 17:11:01

标签: c fgets dynamic-memory-allocation

我正在尝试整理一个程序,该程序将要求用户输入要以随机顺序打印的集合列表的歌曲标题。该程序使用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

1 个答案:

答案 0 :(得分:3)

实际上,问题就在这里:

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

将其更改为: fgets(input, sizeof(input), stdin);你得到了这个:

http://i.gyazo.com/ec6185438adfb5c56c98ec5fcef67eaf.png

代码的其他一些问题:

    按照惯例,
  • argv是传递给main函数的标记化命令行字符串的名称,所以不要像这样命名变量,这会让人感到困惑
  • 使用#define,例如,使用#define MAX_SONGS 5代替将变量用于某事物的最大尺寸。 DiskStation> jikes -cp /opt/lib/rt.jar RunRmiRegistry.java Found 1 semantic error compiling "RunRmiRegistry.java": 42. for (String string : list) { ^ Semantic Error: Enhanced for loops (also known as foreach loops) are only supported for `-source 1.5' or greater.
  • 它非常错误,如果给出错误的输入会崩溃,你应该验证它(例如,如果我输入超过5首歌曲,你将溢出缓冲区并且很可能崩溃)