【问题标题】:Array elements are "lost" outside the function数组元素在函数外“丢失”
【发布时间】:2020-01-07 01:29:09
【问题描述】:

我在文件中有一个矩阵,例如:

3
1 2 3
4 5 6
7 8 -9

其中第一行表示方阵顺序。我正在使用以下代码读取文件并将其存储到向量中(为简单起见,我删除了所有 if 检查):

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

int read_matrix_file(const char *fname, double *vector)
{
    /* Try to open file */
    FILE *fd = fopen(fname, "r");
    char line[BUFSIZ];
    fgets(line, sizeof line, fd);

    int n;
    sscanf(line, "%d", &n)

    vector = realloc(vector, n * n * sizeof *vector);
    memset(vector, 0, n * n * sizeof *vector);

    /* Reads the elements */
    int b;
    for(int i=0; i < n; i++) {
        // Read the i-th line into line
        if (fgets(line, sizeof line, fd) == NULL) {
            perror("fgets");
            return(-1);
        }

        /* Reads th j-th element of i-th line into the vector */
        char *elem_ptr = line;
        for (int j=0; j < n; j++) {
            if(sscanf(elem_ptr, "%lf%n", &vector[n*i+j] , &b) != 1) {
                perror("sscanf");
                return(1);
            }
            elem_ptr += b;
        }
    }
    fclose(fd);

    /* HERE PRINTS OK */
    for(int i=0; i<n*n; i++)
        printf("%i %f\n",i, vector[i]);

    return n;
}

read_matrix_file 接收文件名和doublesarray 并填充数组,返回矩阵顺序。在此代码块中可以看到预期的用法。

int main(void)
{

    const char *fname = "matrix.txt";
    double *vector = malloc(sizeof * vector);

    int n = read_matrix_file(fname, vector);

    /* Here prints junk */
    for(int i=0; i<n*n; i++)
        printf("%i %f\n",i, vector[i]);

    free(vector);
}

问题是,printfread_matrix_file 中工作正常,但在 main 中似乎无效。

我在函数外部分配数组并通过“引用”传递它,但我非常怀疑realloc,不幸的是我不知道如何修复或更好的方法。

【问题讨论】:

  • Google 更新 C 函数中的指针 - 您需要通过 ** 传递向量。
  • 请记住,在 C 中,所有参数都是按值传递。这意味着它们的值被复制到函数的局部参数变量中。修改副本(例如分配给它)不会修改原始副本。请做一些关于在 C 中模拟通过引用传递的研究
  • 另外请注意,您永远不应该将指针分配回您传递给realloc 的指针。如果realloc 失败并返回空指针,那么您将丢失原始指针并发生内存泄漏。
  • 什么是start?应该是elem_ptr

标签: c pointers malloc realloc


【解决方案1】:

您正在read_matrix_file() 内重新分配内存,并将矩阵的元素存储在该内存区域中。但是当你从函数中出来时,由于指针vector是一个局部变量,所以当你离开函数时,它的新值就丢失了。

当您回到 main() 内部时,vector 仍然指向您之前使用 malloc() 分配的(现在可能无效的)内存区域。

您应该在调用 read_matrix_file 之前分配足够大的内存,或者如果您想修改指针并在 main() 中看到反映的更改,请传递一个双指针 (**)

我的意思是这样的:

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

int read_matrix_file(const char *fname, double **p_vector)
{
    /* Try to open file */
    FILE *fd = fopen(fname, "r");
    char line[BUFSIZ];
    fgets(line, sizeof line, fd);

    int n;
    sscanf(line, "%d", &n);

    *p_vector = realloc(*p_vector, n * n * sizeof **p_vector);
    double *vector = *p_vector;

    memset(vector, 0, n * n * sizeof *vector);

    /* Reads the elements */
    int b;
    for(int i=0; i < n; i++) {
        // Read the i-th line into line
        if (fgets(line, sizeof line, fd) == NULL) {
            perror("fgets");
            return(-1);
        }

        /* Reads th j-th element of i-th line into the vector */
        char *elem_ptr = line;
        for (int j=0; j < n; j++) {
            if(sscanf(elem_ptr, "%lf%n", &vector[n*i+j] , &b) != 1) {
                perror("sscanf");
                return(1);
            }
            elem_ptr += b;
        }
    }
    fclose(fd);

    /* HERE PRINTS OK */
    for(int i=0; i<n*n; i++)
        printf("%i %f\n",i, vector[i]);

    return n;
}

在 main 中,调用它:

int n = read_matrix_file(fname, &vector);

编辑:请注意,此代码无法正确处理 realloc() 的失败。

【讨论】:

  • 传递** 我该如何处理重新分配?问题是,在读取文件之前我不知道我的矩阵有多大。还有其他更好的策略吗?
  • @Lin 你处理大小的方法和以前一样。而不是vector,您需要使用*vector
  • 我想你在realloc第一个参数中错过了*p_vector
  • 只是好奇,你为什么在主函数中使用malloc分配内存,然后在函数中使用realloc?为什么不把malloc 放在read_matrix_file 里面?
  • 为什么不在被调用函数中使用'malloc()'?因为需要保留(vector 中已设置的值),realloc() 将保留这些值
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 1970-01-01
  • 1970-01-01
  • 2018-05-07
相关资源
最近更新 更多