rawwwrrrr2228
rawwwrrrr2228

Reputation: 35

Not printing grades as a 2d array

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

void getGrades(FILE *ifp, int assigns, int stus, int grades[assigns][stus]);
void printGrades(int assigns, int stus, int grades[assigns][stus]);

int main(int argc, char *argv[])
{

    int assigns = 0;
    int stus = 0;
    int grades[assigns][stus];

    // command line arg. error checking
    if (argc != 2)
    {
        printf("Syntax Error: ./<exec> <file>\n");
        exit(1);
    }
    // file handle = open("infile.txt", read)
    FILE *ifp = fopen(argv[1], "r");
    if (ifp == NULL){
        printf("Could not open %s for reading!\n", argv[1]);
        exit(1);
    }
    fscanf(ifp, "%d%d", &assigns, &stus); // it does scan in 8 and 5 correctly
    // print debugging check
    // printf("assigns == %d\nstus == %d", assigns, stus);

    getGrades(ifp, assigns, stus, grades);
    printGrades(assigns, stus, grades);
    return 0;
}

void getGrades(FILE *ifp, int assigns, int stus, int grades[assigns][stus])
{
    int i = 0, j = 0;
    // iterate through all of the rows & columns
    for (i = 0; i < assigns; ++i){
        for (j = 0; i < stus; ++j){
           fscanf(ifp, "%d", &grades[i][j]);
        }
    }
}

void printGrades(int assigns, int stus, int grades[assigns][stus])
{
    int i = 0, j = 0;
    for (i = 0; i < assigns; ++i){
        for (j = 0; j < stus; ++j){
            printf("%10d", grades[i][j]);
        }
        printf("\n");
    }
}

input file looks like this:

8 5 100 92 84 76 68 99 91 83 75 67 98 90 82 74 66 97 89 81 73 65 96 88 80 72 64 95 87 79 71 63 94 86 78 70 62 93 85 77 69 0

and I simply want the output to look like this

   100        92        84        76        68
    99        91        83        75        67
    98        90        82        74        66
    97        89        81        73        65
    96        88        80        72        64
    95        87        79        71        63
    94        86        78        70        62
    93        85        77        69         0

I don't know where I'm making an error in the code for my program to not print that output.

The size is dynamic since the rows and columns can change in the input file. Right now the row in the input file is 8 and the column is 5.

Upvotes: 2

Views: 62

Answers (3)

Fe2O3
Fe2O3

Reputation: 8364

This is a simple text processing problem. The input is a series of fields separated by whitespace. The first field (rows) may be incorrect and should be ignored. The second field (cols) specifies the # of columns on each output line.

The following gives the desired output (using a compile time string instead of file access for clarity.)

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

char inStr[] =
    "8 5 "
    "100 92 84 76 68 99 91 83 75 67 98 90 82 74 66 97 "
    "89 81 73 65 96 88 80 72 64 95 87 79 71 63 94 86 78 70 62 93 85 77 69 0";

int main() {
    int cnt = -1, cols = 0; // initialise so that 1st data element is numbered 1

    for( char *t = inStr; (t = strtok( t, " " ) ) != NULL; t = NULL, cnt++ ) {

        if( cnt == -1 ) continue; // don't believe # of rows. data is data.

        if( cnt ==  0 ) { cols = atoi( t ); continue; } // useful info

        printf( "%8s%s", t, ((cnt%cols) == 0) ? "\n" : "" );
    }
    return 0;
}

In fact, there can be even less code involved. Sprinkle a few LFs into the source data (as fgets() would return) and it still works.

char inStr[] =
    "8 5 "
    "100 92 84 76 68 99 91 83\n75 67 98 90 82 74 66 97 "
    "89 81 73 65 96\n88 80 72 64\n95 87 79 71 63 94 86 78 70 62 93 85 77 69 0\n";

int main() {
    int cnt = -1, cols = 0; // bias making 1st data element numbered 1

    for( char *t = inStr; (t = strtok( t, " \n" ) ) != NULL; t = NULL, cnt++ )
        if( cnt <= 0 )
            cols = atoi( t ); // 1st (#rows) is junk, 2nd (#cols) is useful
        else
            printf( "%8s%c", t, " \n"[!(cnt%cols)] );

    if( (cnt-1)%cols ) // when data doesn't complete final row
        putchar( '\n' );

    return 0;
}

Upvotes: 2

user9706
user9706

Reputation:

Here are the issues with your code:

  1. typo in getGrades() cause the function to not terminate. i < stus should be j < stus.
  2. undefined behavior to allocate int grades[assigns][stus] with assigns == 0 and stus == 0. It triggers a segfault once you fix the above for me. Move the definition till after assigns and stus have been read it. Also, VLAs blow up badly if too large so consider using malloc() instead where you can at least catch a failed memory allocation.
  3. fscanf() may fail in which case your variables are not set.
  4. fclose() your file handle.
  5. (minor) reduce scope of variables
  6. (minor) It's a bit odd that you use both return and exit from main. I changed it to return.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define NAME_LENGTH 10

void getGrades(FILE *ifp, int assigns, int stus, int grades[assigns][stus]) {
    // iterate through all of the rows & columns
    for (int i = 0; i < assigns; ++i){
        for (int j = 0; j < stus; ++j){
            if(fscanf(ifp, "%d", &grades[i][j]) != 1) {
                printf("fscanf failed\n");
                return;
            }
        }
    }
}

void printGrades(int assigns, int stus, int grades[assigns][stus]) {
    for (int i = 0; i < assigns; ++i){
        for (int j = 0; j < stus; ++j){
            printf("%10d", grades[i][j]);
        }
        printf("\n");
    }
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Syntax Error: ./<exec> <file>\n");
        return 1;
    }
    FILE *ifp = fopen(argv[1], "r");
    if (ifp == NULL) {
        printf("Could not open %s for reading!\n", argv[1]);
        return 1;
    }
    int assigns = 0;
    int stus = 0;
    if(fscanf(ifp, "%d%d", &assigns, &stus) != 2) {
        printf("fscanf of assigns and stus failed\n");
        fclose(ifp);
        return 1;
    }
    int grades[assigns][stus];
    getGrades(ifp, assigns, stus, grades);
    fclose(ifp);
    printGrades(assigns, stus, grades);
    return 0;
}

and it now outputs:

       100        92        84        76        68
        99        91        83        75        67
        98        90        82        74        66
        97        89        81        73        65
        96        88        80        72        64
        95        87        79        71        63
        94        86        78        70        62
        93        85        77        69         0

Upvotes: 2

Jerry Jeremiah
Jerry Jeremiah

Reputation: 9643

The problem with your code is:

    int assigns = 0;
    int stus = 0;
    int grades[assigns][stus];

What is the size of this array? Later you change the values of assigns and stus but the array has already been created by then.

You should only create the array AFTER you have values for assigns and stus. If you move it down to after the fscanf that reads those values it works: https://onlinegdb.com/UIWe4ZZh5

Upvotes: 2

Related Questions