Pregunta

Tengo este problema de programación defensiva que realmente no sé cómo resolver.

Tengo esta función que toma la ruta del archivo y el tamaño de la tabla (cuenta de filas / columnas) como argumentos y estoy buscando una mejor manera de validar el archivo de entrada. Supongo que los argumentos de esta función siempre son correctos. size representa el "lado más pequeño" de la tabla que se almacena en el archivo:

Por ejemplo :

1 2 3 4 
5 6 7 8 

tamaño = 2 es correcto mientras

1 2 3 4 5
5 6 7 8 9

tamaño = 2 es incorrecto

También me gustaría poder rechazar los archivos como este

1 2 3 4 5 6 7 8

tamaño = 2 (que se acepta a través de FSCANF)

Otro tipo de archivo que me gustaría poder rechazar es

1 2 3
4 5 6

tamaño = 2

Por ahora, mi única seguridad es verificar si los elementos del archivo son realmente números.

Aquí está el código que he hecho hasta ahora:

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

Realmente no estoy donde y cómo comenzar, no soy realmente competente en C y parece que existen muchas funciones y mecanismos para hacer lo que quiero, pero todos parecen muy complejos y algunos son realmente más largos que el código I previsto.

Si alguien puede señalarme en la dirección correcta, sería genial.

¿Fue útil?

Solución

Tu bucle podría verse así:

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

También tenga en cuenta que assert(data); debe ser reemplazado por algo como esto:

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

Otros consejos

No puedes detectar fácilmente los extremos de las líneas en scanf(), entonces, usar eso directamente no cumplirá sus criterios.

Probablemente necesite leer líneas completas (fgets() o quizás getline()), y luego procese cada línea a su vez. El procesamiento de la línea puede usar sscanf(), y puedes usar el %n directiva también. En esquema, esto se reduce a:

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...

También puede calcular una suma de verificación de todo el archivo. La pregunta es qué tan grave eres al respecto. Es fácil crear una suma de verificación XOR, pero no es realmente seguro contra las colisiones. Lo mejor es probablemente usar algo como SHA-1 si es importante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top