Question

J'ai ce problème de programmation défensive que je ne sais pas vraiment comment résoudre.

J'ai cette fonction qui prend le chemin du fichier et la taille de la table (nombre de lignes / colonnes) comme arguments et je recherche une meilleure façon de valider le fichier d'entrée. Je suppose que les arguments de cette fonction sont toujours corrects. size représente le "petit côté" de la table qui est stockée dans le fichier:

Par exemple:

1 2 3 4 
5 6 7 8 

taille= 2 est correct alors que

1 2 3 4 5
5 6 7 8 9

taille= 2 est incorrect

J'aimerais également pouvoir rejeter les fichiers comme celui-ci

1 2 3 4 5 6 7 8

size= 2 (qui est accepté via fscanf)

Un autre type de fichier que j'aimerais pouvoir rejeter est

1 2 3
4 5 6

taille= 2

Pour l'instant, ma seule sécurité est de vérifier si les éléments du fichier sont vraiment des nombres.

Voici le code que j'ai fait jusqu'à présent:

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

Je ne sais pas vraiment par où et comment commencer, je ne suis pas vraiment compétent en C et il semble exister beaucoup de fonctions et de mécanismes pour faire ce que je veux mais ils semblent tous très complexes et certains sont en fait plus longs que le code que j'ai fourni.

Si quelqu'un peut m'indiquer la bonne direction, ce serait formidable.

Était-ce utile?

La solution

Votre boucle for pourrait ressembler à ceci:

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;
    }
}

Notez également que assert(data); doit être remplacé par quelque chose comme ceci:

if (!data)
{
    printf("Error while openning the file [filePath=\"%s\"].\n", filePath);
    cleanExit();
}

Autres conseils

Vous ne pouvez pas détecter facilement les fins de lignes dans scanf(), donc l'utiliser directement ne répondra pas à vos critères.

Vous devez probablement lire des lignes entières (fgets() ou peut-être getline()), puis traiter chaque ligne à son tour.Le traitement de ligne peut utiliser sscanf(), et vous pouvez également utiliser la directive %n.Dans les grandes lignes, cela se résume à:

for (line_num = 0; line_num < size; line_num++)
{
    ...read line from file into buffer line, checking for EOF...
    start = line;
    for (i = 0; i < 2 * size; i++)
    {
        if (sscanf(start, "%f%n", &value, &offset) != 1)
            ...ooops - short line or non-numeric data...
        else
        {
            start += offset;
            table[line_num][i] = value;
        }
    }
}
...check that there's no clutter after the last expected line...

Vous pouvez également calculer une somme de contrôle du fichier entier.La question est de savoir dans quelle mesure vous êtes sérieux.Il est facile de créer une somme de contrôle xor, mais ce n'est pas vraiment sûr contre les collisions.Le mieux est probablement d'utiliser quelque chose comme sha-1 si c'est important.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top