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");
...
}
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;
}