0

In this program I am suppose to read a file for records.ssv and print it out using an array of structures. However the average is to be calculated before printing out the array. The file contains Student Name, ID, Exam1, Exam2, Project 1, Project 2, Average, and Grade(letter, single).

Currently having problems printing out eh array and calculating the average. I will post my code and output below.

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

typedef struct {
        char name[25];
        int I_D[9];
        int exam[2];
        int project[2];
        char grade;
        float avg;
} STUDENT;

void printStuAry(int size, STUDENT stuAry[]);

int main(void)
{
    STUDENT stuAry[5];

    FILE* f = fopen("records.ssv", "r");
    if (f == NULL) {
            printf("Error opening file records.ssv.\n");
            exit(1);
    }

    char line[65];
    int ind = 0;

    while (fgets(line, sizeof(line), f) != NULL) {
        sscanf(line, "%25[^,] ; %d ; %d ; %d ; %d ; %d ; %c",
               stuAry[ind].name,
               &stuAry[ind].I_D,
               &stuAry[ind].exam[0],
               &stuAry[ind].exam[1],
               &stuAry[ind].project[0],
               &stuAry[ind].project[1],
               &stuAry[ind].grade);
        ind++;
    }
    // calculates average
    stuAry[ind].avg = (stuAry[ind].exam[0] + stuAry[ind].exam[1] +
                       stuAry[ind].project[0] + stuAry[ind].project[1]) /4.0;

         printf("\t+---------+-------+-------+-------+---------+----------+----------+------+\n");
    printf("\t| Index   |Student| ID    | Exam1 | Exam2   |Project1  | Project2 | Grade|\n");
    printf("\t+---------+-------+-------+-------+---------+----------+--------+--------+\n");

    printStuAry(5, stuAry);
    if (fclose(f) == EOF) {
        printf("Error closing file records.ssv.\n");
        exit(2);
    }

    int letter;
    printf("Enter grade letter to search and q to quit");
    scanf("%d", letter);

    while (letter != -1){// tests for whether user wants to end program
        printStuAry(5, stuAry);
    }

    return 0;
}

/*
*Function name: printStuAry
*
*Input Parameters: int size Student Ary
*
*Desription: prints out student Ary
*                                                                
*Return value: 0
*/

void printStuAry(int size, STUDENT stuAry[])
{
        for (int i=0; i<size; i++) {
                printf("\t|  %d     |  %s   | %d    |  %d   |  %d     |   %d    |   %d     |  %c  |\n", //displays student information
                                         i, stuAry[i].name, stuAry[i].exam[0],
                                         stuAry[i].exam[1], stuAry[i].project[0],
                                         stuAry[i].project[1], stuAry[i].avg,
                                         stuAry[i].grade);
        }
}

Output

        +---------+-------+-------+-------+---------+----------+----------+------+
        | Index   |Student| ID    | Exam1 | Exam2   |Project1  | Project2 | Grade|
        +---------+-------+-------+-------+---------+----------+--------+--------+
        |  0     |  Panzer   | -544760936    |  32568   |  -544762280     |   32568    |   -27     |     |
        |  1     |  Basler   | -1718237240    |  32767   |  -544747128     |   32568    |   -104     |     |
        |  2     |  Leaton   | -1718237400    |  32767   |  118     |   0    |   9     |     |
        |  3     |  Bishop   | 4195301    |  0   |  194     |   0    |   62     |     |
        |  4     |  Lucey   | -1718237064    |  32767   |  4197349     |   0    |   -96     |     |
Enter grade letter to search and q to quit

What the correct Output should be:

Original:

+-------------------------+--------------+------+------+---------+---------+-------+-----+
| Student Name|Identification|Exam 1|Exam 2|Project 1|Project 1|Average|Grade|
+-------------------------+--------------+------+------+---------+---------+-------+-----+
| Holtkamp, Norman| N21102485| 83| 61| 62| 78| 71.00| C|
| Bellomy, Shavonda| N94185259| 74| 96| 80| 98| 87.00| B|
| Clutter, Loris| N68760306| 83| 68| 93| 70| 78.50| C|
| Rountree, Edythe| N76813896| 98| 91| 90| 81| 90.00| A|
| Waldeck, Marylee| N44293872| 88| 100| 70| 87| 86.25| B|
+-------------------------+--------------+------+------+---------+---------+-------+-----+
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
josmar
  • 57
  • 5
  • Please properly indent your code. As it is, it makes it more difficult to read. – e0k Dec 04 '16 at 18:40
  • 1
    This is all unclear? Are you claiming that `%c` prints you a number and not a character? Either way probably wrong values in the structure. Notice that is also doesn't seem like you print ID in your function. Also why is ID array of integers and not a string (array of characters)? Not to mention you're just reading the value to its first cell (I_D[0]) and not every digit because you mentioned %d to sscanf – Zach P Dec 04 '16 at 18:43
  • 1
    Also, I would suggest to check the return value from your `sscanf()` to ensure that everything was read correctly. – e0k Dec 04 '16 at 18:47
  • 1
    Note that the calculate average calculation is outside the input loop. It is executed once, when `ind` is probably pointing beyond the end of the array of students. Who know what happens when you do that? The answer is 'no-one' — the behaviour is undefined. Indenting the code so it is semi-readable makes it much easier to spot such problems. – Jonathan Leffler Dec 04 '16 at 19:39
  • The correct output is not very pretty; surely, you should have headings aligned with the data, and the columns should be wide enough for the longer of 'the longest data item' and 'column heading'. – Jonathan Leffler Dec 04 '16 at 19:41
  • You should check that `sscanf()` returns the correct number of fields, which is 7 (name, number, and 4 marks, grade). Your scan set `%25[^,]` should use a semicolon and not a comma. You should also show the 5 lines of data that you have for input. That allows us to help identify any other issues with it. There's a strong argument that you should have a space before the scanset in the format string to skip trailing newlines from the previous line of input. – Jonathan Leffler Dec 04 '16 at 19:43
  • You failed to post the contents of the input file `records.ssv`. – Armali Mar 27 '18 at 09:28

2 Answers2

0

Try replacing sscanf(line, "%25[^,] ; %d ; %d ; %d ; %d ; %d ; %c", with sscanf(line, "%25[^,] %d %d %d %d %d %c",

Sourabh
  • 545
  • 5
  • 12
  • But the file data is separated by semicolons, just thought maybe if I used semicolons in the sscanf it would be more accurate – josmar Dec 04 '16 at 19:04
  • In that case, you will need to read the line into a variable and use strtok method to split by delimiter. Refer http://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c – Sourabh Dec 04 '16 at 19:08
0
typedef struct {
        char name[25];
        int I_D[9];
        …
} STUDENT;

You seem to have mixed up char I_D[9] with int I_D; according to the shown sample data, the Identification consists of an N and eight digits; you have to make up your mind whether you want to store it as a string (for which char [9] would be too short) or as an integer (without the N); let's assume the latter.

        sscanf(line, "%25[^,] ; %d ; %d ; %d ; %d ; %d ; %c",

But the file data is separated by semicolons…

Then the sscanf is wrong in the following aspects:

  • 25 - Since you defined char name[25], there's only room for 24 characters plus the terminating \0.
  • [^,] - Since the file data is separated by semicolons, it must be [^;].
  • ; %d - To read the integer part into I_D, the N before must be consumed.

Corrected:

        sscanf(line, "%24[^;];N%d;%d;%d;%d;%d;%c",
Armali
  • 18,255
  • 14
  • 57
  • 171