Estoy trabajando en replicar la función load () de MATLAB para usar en una aplicación C. Tengo problemas para cargar dinámicamente los datos e inicializar las matrices que necesito. Más específicamente, estoy tratando de usar fgets con matrices que se han inicializado con calloc y no puedo hacer que funcione. La función se encuentra a continuación y se agradece la ayuda.

EDITAR: El código actualizado está debajo del siguiente ejemplo defectuoso.

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

void *load(const char *Filename);

void *load(const char *Filename)
{
    FILE* FID;
    if ((FID = fopen(Filename, "r")) == NULL)
    {
        printf("File Unavailable.\n");
    }
    else
    {
        int widthCount = 0, heightCount = 0;

        char ReadVal;
        while ((ReadVal = fgetc(FID)) != '\n')
        {
            if (ReadVal == ' ' || ReadVal == ',' || ReadVal == '\t')
            {
                widthCount++;
            }
        }

        rewind(FID);
        char* String = calloc(widthCount * 100, sizeof(char));
        while (fgets(*String, widthCount+1, FID) != EOF)
        {
            heightCount++;
        }
        double* Array = calloc(widthCount * heightCount, sizeof(double));
        rewind(FID);
        int i = 0, j = 0;
        char * pch;
        while (fgets(*String, widthCount+1, FID) != EOF)
        {
            pch = strtok(String, " ,\t");
            while (pch != NULL)
            {
                Array[i][j] = strtod(pch, NULL);
                pch = strtok (NULL, " ,\t");
                j++;
            }
            i++;
            j = 0;
        }

        fclose(FID);
        return Array;

    }

}

El código revisado: esta solución funciona para cualquiera que busque un problema similar.

void *load(const char *Filename)
{
    FILE* FID;
    if ((FID = fopen(Filename, "r")) == NULL)
    {
        printf("File Unavailable.\n");
        return NULL;
    }
    else
    {   
        int widthCount = 0, heightCount = 0;
        double *Array;
        char Temp[100];
        while ((Temp[0] = fgetc(FID)) != '\n')
        {
            if (Temp[0] == '\t' || Temp[0] == ' ' || Temp[0] == ',')
            {
                widthCount++;
            }
        }
        widthCount++;
        //printf("There are %i columns\n", widthCount);
        rewind(FID);
        while (fgets(Temp, 99, FID) != NULL)
        {
            heightCount++;
        }
        //printf("There are %i rows\n", heightCount);
        Array = (double *)calloc((widthCount * heightCount), sizeof(double));
        rewind(FID);
        int i = 0;
        while (!feof(FID))
        {

            fscanf(FID, "%lf", &*(Array + i));
            fgetc(FID);
            i++;
        }

        return Array;   
    }
}
2
Nathan Tornquist 4 abr. 2012 a las 20:40

1 respuesta

La mejor respuesta

La matriz no es una matriz 2d en lugar de Array[i][j] = strtod(pch, NULL); solo incrementa el puntero *(Array++) = strtod(pch, NULL);

2
Martin Beckett 4 abr. 2012 a las 20:42
Gracias, no lo había entendido. Mi principal problema es pasar el comando fgets. Necesito poder tomar cada fila en función del tamaño de fila que determiné en tiempo de ejecución.
 – 
Nathan Tornquist
4 abr. 2012 a las 20:44
Podría ayudar dar una muestra del formato de archivo, cómo se establece el ancho de línea etvc
 – 
Martin Beckett
4 abr. 2012 a las 20:46
No tengo el ancho de línea. Para la clase, el objetivo era que el usuario proporcionara las dimensiones de los datos para cargar. Decidí intentar cargar todos los datos sin ninguno de esos valores. Ese es el propósito de los recuentos de ancho y alto al comienzo de la función.
 – 
Nathan Tornquist
4 abr. 2012 a las 20:48
"Mi principal problema es superar el comando fgets". Y ha notado que fgets no es adecuado para el trabajo en el caso general. Bien. Si no sabe la longitud de una línea en particular antes de leerla, quiere getline o algo equivalente. A partir de 2008, getline es parte de POSIX, por lo que debería estar disponible en cualquier sistema Unixish.
 – 
dmckee --- ex-moderator kitten
4 abr. 2012 a las 20:48
1
El recuento de bytes es solo una pista, o el tamaño ya asignado, getline reasignará automáticamente la matriz para que se ajuste a los datos. Si tiene getlien, ahorrará mucho trabajo haciendo crecer la matriz y moviendo datos a medida que lee los valores. La alternativa es leer cada nuevo valor un carácter a la vez en un pequeño búfer fijo (por ejemplo, para que quepan 8 o 10 lugares decimales) y luego convertir cada uno a Array
 – 
Martin Beckett
4 abr. 2012 a las 20:56