I have this defensive-programming issue that I don't really know how to solve.
I have this function that takes file path and size of table (rows / columns count) as arguments and I'm looking for better way of validating the input file. I assume that arguments of this function are always correct. size
represents the "smaller side" of the table that is stored in file:
For example :
1 2 3 4
5 6 7 8
size = 2 is correct while
1 2 3 4 5
5 6 7 8 9
size = 2 is incorrect
I'd also like to be able to reject the files like this
1 2 3 4 5 6 7 8
size = 2 (which is accepted through fscanf)
Another type of file I'd like to be able to reject is
1 2 3
4 5 6
size = 2
As for now my only security is checking if the elements of the file are really numbers.
Here is the code I've done so far :
void import(float** table, int size, char* path)
{
FILE* data = fopen(path, "r");
assert(data);
int i,j;
int st;
for (i=0; i<size; i++)
{
for(j=0; j<(size*2)-1; j++)
{
st = fscanf(data, "%f", &table[i][j]);
if (!st)
{
printf("Error while importing the file.\n");
fclose(data);
return -1;
}
}
}
fclose(data);
}
I don't really where and how to start, I'm not really proficient in C and there seems to exist a lot of functions and mechanisms to do what I want but they all seem very complex and some are actually longer than the code I provided.
If anyone can point me in the right direction that'd be great.
Your for loop could look like this:
char line[1000], *token;
for (i = 0; i < size; i++) // for each line
{
if (fgets(line, 1000, data) != NULL) // read line
{
token = strtok (line," ");
for (j = 0; j < (size * 2) - 1; j++) // for each number from line
{
if (sscanf(token, "%f", &table[i][j]) <= 0)
{
// there are columns missing:
printf("Error while importing the file.\n");
fclose(data);
return -1;
}
token = strtok (NULL," ");
}
}
else
{
// there are rows missing:
printf("Error while importing the file.\n");
fclose(data);
return -1;
}
}
Also note that assert(data);
should be replaced with something like this:
if (!data)
{
printf("Error while openning the file [filePath=\"%s\"].\n", filePath);
cleanExit();
}