Question

I want to dynamicly construct a matrix in C from a text document using a function. I ran into problems when making the matrix using calloc and probably when giving the values to the matrice elements, and I couldn't find anything. I can handle a vector.

Code here:

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

void beolvas_ellista(int *, int *, int *, int *, int ***, char *);

int main()
{
    int ir, suly, csom, el, i, **ellista;

    //The following commented code works
    /*FILE * f;
    f=fopen("be.txt","r");

    fscanf(f,"%d",&ir);
    fscanf(f,"%d",&suly);
    fscanf(f,"%d",&csom);
    fscanf(f,"%d",&el);

    ellista=(int **)calloc(2,sizeof(int *));
    for(i=0;i<el;++i)
    {
        ellista[i]=(int *)calloc(el,sizeof(int));
    }
    i=0;
    while(!feof(f))
    {
        fscanf(f,"%d",&ellista[0][i]);
        fscanf(f,"%d",&ellista[1][i]);
        ++i;
    }

    for(i=0;i<el;++i)
        printf("%d %d\n",ellista[0][i],ellista[1][i]);

    fclose(f);*/

    beolvas_ellista(&ir, &suly, &csom, &el, &ellista, "be.txt");

    for(i=0;i<el;++i)
        printf("%d %d\n",ellista[0][i],ellista[1][i]);

    return 0;
}

void beolvas_ellista(int *ir, int *suly, int *csom, int *el, int ***ellista, char *allomany)
{
    int i;
    FILE * f;
    f=fopen(allomany,"r");

    fscanf(f,"%d",ir);
    fscanf(f,"%d",suly);
    fscanf(f,"%d",csom);
    fscanf(f,"%d",el);

    *ellista=(int **)calloc(2,sizeof(int *));
    for(i=0;i<*el;++i)
    {
        *ellista[i]=(int *)calloc(*el,sizeof(int));
    }

    i=0;
    while(!feof(f))
    {
        fscanf(f,"%d",ellista[0][i]);
        fscanf(f,"%d",ellista[1][i]);
        ++i;
    }

    fclose(f);
}

Here is the text file:

be.txt

0 0
7 8
1 2
1 3
2 3
3 4
4 5
4 6
5 7
6 7

Also here is the code that I used to gather information:

void beolvas(int*pn, int**pa, char*allomany)
{
int i;FILE*f;
f=fopen(allomany,"r");
fscanf(f,"%d",pn);
*pa=(int*)malloc((*pn)*sizeof(int));
for(i=0; i<*pn; i++)
fscanf(f,"%d",(*pa)+i);
fclose(f);
}
main()
{
int n, *a;
beolvas(&n, &a, "be.txt");
...
}
Was it helpful?

Solution

The following bullet-list the items wrong in your function.

  • You're incorrectly using feof() as the break condition of your while loop. See this question for more information.

  • You ignore the return result of fscanf() and with that thereby have no assurance at all the parameter parsing succeeded or not. See the documentation of fscanf().

  • Your code does not fit the model of the file content. The file, according to your code, should set ir, suly, csom, and el to values 0, 0, 7, and 8 respectively. You then allocate space for exactly two pointers-to-int, saving the result in ellista, then proceed to index into *ellista up to el items, which is clearly not 2. It is neither clear nor evident that you want a 2xN matrix or an Nx2 matrix when this is finished, and the code as-written does neither correctly.

  • Stylistic, but helpful: You should be setting your out-parameters on success of your function, not on initial entrance or parse. Eg: Your ellista by-address parameter should be set as the last operation, not the first, based on the success of the function. Declare a local int** local; temp var, run your algorithm populating that, and upon success set the out-parameter.

All of that said, I think you want a 2xN matrix, and if so, the code below will do that. Note this does not check the results of the malloc and calloc calls, which i leave to you. This function will return zero (0) on success, non-zero on failure :

int beolvas_ellista(int *ir, int *suly, int *csom, int *el, int ***ellista, const char *allomany)
{
    FILE * f = fopen(allomany,"r");
    int ** local =  NULL;
    int i, res = -1;

    if (f == NULL)
        return res;

    if (fscanf(f,"%d",ir) == 1 &&
        fscanf(f, "%d",suly) == 1 &&
        fscanf(f,"%d",csom) == 1 &&
        fscanf(f,"%d",el) == 1)
    {
        // allocate two pointers, then in those two pointers, allocate
        //  space for *el integers.
        local = malloc(2 * sizeof(*local));
        local[0] = calloc(*el, sizeof(*(local[0])));
        local[1] = calloc(*el, sizeof(*(local[0])));

        for (i=0; i<*el; ++i)
        {
            if (fscanf(f, "%d", local[0]+i) != 1 ||
                fscanf(f, "%d", local[1]+i) != 1)
                break;
        }

        // only if i == *el did we finish the above
        if (i == *el)
        {
            *ellista = local;
            res = 0;
        }
        else
        {   // failed to read file content. free up memory
            // and return error state.
            free(local[0]);
            free(local[1]);
            free(local);
        }
    }
    fclose(f);
    return res;
}

OTHER TIPS

Your input file does not fit the code. You say in your input file *el = 8. In your code you take this as row count, but actually only spending 2 rows to the matrix in your first calloc call...

P.S. Try this instead:

Edit: Wrong analyse by me. Your actual problem is a predecence one. You need to dereference your * in the right way with brackets set, like so:

void beolvas_ellista(int *ir, int *suly, int *csom, int *el, int ***ellista, char *allomany)
{
    int i;
    FILE * f;
    f=fopen(allomany,"r");

    fscanf(f,"%d",ir);
    fscanf(f,"%d",suly);
    fscanf(f,"%d",csom);
    fscanf(f,"%d",el);


    *ellista=(int **)calloc(2,sizeof(int *));
    for(i=0;i<*el;++i)
    {
        (*ellista)[i]=(int *)calloc(*el,sizeof(int));

    }



    i=0;

    while(!feof(f))
    {
        fscanf(f,"%d",&((*ellista)[0][i]));
        fscanf(f,"%d",&((*ellista)[1][i]));
        ++i;
    }

    fclose(f);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top