繁体   English   中英

从标准输入问题中得到的东西[C]

[英]fgets from stdin problems [C]

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

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...*/

例如,如果我想要命名地址和电话号码,并连续要求输入(因此地址与上述地址几乎相同,只不过用地址替换“名称”),我发现它会跳过输入。 我的意思是,我没有机会输入它。 输出实际上是输入名称:输入地址:(这是提示我输入的位置)

从先前调用未从输入中读取换行符的函数之前,换行符仍处于stdin输入中。 通过阅读来清除stdin ,直到您读出换行符为止- 而不是像其他人建议的那样冲洗stdin

编辑:感谢Alok,为更正!

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

我想知道您是否在提示输入更多信息之前不需要阅读stdin并将其清空?

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问题变得毫无意义。

您可能在调用fgets读取名称之前使用scanf来读取choice scanf可能在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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM