循环中的scanf(“%[^ \ n]%* c”,...)

时间:2017-06-01 07:51:30

标签: c scanf

我必须编制一个新文件,我必须在一行中有多个学生信息(例如:Student_name, student_Surname, school_subject和学生人数),我必须输入新学生,直到我输入END。

我必须使用printf和scanf。名字,姓氏和主题可以是多个单词当我尝试使用scanf("[^\n]*c", name)时,我只能输入一个学生的信息而循环只是忽略休息而对于其他学生我只能输入整数的学生数。

我的代码出了什么问题?

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);    

}

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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;
}

答案 2 :(得分: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;
}