2016-05-13 23 views
0

我遇到了一些問題,例如將字符串(例如名稱)保存到struct字段中。我已經使用gets()fgets(),但fgets()也無法正常工作。使用gets()將字符串保存到結構中?

我從來沒有機會輸入第一個員工的名字;它直接跳到員工代碼,然後跳過地址。出於某種原因,輸入第二名員工時,我輸入姓名和代碼,然後再次跳過地址。

任何人都知道我在做什麼錯了?

#include <stdio.h> 

typedef struct { 
    char name[150]; 
    int code; 
    char add[300]; 
} tEmployee; 

int main() 
{ 
    printf("How many employees would you like to register?\n"); 
    int n; 
    scanf("%i", &n); 

    tEmployee employee[n]; 

    for (int i = 0; i < n; i++) 
    { 
     printf("Name: "); 
     gets(employee[i].name); 
     printf("Code: "); 
     scanf("%i", &employee[i].code); 
     printf("Address: "); 
     gets(employee[i].add); 

     printf("%s\n", employee[i].name); 
     printf("%i\n", employee[i].code); 
     printf("%s\n", employee[i].add); 
    } 
    return 0; 
} 
+4

切勿使用'gets()'。 –

+4

[永遠不要使用gets()](http://stackoverflow.com/q/1694036/10077)。 –

+1

還記得按下* scanf的*鍵嗎?數字和輸入?輸入生成'\ n'。 'gets' /'fgets'消耗它,因此不等待進一步的輸入。修復?在每個scanf後添加'getchar();'。 –

回答

1

C庫輸入例程與處理換行符(\ n)的方式不一致。有些人將其作爲輸入的一部分進行閱讀,有些則沒有。由於scanf()在換行符之前得到了它所需要的內容,所以它沒有理由讀取它,所以我們必須明確地在下一次輸入之前將其從緩衝區中清除。有不同的技術,但只是調用getchar()這個例子。

而且,由於gets()被認爲是不安全的,並留下一個換行符晃來晃去您的輸入結束後,我添加了一個自定義的my_gets()包裝,解決這兩個問題:

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

typedef struct { 
    char name[150]; 
    int code; 
    char add[300]; 
} tEmployee; 

char *my_gets(char *str, int size) 
{ 
    char *pos; 

    char *result = fgets(str, size, stdin); 

    if (result != NULL && (pos = strchr(str, '\n')) != NULL) 
     *pos = '\0'; 

    return result; 
} 

int main() 
{ 
    int n; 
    printf("How many employees would you like to register?\n"); 
    scanf("%i", &n); 
    getchar(); // eat newline \n 

    tEmployee employee[n]; 

    for (int i = 0; i < n; i++) 
    { 
     printf("Name: "); 
     my_gets(employee[i].name, 150); 

     printf("Code: "); 
     scanf("%i", &employee[i].code); 
     getchar(); // eat newline \n 

     printf("Address: "); 
     my_gets(employee[i].add, 300); 

     printf("%s\n", employee[i].name); 
     printf("%i\n", employee[i].code); 
     printf("%s\n", employee[i].add); 
    } 

    return 0; 
} 

你可以做一個類似的包裝功能爲您的特定用途scanf(),爲您額外換行符,所以你不必擔心它,每次你調用該函數的輸入。

0

這是你的混合使用getsscanf。我在C++中面臨類似的問題,當我混合使用std::cin>>運算符和std::getline函數。

此外,gets已過時,不使用它......

無論如何,如果你真的想都使用了,那麼你就應該「刷新」下一次你使用scanf每一次,或標準輸入你讀了stdin,你會讀到它的其餘部分直到行尾(\n)。

One way to do it,是每個scanf後讀取,直到行的末尾:

/* define the function */ 
void flush() 
{ 
    while (getchar() != '\n'); 
} 

然後用它在你的代碼如下:

printf("How many employees would you like to register?\n"); 
int n; 
scanf("%i", &n); 

flush(); 

tEmployee employee[n]; 

for (int i = 0; i < n; i++) 
{ 
    printf("Name: "); 
    gets(employee[i].name); 
    printf("Code: "); 
    scanf("%i", &employee[i].code); 

    flush(); 

    printf("Address: "); 
    gets(employee[i].add); 

    printf("%s\n", employee[i].name); 
    printf("%i\n", employee[i].code); 
    printf("%s\n", employee[i].add); 
} 
return 0; 
0

試試這個:

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

typedef struct { 
    char name[150]; 
    int32_t code; 
    char add[300];  
} tEmployee; 

typedef uint_fast8_t bool_t; 

/***************************************************************************** 
* flush stdin... this should be standard but somewhy you need to reinvent 
* it all the time... 
*****************************************************************************/ 
static inline void flush_stdin() 
{ 
    char ch; 

    do { 
     ch = getchar(); 
    } while ((ch != '\n') && (ch != EOF)); 
} 

/***************************************************************************** 
* reads a line of text from a stream. 
*****************************************************************************/ 
static inline bool_t xio_fgetline(FILE *stream, char *linebuf, size_t szline) 
{ 
    fgets(linebuf, szline, stream); 

    // find last character. 
    char *lc = linebuf + strlen(linebuf) - 1; 

    // the only case when lc is a null is if the program memory 
    //  has been altered. In this case, it should crash anyway. 
    //  therefore I skip a nullcheck before chomping. 

    // chomp linebuf. 
    if (*lc == '\n') { 
     *lc = 0; 
    } 

    // string is {0} after chomping. 
    if (strlen(linebuf) == 0) { 
     return 0; 
    } 

    return 1; 
} 

/***************************************************************************** 
* reads a line of text from stdin. 
*****************************************************************************/ 
static inline bool_t xio_getline(char *linebuf, size_t szline) 
{ 
    return (xio_fgetline(stdin, linebuf, szline)); 
} 

int main(int argc, char **argv) 
{ 
    int32_t n; 
    tEmployee *employee = (tEmployee *)0; 

    printf("How many employees would you like to register?\n"); 
    scanf("%i", &n); 
    flush_stdin(); 

    employee = (tEmployee *)malloc(n * sizeof(tEmployee)); 

    for (int32_t i = 0; i < n; ++i) { 
     printf("Name: "); 
     xio_getline(employee[i].name, sizeof(employee[i].name)); 

     printf("Code: "); 
     scanf("%i", &employee[i].code); 
     flush_stdin(); 

     printf("Address: ");   
     xio_getline(employee[i].add, sizeof(employee[i].add)); 

     printf("%s\n", employee[i].name); 
     printf("%i\n", employee[i].code); 
     printf("%s\n", employee[i].add); 
    } 

    free(employee); 
    return 0; 
}