2017-06-01 107 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; 
}