2017-06-01 149 views
0

我必須編寫一個新文件,其中必須有多個學生信息(如:Student_name, student_Surname, school_subject和學生人數)一行,我必須輸入新的學生,直到我輸入END。我不得不使用printf和scanf。姓名和科目可以是多個單詞當我嘗試使用scanf("[^\n]*c", name)時,我只能輸入一個學生的信息,循環只是忽略休息,對於其他學生,我只能輸入整數的學號。循環中的C程序scanf(「%[^ n]%* c」,...)

我的代碼有什麼問題?

int main() { 
    FILE *outputfile = NULL; 

    struct imenik { 
     char prezime[17 + 1]; 
     char ime[13 + 1]; 
     char predmet[20 + 1]; 
     int bodovi; 
    } ucenik; 

    outputfile = fopen("imenik.txt", "w"); 

    printf("Ucitaj ime ucenika: "); 
    scanf("%[^\n]%*c", ucenik.ime); 

    printf("Ucitaj prezime ucenika: "); 
    scanf("%[^\n]%*c", ucenik.prezime); 

    printf("Ucitaj predmet: "); 
    scanf("%[^\n]%*c", ucenik.predmet); 

    printf("\nUcitaj broj bodova (0-50): "); 
    scanf("%d", &ucenik.bodovi); 

    fprintf(outputfile, "%s | %s | %s | %d\n", ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi); 
    fclose(outputfile);  

} 
+5

'我要編制新file' ......好吧,thate是一個問題...... –

+0

的[可能的複製爲什麼我收到一個來自scanf循環的分段錯誤?](https://stackoverflow.com/questions/40327254/why-am-i-getting-a-segmentation-fault-from-scanf-loop) – Badda

+1

顯示你的代碼或我們不能幫助您。 – Badda

回答

1

的問題是在這裏:

scanf("%d", &ucenik.bodovi); 

這讀取的次數,但之後,在沒有閱讀的換行符。因此,當循環重複時,它將該換行讀取爲下一個學生名稱的空行輸入。

你可以把它改成:

scanf("%d ", &ucenik.bodovi); 

空間告訴它的數量後,任何空白跳過。

但實際上,最好將開頭的的空格放在每個scanf處,而不是在最後忽略換行符。有關說明,請參閱http://stackoverflow.com/questions/19499060/what-is-difference-between-scanfd-and-scanfd。因此,將其更改爲:

printf("Ucitaj ime ucenika: "); 
scanf(" %[^\n]", ucenik.ime); 

printf("Ucitaj prezime ucenika: "); 
scanf(" %[^\n]", ucenik.prezime); 

printf("Ucitaj predmet: "); 
scanf(" %[^\n]", ucenik.predmet); 

printf("\nUcitaj broj bodova (0-50): "); 
scanf("%d", &ucenik.bodovi); 
+0

OP的問題似乎沒有循環。第一個問題是。 –

+0

@VidorVistrom他在評論中說,他從帖子中刪除了它。 – Barmar

+0

他不應該有。它就像......你去看醫生,告訴他我的妻子正在牙痛。請開一些藥 –

1

我建議你實現這樣的:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define S_SIZE 32 
#define T_SIZE 128 
int main(void) { 
    FILE *outputfile = NULL; 

    struct imenik { 
     char prezime[S_SIZE]; 
     char ime[S_SIZE]; 
     char predmet[S_SIZE]; 
     int bodovi; 
    } ucenik; 

    outputfile = fopen("imenik.txt", "a"); 
    if (outputfile == NULL) { 
     perror("Fopen"); 
     exit(EXIT_FAILURE); 
    } 
    char tmp[T_SIZE]; 

    while (1) { 
     printf("Enter info separated with spaces: "); 
     fgets(tmp, T_SIZE, stdin); 
     if (strcmp(tmp, "END\n") == 0) { 
      break; 
     } 
     sscanf(tmp, "%s %s %s %d", ucenik.ime, ucenik.prezime, ucenik.predmet, &ucenik.bodovi); 
     fprintf(outputfile, "%s | %s | %s | %d\n", ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi); 
    } 
    fclose(outputfile); 

    return 0; 
} 
+0

有意使用'strncmp'而不是'strcmp'嗎?如果您不知道這將意味着輸入「ENDD \ n」,「END1654 \ n」或甚至「END31d6546esf16sdf687 \ n」將與「結束」沒有區別,因爲只評估了3個第一個字符。這種情況不應該被評估爲錯誤嗎?如果是,我推薦使用'strcmp(tmp,「end \ n)」' – nounoursnoir

+0

同意'fgets()'和'sscanf()'是更好的選擇,但是OP說「我必須使用printf和scanf」。而且這種解決方案只允許單個單詞嗎? OP說,「姓名和科目可以是多個詞。」 –

+0

@nounoursnoir是的,你說得對,我寫得很快。編輯。 –

0

你行:

scanf("%d", &ucenik.bodovi); 

離開輸入流中的換行符。在下一次呼叫scanf()時立即退出,並且將換行符留下,等等。不要嘗試向格式字符串添加尾隨空格字符,如有些人所建議的:"%d "。這會在輸入結束時消耗換行符,並等待更多輸入,直到遇到非空白字符或EOF

最簡單的方法,就是去做你已經做丟棄換行符:

scanf("%d%*c", &ucenik.bodovi); 

請注意,您應該使用scanf()時讀入一個字符串,以避免緩衝區溢出指定格式字符串,最大寬度:

scanf("%13[^\n]%*c", ucenik.ime); 

此外,您應該檢查outputfile以確保文件已成功打開。實施循環

一種方法是第一個電話的地方scanf()外循環,然後使用strcmp()while語句來檢查"END"。在循環結束後,重複第一次調用scanf()

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

int main(void) { 
    FILE *inputfile = NULL; 
    FILE *outputfile = NULL; 

    struct imenik { 
     char prezime[17 + 1]; 
     char ime[13 + 1]; 
     char predmet[20 + 1]; 
     int bodovi; 
    } ucenik; 

    outputfile = fopen("imenik.txt", "w"); 

    /* Did file open successfully? */ 
    if (outputfile == NULL) { 
     perror("Unable to open file:"); 
     exit(EXIT_FAILURE); 
    } 

    /* Specify maximum widths in calls to scanf() */ 
    printf("Ucitaj ime ucenika: "); 
    scanf("%13[^\n]%*c", ucenik.ime); 

    while (strcmp(ucenik.ime, "END") != 0) { 

     printf("Ucitaj prezime ucenika: "); 
     scanf("%17[^\n]%*c", ucenik.prezime); 

     printf("Ucitaj predmet: "); 
     scanf("%20[^\n]%*c", ucenik.predmet); 

     printf("\nUcitaj broj bodova (0-50): "); 
     scanf("%d%*c", &ucenik.bodovi); 

     fprintf(outputfile, "%s | %s | %s | %d\n", 
       ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi); 

     printf("Ucitaj ime ucenika: "); 
     scanf("%13[^\n]%*c", ucenik.ime); 
    } 

    fclose(outputfile); 

    return 0; 
}