0

I'm very new at C++, maintaining my M.Sc on Information Systems. I have my first C++ homework announced and have been working on it for a couple of days. The aim of the code is simply to read info from a text file and print it on screen, then make calculation on some of it and print results to a new text file. However when I build, it gives the error:

EXC_BAD_ACCESS (code=EXC_I386_GBFLT)

in the first fscanf in readInfo function.

I know the code I wrote is not completely efficient but I just want it to print on screen and on output file correctly. I would really appreciate if anyone help me to resolve this error. I am about to freak out...

#include <stdio.h>

typedef struct {
    char id[10];
    char name[40];
    float midterm;
    float final;
    int attendance;
}Student;


void readInfo(Student studentList[], int *count)
{
    FILE *fin=fopen("scores.txt","r");

    char surname = '\0';
    *count=0;
    while(!feof(fin))
    {
        fscanf(fin,"%c %c %c %f %f %d",studentList[*count].id, studentList[*count].name, &surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);

        strcpy(studentList[*count].name, studentList[*count].name);
        strcat(studentList[*count].name, " ");
        strcat(studentList[*count].name, &surname);

        *count++;
    }fclose(fin);

    printf("%-7s%17s %5.1f %5.1f %-2d\n", studentList[*count].id, studentList[*count].name, studentList[*count].midterm, studentList[*count].final, studentList[*count].attendance);
}

float studentScore(float midterm, float final, int attendance)
{
    float score;
    int maxAttend=0;
    char id[10];
    char name[40];
    char surname[40];

    FILE *fin=fopen("scores.txt","r");

    while(!feof(fin))
    {
        fscanf(fin,"%c %c %c %f %f %d",id, name, surname, &midterm, &final, &attendance);

        if(attendance>maxAttend)
            maxAttend=attendance;

    }fclose(fin);

    score=midterm*0.3+final*0.5+(maxAttend/20)*attendance;

    return score;

}

float avgScore(Student studentList[])
{
    float average;

    int count;

    int totalScore=0;

    readInfo(studentList, &count);

    for(int i=0; i<=count; i++)
    {
        totalScore+=studentScore(studentList[count].midterm, studentList[count].final, studentList[count].attendance);
    }

    average=totalScore/count;

    return average;
}

void courseGradeOutput(Student studentList[])
{
    FILE *fout=fopen("output.txt","w");

    int count;
    int pass=0;
    float score;
    char letterGrade[2];
    float avg;

    fprintf(fout,"\tId\tName, Surname = (Score, Letter)\n");

    readInfo(studentList, &count);

    for(int i=0; i<=count; i++)
    {
        score=studentScore(studentList[i].midterm, studentList[i].final, studentList[i].attendance);

        if(score>=0 && score<=49)
        {    letterGrade[0]={'F'};
            letterGrade[1]={'F'};}
        else if (score>=50 && score<=59)
        {letterGrade[0]={'F'};
            letterGrade[1]={'D'};}
        else if (score>=60 && score<=64)
        {letterGrade[0]={'D'};
            letterGrade[1]={'D'};}
        else if (score>=65 && score<=69)
        {letterGrade[0]={'D'};
            letterGrade[1]={'C'};}
        else if (score>=70 && score<=74)
        {letterGrade[0]={'C'};
            letterGrade[1]={'C'};}
        else if (score>=75 && score<=79)
        {letterGrade[0]={'C'};
            letterGrade[1]={'B'};}
        else if (score>=80 && score<=84)
        {letterGrade[0]={'B'};
            letterGrade[1]={'B'};}
        else if (score>=85 && score<=89)
        {letterGrade[0]={'B'};
            letterGrade[1]={'A'};}
        else if (score>=90 && score<=100)
        {letterGrade[0]={'A'};
            letterGrade[1]={'A'};}

        if(score>=60)
            pass++;

        fprintf(fout,"%7s %16s = ( %4.1f, %6s\n)", studentList[i].id, studentList[i].name, score, letterGrade);

    }

    avg=avgScore(studentList);

    fprintf(fout,"\nSome statistics:\n\nClass Avg Score: %5.2f \n #Students: %11d \n #Passed Students: %4d \n #Failed Students: %4d",avg,count,pass,(count-pass));

    fclose(fout);

}

int main()
{   Student studentList[100];
    int count;

    readInfo(studentList, &count);

    courseGradeOutput(studentList);
}

Screenshot

Basak Oguz
  • 17
  • 7
  • Are you sure fscanf crashes? Side notes: `strcpy(studentList[*count].name, studentList[*count].name);` is nonsense. surname is a char, you only read a char but you `strcat(..., &surname)`. strcat-ing a char won't work. – Werner Henze Nov 18 '15 at 17:04
  • Yes, I believe it is fscanf, since the error is shown on that line (Screenshot). I don't know if showing the error on that line means something else. I am trying to put both name and surname info from txt file into studentList[i].name. Besides my code is nonsense, I would appreciate if you can guide me to make it right... – Basak Oguz Nov 18 '15 at 18:34
  • 1
    `*count++` does not do what you think it does. It first increments the pointer `count` and then dereferences it. This is probably what causes the crash. You need to write `(*count)++`. – MicroVirus Nov 18 '15 at 18:36
  • Thank you very much. Error solved. Now there is the issue that code prints nothing near what I want it to print.. :) – Basak Oguz Nov 18 '15 at 19:05

1 Answers1

1

The crash is most likely caused by either fscanf followed by strcpy and/or by your increment of count inside readInfo.

You write *count++, but this is equivalent to

count = count + 1;
*(count-1);

What you want is (*count)++.

The fscanf scans characters %c where you want to scan strings %s (for id and name). You also want to scan surname as a string, probably, but then you need to change surname to be a character array:

char surname[30];
*count=0;
while(!feof(fin))
{
    fscanf(fin,"%s %s %s %f %f %d",studentList[*count].id, studentList[*count].name, surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);

    strcat(studentList[*count].name, " ");
    strcat(studentList[*count].name, surname);

    (*count)++;
}
fclose(fin);

I also removed the first strcpy as you were copying from a buffer to itself, which is not allowed.

I haven't checked the other functions thoroughly, but I do notice that you do not use the result from your readInfo called from main when you do courseGradeOutput: this function calls readInfo again. You could modify it to take the read student records and the count, so you don't have to read the file again.

You might also want to improve scanf a bit to pass a width, such as %29s for name, to avoid overflowing the buffer when the name inside the file is too long; and the same for the other strings you scan. You should then also look at the return value of fscanf and only use the things you scanned when it succeeded in scanning every argument.

MicroVirus
  • 5,324
  • 2
  • 28
  • 53
  • Glad to hear it. You can accept the answer if it solved your problem, using the gray/green checkmark next to the answer. – MicroVirus Nov 18 '15 at 19:10