[英]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
轉換為int
或strcmp
以與“ 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.