Search code examples
cstructvisual-studio-codereturn-type

Error checking attempt, how would I fix this?


For a homework assignment I was tasked with adding error checks to code. I have two left: one I understand what I need to write an error check for, but cannot get it to work, the other I haven't found what to check for yet.

I've tried changing the return type of read_edge to allow use of return 0; to end the function when finding an error, but this resulted in g.edges receiving wrong types. I've also tried setting the error check just before main calls read_edge on a test 'edge' struct, but it had no effect on catching the error.

typedef int vertex;

typedef struct {
    vertex source;
    vertex target;
    float weight;
} edge;

typedef struct {
    int n;
    int m;
    vertex* vertices;
    edge* edges;
} graph;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
edge read_edge(FILE* file) {
    edge e;
        if (fscanf(file, "%d %d %f", &e.source, &e.target, &e.weight) != 3){
        printf("Error: Expected an Integer and/or Float\n");
        return 0;
    }
    fscanf(file, "%d %d %f", &e.source, &e.target, &e.weight);
    return e;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

and this bit is the part of main that calls read_edge:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    graph g = create_graph(n, m);

    for (int i = 0; i < m; i++) {
        // missing error check 
        g.edges[i] = read_edge(file);
    }

    printf("%d %d\n", g.n, g.m);

    return 0;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Clearly this will get compilation errors because of me trying to return 0; in a return type of 'edge' but I'm not sure how to allow this to happen.


Solution

  • Change the functions so that they return an int, and take a pointer to the struct to be filled in as a parameter.

    Also, you shouldn't call fscanf() twice. The second call will try to read the next structure from the file, not reread what you read when you were testing the result.

    int read_edge(FILE* file, edge *e) {
        if (fscanf(file, "%d %d %f", e->source, e->target, e->weight) != 3){
            printf("Error: Expected two integers and float\n");
            return 0;
        }
        return 1;
    }
    

    In the caller, instead of

    e = read_edge(f);
    

    you use something like

    int success = read_edge(f, &e);
    

    So the other function would be:

    for (int i = 0; i < m; i++) {
        int success = read_edge(file, &g.edges[i]);
        if (!success) {
            break;
        }
    }