当使用动态结构数组时,我的 realloc 函数只执行一次 realloc

My realloc function is doing realloc only once when working with a dynamic array of structs

我有一个函数 leerArch() 可以读取包含学生信息的文件和 returns 指向 structs t_alumno.

的动态数组的指针

但是当我进行调试时,似乎除了 realloc 函数之外一切正常。指针*arrDin只改变了一次,然后就没有再改变。

当我打印我的动态数组时,我得到了元素的数量和学生的 id,但是名字和姓氏只是我数组中每个元素的最后一个学生。

所以我怀疑我的 realloc 函数没有正常工作,因为在多次调试和检查我的代码后我找不到任何其他可能导致这个问题的缺陷。

这是我的结构:

typedef struct alumno{
    int nro_registro;
    char *nombre;
    char *apellido;
}t_alumno;

这是我的函数,这个函数读取文件和 returns struct alumno:

的动态数组
t_alumno *leerArch(char *nomArch){
    int r,i,legajo,j;
    char c;
    char *nombre = malloc(1);
    char *apellido = malloc(1);
    t_alumno *arrDin = malloc(sizeof(t_alumno));

    //reading file
    //rach line has: 123456,name,surname
    FILE *arch = fopen(nomArch,"r");
    r = fscanf(arch,"%d,",&legajo);
    for (i=0; r!= EOF; i++){
        //writing name in a string
        c = fgetc(arch);
        for(j=0; c!=',' && c != EOF; j++){
            *(nombre+j) = c;
            nombre = realloc(nombre,j+2);
            c = fgetc(arch);
        }
        c = fgetc(arch);
        *(nombre+j) = '[=11=]';
        //writing surname in a string
        for(j=0;  c != EOF && c!='\n'; j++){
            *(apellido+j) = c;
            apellido = realloc(apellido,j+2);
            c = fgetc(arch);
        }
        *(apellido+j) = '[=11=]';
        //adding element to my array. I suspect this realloc doesn't work properly
        (arrDin+i)->nro_registro = legajo;
        (arrDin+i)->nombre = nombre;
        (arrDin+i)->apellido = apellido;
        arrDin = realloc(arrDin,(i+2)*sizeof(t_alumno));

        r = fscanf(arch,"%d,",&legajo);
    }
    //adding an ending element
    (arrDin+i)->nro_registro = 0;
    (arrDin+i)->nombre = "void";
    (arrDin+i)->apellido = "void";

    fclose(arch);

    return arrDin;
}

我的文件有:

170022,Juan,Rodriguez
170050,Maria,Perez
170125,Lorena,Ledesma
170245,Tomas,Garcia

打印这个数组时的输出是:

{170022,Tomas,Garcia}
{170050,Tomas,Garcia}
{170125,Tomas,Garcia}
{170245,Tomas,Garcia}

打印功能:

void imprimirArr(t_alumno *arrDin){
    int i;
    for(i=0; (arrDin+i)->nro_registro != 0; i++){
        printf("\n{%d,%s,%s}",(arrDin+i)->nro_registro,(arrDin+i)->nombre,(arrDin+i)->apellido);
    }
}

我刚刚发现我的错误。所以基本上我放入数组的 char* 指针被一遍又一遍地替换,因为我们在这里使用指针,所以我在再次写入字符串之前添加了一个新的 malloc 这样我们就得到了新的 char指针并得到修复。

t_alumno *leerArch(char *nomArch){
    int r,i,legajo,j;
    char c;
    char *nombre;
    char *apellido;
    t_alumno *arrDin = malloc(sizeof(t_alumno));

    //reading file
    //rach line has: 123456,name,surname
    FILE *arch = fopen(nomArch,"r");
    r = fscanf(arch,"%d,",&legajo);
    for (i=0; r!= EOF; i++){
        //writing name in a string
        c = fgetc(arch);
        nombre = malloc(1);
        for(j=0; c!=',' && c != EOF; j++){
            *(nombre+j) = c;
            nombre = realloc(nombre,j+2);
            c = fgetc(arch);
        }
        c = fgetc(arch);
        *(nombre+j) = '[=10=]';
        //writing surname in a string
        apellido = malloc(1);
        for(j=0;  c != EOF && c!='\n'; j++){
            *(apellido+j) = c;
            apellido = realloc(apellido,j+2);
            c = fgetc(arch);
        }
        *(apellido+j) = '[=10=]';
        //adding element to my array. I suspect this realloc doesn't work properly
        (arrDin+i)->nro_registro = legajo;
        (arrDin+i)->nombre = nombre;
        (arrDin+i)->apellido = apellido;
        arrDin = realloc(arrDin,(i+2)*sizeof(t_alumno));

        r = fscanf(arch,"%d,",&legajo);
    }
    //adding an ending element
    (arrDin+i)->nro_registro = 0;
    (arrDin+i)->nombre = "void";
    (arrDin+i)->apellido = "void";

    fclose(arch);

    return arrDin;
}

问题是您经常对“apellido”和“nombre”使用相同的指针。 因此,在两个 for 循环中,您都在更改字符,但指针仍然相同。

您必须以这种方式使用 strdup 函数复制您的指针

(arrDin+i)->nombre = strdup(nombre);
(arrDin+i)->apellido = strdup(apellido);

但是,我不知道您目前是否正在学习 C 语言,但是您可以使用 getline 和 strsep 函数做得比您在这里所做的更好,这里是示例代码:

void print_alumnos(t_alumno **arrDin)
{
    for (size_t i = 0; arrDin[i] != NULL; i++) {
        printf("{%d, %s, %s}\n", arrDin[i]->nro_registro, arrDin[i]->nombre, arrDin[i]->apellido);
    }
}

char **split_line(char *line)
{
    char **splited_line = NULL;
    char *token = NULL;
    size_t i = 0;

    while ((token = strsep(&line, ",")) != NULL) {
        splited_line = realloc(splited_line, sizeof(char *) * (i + 2));
        splited_line[i] = strdup(token);
        splited_line[++i] = NULL;
    }
    return splited_line;
}

FILE *open_file(char *filename)
{
    FILE *filestream = NULL;

    if (!filename) {
        return NULL;
    }
    filestream = fopen(filename, "r");
    if (filestream == NULL) {
        return NULL;
    }
    return filestream;
}

struct alumno **read_file(char *filename)
{
    FILE *filestream = open_file(filename);
    char *line = NULL;
    char *tmp_ptr = NULL;
    char **splited_line = NULL;
    size_t i = 0;
    size_t nread = 0;
    struct alumno **alumnos = NULL;

    if (filestream == NULL)
        return NULL;
    while (getline(&line, &nread, filestream) > 0) { // getting line by line
        tmp_ptr = line;
        if (line[strlen(line) - 1] == '\n') {
            line[strlen(line) - 1] = '[=11=]'; // delete \n because getline is keeping it
        }
        splited_line = split_line(line);
        alumnos = realloc(alumnos, sizeof(struct alumno *) * (i + 2));
        alumnos[i] = malloc(sizeof(struct alumno));
        alumnos[i]->nro_registro = atoi(splited_line[0]);
        alumnos[i]->apellido = splited_line[1];
        alumnos[i]->nombre = splited_line[2];
        alumnos[++i] = NULL;
        free(tmp_ptr);
        line = NULL;
        nread = 0;
    }
    fclose(filestream);
    return alumnos;
}

int main(void)
{
    struct alumno **alumnos = read_file("test.txt");

    print_alumnos(alumnos);
    return 0;
}