来自stdin问题的fgets

我正在编写一个可以处理文件的程序。 我需要能够将数据作为结构输入,并最终将其读出。 我目前遇到的问题是这个代码:

typedef struct { char* name; ..... }employeeRecord; employeeRecord record; char name[50]; if(choice == 1) { /*Name*/ printf("\nEnter the name:"); fgets(name,50,stdin); record.nameLength = strlen(name) -1; record.name = malloc(sizeof(char)*record.nameLength); strcpy(record.name,name); /*Other data, similar format...*/ 

如果我想要,例如,姓名地址和电话号码,并要求连续每一个(所以地址几乎与上面相同,除了用地址替换’名称’),我发现它跳过输入。 我的意思是,我没有机会输入它。 输出实际上输入名称:输入地址:(这里是它提示我输入的地方)

我尝试了你的代码,无法重现问题。 以下代码按照您期望的方式工作,它会提示输入名称,等待您输入名称,然后提示输入地址等。

我想知道你是否需要在提示更多输入之前读取标准输入并清空它?

 typedef struct { char* name; char* address; }employeeRecord; int readrecord(employeeRecord &record) { char name[50]; char address[100]; printf("\nenter the name:"); fgets(name, sizeof(name), stdin); record.nameLength = strlen(name) + 1; record.name = malloc(sizeof(char)*record.nameLength); strcpy(record.name,name); printf("\nenter the address:"); fgets(address, sizeof(address), stdin); ... } 

很明显,你想在strlen(name)中加1,而不是减1.或者,如果你想在你的记录中存储没有终止null的名字,那么你需要使用memcpy将字符串复制到你的记录中,而不是strcpy。

编辑:

我从评论中看到你使用scanf来读取选择值,这会在输入缓冲区中留下一个\ n,然后由你的第一个fgets调用拾取。 你应该做的是使用fgets来读取选择行,然后使用sscanf来解析输入中的值。 像这样

 int choice; char temp[50]; fgets(temp, sizeof(temp), stdin); sscanf(temp, "%d", &choice); 

这应该使整个问题冲洗stdin没有实际意义。

新行仍处于先前调用函数的stdin ,该函数未从输入读取换行符。 通过阅读清除stdin ,直到你读出换行符 – 而不是像其他人所建议的那样刷新stdin

编辑:谢谢Alok,为了更正!

您可能在调用fgets读取名称之前使用scanf读取choicescanf可能在stdin留下了一个换行符,你的代码错误地输入了一个空名称。 如果确实如此,尽量不要使用scanf (使用fgets来检索choice并使用atoi转换为intstrcmp来与“1 \ n”进行比较等)。 代码应该可以工作,通过以下修改来解释fgets还将终止换行符读入缓冲区(您可能想要剥离):

  #define MY_LENOF(x) (sizeof(x)/sizeof((x)[0])) char choice[3] = { 0 }; /* example of how to initialize to all NULs */ if (!fgets(choice, MY_LENOF(choice), stdin)) { fprintf(stderr, "Premature end of input\n"); exit(1); } if (strcmp(choice, "1\n") == 0) { /*Name*/ printf("\nEnter the name:"); if (!fgets(name, MY_LENOF(name), stdin)) { /* if fgets fails it leaves name unchanged, so we reset it to "" */ name[0] = '\0'; } /* good practice to use srtnlen in order not to overrun fixed buffer */ /* not necessarily a problem with fgets which guarantees the trailing NUL */ size_t nameLength = strnlen(name, MY_LENOF(name)); assert(name[nameLength] == '\0'); if (nameLength - 1 > 0 && name[nameLength - 1] == '\n') { /* strip trailing newline */ name[--nameLength] = '\0'; } else if (nameLength >= MY_LENOF(name) - 1) { fprintf(stderr, "Name is too long\n"); exit(1); } else { fprintf(stderr, "Premature end of input\n"); exit(1); } record.nameLength = nameLength; record.name = malloc(sizeof(char)*(record.nameLength + 1)); strcpy(record.name, name);