2012-09-07 41 views
0

我正在寫這個來獲取學生信息(最後3個學期的全名,id和gpa,所以我使用了結構和一個for循環來插入信息,但是在第一次學習之後for循環(這意味着在學生2)我的第一個和第二個輸入一起顯示在屏幕上。我怎麼能以簡單易懂的方式來防止這種情況發生?(PS:我已經試圖把getchar();放在for循環的結束,它的工作,但是,我不應該使用它,因爲我們還沒有在課堂上所學到)C編程數據輸入錯誤

C程序的一部分在我的錯誤發生:

#include <stdio.h> 

struct Student { 
    char name[30]; 
    int id; 
    float gpa[3]; 
}; 

float averageGPA (struct Student []); 

int main() 
{ 
    int i; 
    float average; 
    struct Student studentlist[10]; 
    i=0; 

    for (i; i<10; i++) 
    { 
    printf("\nEnter the Student %d full name: ", i+1); 
    fgets(studentlist[i].name, 30, stdin); 
    printf("Enter the Student %d ID: ", i+1); 
    scanf("\n %d", &studentlist[i].id); 
    printf("Enter the Student %d GPA for the 1st trimester: ", i+1); 
    scanf("%f", &studentlist[i].gpa[0]); 
    printf("Enter the Student %d GPA for the 2nd trimester: ", i+1); 
    scanf("%f", &studentlist[i].gpa[1]); 
    printf("Enter the Student %d GPA for the 3rd trimester: ", i+1); 
    scanf("%f", &studentlist[i].gpa[2]); 
    } 

    average = averageGPA(studentlist); 

    printf("\n\nThe average GPA is %.2f", average); 

    return 0; 
} 

float averageGPA (struct Student studentlist[]) 
{ 
    int i; 
    float total = 0.0, average = 0.0; 
    for (i=0; i<10; i++) 
    { 
    total = studentlist[i].gpa[0] + studentlist[i].gpa[1] + studentlist[i].gpa[2]; 
    } 

    average = total/30 ; 
    return average; 
} 

計算機輸出:

Enter the Student 1 full name: mm 

Enter the Student 1 ID: 12 

Enter the Student 1 GPA for the 1st trimester: 3 

Enter the Student 1 GPA for the 2nd trimester: 4 

Enter the Student 1 GPA for the 3rd trimester: 3 

Enter the Student 2 full name: Enter the Student 2 ID: <<<<< Here is the problem!! 
+1

請修改您的文章適當的縮影。它似乎在複製/粘貼期間消失了。 – Lundin

+0

爲什麼不像所有其他輸入一樣,對_name_字段使用'scanf'? – Vishal

回答

1

使用scanf函數:

scanf(" %[^\n]",studentlist[i].name); 

格式說明第一個空間是很重要的。它否定了之前輸入的換行符。順便說一句,該格式指示閱讀,直到遇到新行(\ n)。

[編輯:根據要求添加的解釋]

格式說明用於接受字符串是%s。但它允許你只輸入非空白字符。另一種方法是在方括號內指定可接受(或不可接受,基於場景)的字符。

在方括號內,您可以指定單個字符,範圍或其組合。要指定要排除的字符,請在插入符號(^)前加上。

所以,%[a-z]將意味着a到z之間的任何字符(包括兩端)將被接受

在你的情況,我們需要比換行符被接受其他每個字符。所以我們拿出說明書%[^\n]

您將從網上獲得關於這些說明符的更多信息。這裏有一個方便鏈接:http://beej.us/guide/bgc/output/html/multipage/scanf.html

在開始的空間實際上'消耗'任何先前的輸入空白的前面的空白。你可以在這裏參考答案進行了詳細的解釋:scanf: "%[^\n]" skips the 2nd input but " %[^\n]" does not. why?

+0

我試過這個,它的工作很完美,但是我不知道你是如何得到這個格式說明符的,一點解釋就會很棒。非常感謝您的幫助 – MohdAziz

+0

我已經添加了解釋 – vaisakh

+0

哦,這太棒了,非常感謝您的幫助。 – MohdAziz

2

嘗試最後scanf吃完後換行:

scanf("%f ", &studentlist[i].gpa[2]); 
     ^

這是非常非常喜歡你的getchar解決方案。它實際上優於getchar,因爲它只丟棄空格。在下面的方法讀取學生姓名

+0

我試過這個,但它沒有奏效。在插入最後一個GPA並點擊輸入後,它會一直給我空間(例如,當你按下msword時輸入)。 – MohdAziz

2

但你必須使用getchar()你最後scanf("%f")後丟棄換行符仍處於輸入緩衝器,它根據給定的格式轉換的浮動和離開緩衝所有其他字符。

如果您不能使用getchar(),請在循環結束時使用另一個fgets() ..但當然getchar()會更好

編輯說明:每當你鍵入你的鍵盤字符進入輸入緩衝區等待由您的應用程序處理。 getchar()只從該緩衝區中「消耗」一個字符(返回它),如果緩衝區爲空,則等待有效字符。 scanf(「%f」)僅「消耗」導致浮動的字符。因此,當您鍵入「5.12 <輸入>」時,scanf讀取並從緩衝區「5.12」中刪除,並將「<」輸入>。所以下一個fgets()已經在緩衝區中找到一個換行符並立即返回;這就是爲什麼你應該使用getchar():忽略它的返回值,你成功地從緩衝區中丟棄了「<」輸入>。最後,請注意,如果在緩衝區中只有「<」輸入>,scanf(「%f」)會丟棄它(因爲它不能在float中轉換)並等待另一個輸入阻塞應用程序。

最後一個注意事項:輸入流被您的操作系統默認策略緩衝,從應用程序直到您輸入「<輸入>」纔會收​​到任何字符。

+0

scanf()在格式字符串中的空格(請參閱其他答案)會更好然而,因爲它只丟棄空白字符,並且同時丟棄任何數量的空白字符(例如CR + LF)而不是單個空白字符。 – Lundin

+0

我不確切知道getchar()做了什麼,但是在瀏覽互聯網之後,我看到了很多使用它的地方,所以我嘗試了它,並且它工作正常。你能否給我提供一個關於getchar()函數的信息性解釋,並且非常感謝你的幫助。保重 – MohdAziz

0

我只對scanf()說不。對所有輸入字段使用fgets(),並使用atoi()和atof()將其轉換爲數字。