如何在追加后从文件中打印值

时间:2015-04-01 18:25:26

标签: c file struct scanf

我有以下问题:我必须制作一份包含姓名,年龄和成绩的学生档案。它工作正常,但问题是在屏幕上打印所有内容。当我输入' L'在屏幕上打印内容效果很好。当我按下A'要将另一名学生添加到文件中(附加),学生将出现在我的文件中(因此我们共有4名学生),但是当我按下“L'再次打印,它只打印4个学生中的3个,包括附加的一个,但删除另一个。 ' S'代表写文件。

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

struct student{
    char nume[20];
    int varsta;
    float medie;
};

void citire_date(struct student *studenti, FILE *f, int n){
    int i;

    for(i=0;i<n;i++){
        printf("Introduceti datele studentului %d\n", i+1);
        printf("Nume: "); fflush(stdin); gets((studenti+i)->nume);
        printf("Varsta: "); scanf("%d", &((studenti+i)->varsta));
        printf("Medie: "); scanf("%f", &((studenti+i)->medie));
        fprintf(f, "Nume: %s\n", (studenti+i)->nume);
        fprintf(f, "Varsta: %d\n", (studenti+i)->varsta);
        fprintf(f, "Medie: %.2f\n", (studenti+i)->medie);
        fprintf(f, "\n");
    }
}

void afisare_date(struct student *studenti, int n){
    int i;
    char nume1;
    int varsta1;
    float medie1;

    for(i=0;i<n;i++){
       printf("Nume: %s\n", (studenti+i)->nume);
        printf("Varsta: %d\n", (studenti+i)->varsta);
        printf("Medie: %.2f\n", (studenti+i)->medie);
        printf("\n");
    }
}

void append(struct student *studenti, FILE *f){
    int i;

    for(i=0;i<1;i++){
        printf("Nume: "); fflush(stdin); gets((studenti+i)->nume);
        printf("Varsta: "); scanf("%d", &((studenti+i)->varsta));
        printf("Medie: "); scanf("%f", &((studenti+i)->medie));
        fprintf(f, "Nume: %s\n", (studenti+i)->nume);
        fprintf(f, "Varsta: %d\n", (studenti+i)->varsta);
        fprintf(f, "Medie: %.2f\n", (studenti+i)->medie);
        fprintf(f, "\n");
    }
}

int main()
{
    FILE *f;
    struct student studenti[20];
    int n;
    char optiune;

    f=fopen("studenti.txt", "w");
    if(f==NULL){
        printf("Nu s-a putut deschide/crea fisierul pentru scriere.\n");
        exit(1);
    }

    printf("\n");

    do{
        printf("S. Scriere fisier.\n");
        printf("A. Adaugarea unui nou student in fisier.\n");
        printf("L. Listarea datelor tuturor studentilor.\n");
        printf("M. Modificarea datelor unui student.\n");
        printf("C. Cautarea unui student dupa nume.\n");
        printf("X. Terminarea programului.\n");
        printf("Introduceti optiunea: "); fflush(stdin); optiune=toupper(getchar());
        printf("\n");


        switch(optiune){
            case 'S':
                printf("Introduceti numarul de studenti: "); scanf("%d", &n);
                citire_date(studenti, f, n);
                fclose(f);
                printf("\n");
                break;
            case 'A':
                f = fopen("studenti.txt", "a");
                if(f==NULL ){
                    printf("Nu s-a putut deschide fisierul pentru adaugare.\n");
                    exit(2);
                }
                append(studenti, f);
                fclose(f);
                break;
            case 'L':
                afisare_date(studenti, n);
                break;
            case 'M':
                break;
            case 'C':
                break;
            case 'X':
                break;
            default:
                printf("\nAti introdus o optiune eronata!\n");
                break;

        }
    }while(optiune!='X');





    return 0;
}

我想我需要使用fscanf,但我不知道它是如何从文件中读取&#34; Nume:name&#34; &#34; Varsta:19&#34;等等。 提前谢谢。

3 个答案:

答案 0 :(得分:0)

我编辑了我的主要内容,所以现在一切都应该清楚了。

int main()
{
    FILE *f;
    struct student studenti[20];
    int n;
    char optiune;

     printf("Introduceti numarul de studenti: "); scanf("%d", &n);

    f=fopen("studenti.txt", "w");
    if(f==NULL){
        printf("Nu s-a putut deschide/crea fisierul pentru scriere.\n");
        exit(1);
    }
    citire_date(studenti, f, n);
    fclose(f);

    printf("\n");

    do{
        printf("A. Adaugarea unui nou student in fisier.\n");
        printf("L. Listarea datelor tuturor studentilor.\n");
        printf("M. Modificarea datelor unui student.\n");
        printf("C. Cautarea unui student dupa nume.\n");
        printf("X. Terminarea programului.\n");
        printf("Introduceti optiunea: "); fflush(stdin); optiune=toupper(getchar());
        printf("\n");


        switch(optiune){
            case 'A':
                f = fopen("studenti.txt", "a");
                if(f==NULL ){
                    printf("Nu s-a putut deschide fisierul pentru adaugare.\n");
                    exit(2);
                }
                append(studenti, f);
                fclose(f);
                break;
            case 'L':
                afisare_date(studenti, n);
                break;
            case 'M':
                break;
            case 'C':
                break;
            case 'X':
                break;
            default:
                printf("\nAti introdus o optiune eronata!\n");
                break;

        }
    }while(optiune!='X');





    return 0;
}

现在有什么建议吗?

答案 1 :(得分:0)

append()循环中

for(i=0;i<1;i++) {
    ...
    gets((studenti+i)->nume);

写入studenti[0]

它附加到文件但不附加到数组。该功能需要知道(并返回)您已有的学生人数。

int append(struct student *studenti, FILE *f, int studs){
    int i;

    printf("Nume: "); fflush(stdin); gets((studenti+studs)->nume);
    printf("Varsta: "); scanf("%d", &((studenti+studs)->varsta));
    printf("Medie: "); scanf("%f", &((studenti+studs)->medie));
    fprintf(f, "Nume: %s\n", (studenti+studs)->nume);
    fprintf(f, "Varsta: %d\n", (studenti+studs)->varsta);
    fprintf(f, "Medie: %.2f\n", (studenti+studs)->medie);
    fprintf(f, "\n");
    return studs + 1;
}

答案 2 :(得分:0)

你的代码并不遥远。主要问题是您对输入的处理以及对学生的追加。首先是几个关键问题:

fflush(stdin) 未定义的行为,并且总是错误的。永远不要使用gets它不再是libc的一部分而且不安全。

您可以使用格式字符串scanf轻松处理"%[^\n]%*c"的单个字符串输入。这将使用尾随newline和空stdin。 (它不是万无一失的,但它适用于大多数用途)。它还提供了一种方法来检查空字符串的返回值(例如,仅[Enter])并终止输入(见下文)。对于阅读数字(例如intfloat,...),您有责任在再次致电stdin之前清空scanf。我在下面为您创建了一个简单的flush_stdin()函数。

最后,append需要获取当前学生的数量并在函数内增加。将指针传递给n是解决此问题的最简单方法。它还允许您在append中阅读多个学生,只需在[Enter]的空行处点击(studenti + *n)->nume)即可终止输入。 (你也应该#define MAXSTUDENTS 20(你当前的,或者你需要的任何东西),以便你可以检查你在追加时不超过学生人数。(例如if (*n == MAXSTUDENTS)并采取适当的行动)

以下是您的代码的更新版本,它更接近您的预期方式。查看代码,如果您有疑问,请告诉我。

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

void flush_stdin () 
{
    int c = 0;
    while ((c = getchar()) != '\n' && c != EOF);
}

struct student{
    char nume[20];
    int varsta;
    float medie;
};

void citire_date(struct student *studenti, FILE *f, size_t n)
{
    int i = 0;  /* always initialize ALL variables */

    for(i=0;i<n;i++){
        printf("Introduceti datele studentului %d\n", i+1);
        printf("  Nume: "); scanf ( "%[^\n]%*c", (studenti+i)->nume);
        printf("  Varsta: "); scanf("%d", &((studenti+i)->varsta));
    flush_stdin ();
        printf("  Medie: "); scanf("%f", &((studenti+i)->medie));
    flush_stdin ();
        fprintf(f, "Nume: %s\n", (studenti+i)->nume);
        fprintf(f, "Varsta: %d\n", (studenti+i)->varsta);
        fprintf(f, "Medie: %.2f\n", (studenti+i)->medie);
        fprintf(f, "\n");
    }
}

void afisare_date(struct student *studenti, size_t n)
{
    int i = 0;
//     char nume1 = 0;     /* what are these for? */
//     int varsta1 = 0;
//     float medie1 = 0.0;

    for(i=0;i<n;i++)
    {
        printf("Nume: %s\n", (studenti+i)->nume);
        printf("Varsta: %d\n", (studenti+i)->varsta);
        printf("Medie: %.2f\n", (studenti+i)->medie);
        printf("\n");
    }
}

void append(struct student *studenti, FILE *f, size_t *n)
{
    int i = 0;

    while (1)
    {
        printf ("\nEnter student information ([Enter] when done)\n\n");
        printf("  Nume: "); 
        if (!scanf ( "%[^\n]%*c", (studenti + *n)->nume))
        {
            flush_stdin ();
            break;
        }
        printf("  Varsta: "); scanf("%d", &((studenti + *n)->varsta));
        if ((studenti+i)->varsta == '\n')
            break;
    flush_stdin ();
        printf("  Medie: "); scanf("%f", &((studenti + *n)->medie));
        if ((studenti+i)->medie == '\n')
            break;
    flush_stdin ();

        fprintf(f, "Nume: %s\n", (studenti + *n)->nume);
        fprintf(f, "Varsta: %d\n", (studenti + *n)->varsta);
        fprintf(f, "Medie: %.2f\n", (studenti + *n)->medie);
        fprintf(f, "\n");

        (*n)++;  /* increment numbre of students */
    }
}

int main()
{
    FILE *f = NULL;
    struct student studenti[20];
    size_t n = 0;
    char optiune = 0;

    f=fopen("studenti.txt", "w");
    if(f==NULL){
        printf("Nu s-a putut deschide/crea fisierul pentru scriere.\n");
        exit(1);
    }

    printf("\n");

    do{
        printf("S. Scriere fisier.\n");
        printf("A. Adaugarea unui nou student in fisier.\n");
        printf("L. Listarea datelor tuturor studentilor.\n");
        printf("M. Modificarea datelor unui student.\n");
        printf("C. Cautarea unui student dupa nume.\n");
        printf("X. Terminarea programului.\n");
        printf("Introduceti optiunea: "); 
        optiune=toupper(getchar());
        flush_stdin(); 
        printf("\n");


        switch(optiune){
            case 'S':
                printf("Introduceti numarul de studenti: "); scanf("%d", &n);
            flush_stdin ();
                citire_date(studenti, f, n);
                fclose(f);
                printf("\n");
                break;
            case 'A':
                f = fopen("studenti.txt", "a");
                if(f==NULL ){
                    printf("Nu s-a putut deschide fisierul pentru adaugare.\n");
                    exit(2);
                }
                append(studenti, f, &n);
                fclose(f);
                break;
            case 'L':
                afisare_date(studenti, n);
                break;
            case 'M':
                break;
            case 'C':
                break;
            case 'X':
                break;
            default:
                printf("\nAti introdus o optiune eronata!\n");
                break;

        }
    }while(optiune!='X');


    return 0;
}

<强>输出

$ ./bin/student_missing

S. Scriere fisier.
A. Adaugarea unui nou student in fisier.
L. Listarea datelor tuturor studentilor.
M. Modificarea datelor unui student.
C. Cautarea unui student dupa nume.
X. Terminarea programului.
Introduceti optiunea: s

Introduceti numarul de studenti: 1
Introduceti datele studentului 1
  Nume: John Student
  Varsta: 1
  Medie: 91.2

S. Scriere fisier.
A. Adaugarea unui nou student in fisier.
L. Listarea datelor tuturor studentilor.
M. Modificarea datelor unui student.
C. Cautarea unui student dupa nume.
X. Terminarea programului.
Introduceti optiunea: l

Nume: John Student
Varsta: 1
Medie: 91.20

S. Scriere fisier.
A. Adaugarea unui nou student in fisier.
L. Listarea datelor tuturor studentilor.
M. Modificarea datelor unui student.
C. Cautarea unui student dupa nume.
X. Terminarea programului.
Introduceti optiunea: a


Enter student information ([Enter] when done)

  Nume: Jill Student
  Varsta: 2
  Medie: 94.3

Enter student information ([Enter] when done)

  Nume: Juan Student
  Varsta: 3
  Medie: 92.5

Enter student information ([Enter] when done)

  Nume:
S. Scriere fisier.
A. Adaugarea unui nou student in fisier.
L. Listarea datelor tuturor studentilor.
M. Modificarea datelor unui student.
C. Cautarea unui student dupa nume.
X. Terminarea programului.
Introduceti optiunea: l

Nume: John Student
Varsta: 1
Medie: 91.20

Nume: Jill Student
Varsta: 2
Medie: 94.30

Nume: Juan Student
Varsta: 3
Medie: 92.50

S. Scriere fisier.
A. Adaugarea unui nou student in fisier.
L. Listarea datelor tuturor studentilor.
M. Modificarea datelor unui student.
C. Cautarea unui student dupa nume.
X. Terminarea programului.
Introduceti optiunea: x