簡體   English   中英

fgets()和scanf()之間的區別

[英]The difference between fgets() and scanf()

這是我的代碼。 我不想使用scanf()來讀取名稱,我嘗試使用fgets()但是在輸入了名字和年齡之后,第二次和第三次我的程序運行for循環時,它就不會使用age了。

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

struct student
{
    char name[15];
    int age;
};


int main()
{
    int i;
    struct student s[A];
    for (i = 0 ; i < A ; i++)
    {
        printf("enter the names and age\n");
        fgets(s[i].name, 10, stdin);
        scanf("%d", &s[i].age);
    }
    printf("\n\n");

    for (i = 0 ; i < A ; i++)
    {
        printf("%s\t%d\n", s[i].name, s[i].age);
    }
    return 0;
}

它不起作用,為什么呢?

但是當我用

scanf("%s%d",s[i].name,&s[i].age);

工作正常

fgets()和scanf()之間的區別

fgets(...)通常讀取直到收到'\\n'

scanf("%d", ...)通常:
1.讀取並丟棄前導空白。
2.讀取數字輸入(符號,數字),直到掃描非數字。
3.將非數字放回 stdin以用於下一個輸入功能。


例:

j 0 H N 輸入
fgets()"John\\n"讀入s[0].name

2 1 輸入
scanf("%d",...)21讀入s[0].age '\\n'放回stdin

fgets()"\\n"讀入s[1].name

中號
"M"scanf("%d",...)讀取, s[1].age沒有任何s[1].age 'M'放回stdin

A R y 輸入
fgets()"Mary\\n"讀入s[2].name

1 9 輸入
scanf("%d",...)19讀入s[2].age '\\n'放回stdin

fgets()"\\n"讀入s[3].name


備選方案:要讀取2行,請調用fgets()兩次, 然后解析:

int Scan_student(struct student *dest) {
  char buffer[2][80];
  dest->name[0] = '\0';
  dest->age[0] = -1;
  printf("enter the names and age\n");
  for (int i=0; i<2; i++) {
    if (fgets(buffer[i], sizeof buffer[i], stdin) == NULL) {
      return EOF; // stdin was closed, no more input (or input error)
    }
    buffer[i][strcspn(buffer[i], "\r\n")] = '\0'; // lop off potential trailing \n
  }
  // parse the 2 buffers: MANY options here - something simple for now.
  if (sscanf(buffer[0], " %14[-'A-Za-z ]", dest->name) != 1) {
    return 0;
  }
  if (sscanf(buffer[1], "%d", &dest->age) != 1) {
    return 0;
  }
  return 1;
}


int i;
struct student st[3];
for (i = 0 ; i < sizeof(st) / sizeof(st[0]) ; i++) {
  if (Scan_student(&st[i]) != 1) break;
}

如果在一行中同時輸入名稱和年齡,則這是正常行為,因為fgets()會讀取整行,直到讀取9個字節(在您的情況下)或找到一個'\\n'

您需要兩者之一,例如您只能使用fgets()

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

struct student
{
    char name[100];
    int age;
};


int main()
{
    int i;
    struct student s[1];
    for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
    {
        char number[100];
        char *unconverted;
        printf("Name > ");
        fgets(s[i].name, sizeof(s[i].name), stdin);
        if ((unconverted = strchr(s[i].name, '\n')) != NULL)
            *unconverted = '\0'; // Remove the trailing '\n'
        printf("Age  > ");
        fgets(number, sizeof(number), stdin);
        s[i].age = strtol(number, &unconverted, 10);
        if ((*unconverted != '\0') && (*unconverted != '\n'))
            s[i].age = -1; // Invalid value indicating input error
    }

    for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
        printf("Name: %s\nAge : %d\n", s[i].name, s[i].age);
    return 0;
}

或僅scanf()

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

struct student
{
    char name[100];
    int age;
};


int main()
{
    int i;
    struct student s[1];
    for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
    {
        printf("Name Age > ");
        if (scanf("%99s%d", s[i].name, &s[i].age) != 2)
        {
            fprintf(stderr, "input error\n");
            s[i].name[0] = '\0';
            s[i].age = -1;
        }
    }

    for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
        printf("Name: %s\nAge : %d\n", s[i].name, s[i].age);
    return 0;
}

然后您可以在一行中輸入姓名和年齡。

fgets()方法更好,因為您不需要處理scanf()不會從stdin拾取的'\\n' 如果您要強制用戶在單獨的行中輸入值,則可以使用組合鍵。

老實說,這里不需要fgets(),因為您已指定從stdin進行讀取,您應該只使用默認情況下從stdin讀取的gets()。 如果您在scanf()語句和gets()語句之間移動,則應使用fflush(stdin)清除輸入流,例如以下示例:

scanf("%99s", s[i].name);
fflush(stdin);
gets(s[i].age);

通常,最好還是使用scanf()或gets()而不合並它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM