簡體   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