如何将函数内的2D数组返回到C中的main

时间:2016-10-17 15:30:11

标签: c arrays multidimensional-array return

我读了一个文本文件并将内容存储在一个名为H的2D数组中,我需要将这个2D数组以某种方式返回到main,所以我可以在那里使用它并将其传递给其他函数。我不知道如何让返回工作,也许使用指针。我将readTxtFile函数设置为void函数来测试文件读取是否正常(它确实如此)但我无法对函数外部的2D数组执行任何操作。我有两个函数getRows()和getCols(),我没有在这里显示,但我可以,如果需要的话。

到目前为止我的代码:

int main(void){

    //  int *H;
    //  H = readTxtFile("H.txt");
    readTxtFile("H.txt");
    return 0;
}

void readTxtFile(char *filename){
    int rows, cols;
    FILE *fp = fopen(filename, "r");
    if (!fp){
        perror("can't open H.txt\n");
        //return EXIT_FAILURE;
    }
    rows = getRows(fp);
    cols = getCols(fp);
    int (*H)[cols] = malloc(sizeof(int[rows][cols]));
    if(!H){
        perror("fail malloc\n");
        exit(EXIT_FAILURE);
    }

    for(int r = 0; r < rows; ++r){
        for(int c = 0; c < cols; ++c){
            if(EOF==fscanf(fp, "%d", &H[r][c])){
                fprintf(stderr, "The data is insufficient.\n");
                free(H);
                exit(EXIT_FAILURE);
            }
        }
    }
    fclose(fp);

    // printH(rows,cols,H);
    //  return H;


}

这就是文本文件的样子:

1 1 0 1 0 0
0 1 1 0 1 0
1 0 0 0 1 1
0 0 1 1 0 1
2 2 2 2 2 2

任何帮助将不胜感激

3 个答案:

答案 0 :(得分:3)

我要做的是根据它来定义2D数组的结构:

  • 列数
  • 行数
  • 指向内存中数组数据的指针

请注意,我会&#34;线性化&#34; 数组,即分配一个大小为Columns * Rows * sizeof(int)的内存块,并给出 i j 行和列索引,这两个索引可以用简单的数学转换为1D数组中的索引(例如index = rowIndex * Columns + columnIndex

然后,我只是从ReadTxtFile函数返回一个指向这个结构的指针:

struct IntArray2D {
    int Rows;
    int Columns;
    int* Elements;
};

/* 
 * Define a couple of helper functions to allocate 
 * and free the IntArray2D structure. 
 */
struct IntArray2D* IntArray2D_Create(int rows, int columns);
void IntArray2D_Free(struct IntArray2D* array);

/* 
 * On success, returns a 2D array with data read from file.
 * On failure, returns NULL.
 * NOTE: callers must call IntArray2D_Free() when done 
 */
struct IntArray2D* ReadTxtFile(const char* filename);

编辑作为替代方案,你可以定义数组结构有一个带行和列的标题块,立即后跟&#34;线性化&#34 ; 2D数组元素,使用 "flexible array member"

struct IntArray2D {
    int Rows;
    int Columns;
    int Elements[];
};

然后,您可以定义一些方便的函数来操作此自定义数组结构,例如:

struct IntArray2D* IntArray2D_Create(int rows, int columns)
{
    /* Check rows and columns parameters are > 0 */
    /* ... */

    struct IntArray2D *p = malloc(sizeof(struct IntArray2D)
                                  + rows * columns * sizeof(int));
    if (p == NULL) {
        return NULL;
    }

    p->Rows = rows;
    p->Columns = columns;

    /* May zero out the array elements or not... */
    memset(p->Elements, 0, rows * columns * sizeof(int));

    return p; 
}

void IntArray2D_Free(struct IntArray2D* array)
{
    free(array);
}

int IntArray2D_GetElement(struct IntArray2D* array, 
                                 int row, int column)
{
    /* Check array is not NULL; check row and column 
       indexes are in valid ranges ... */

    int index = row * (array->Columns) + column;
    return array->Elements[index];
}

void IntArray2D_SetElement(struct IntArray2D* array, 
                                  int row, int column,
                                  int value)
{
    /* Check array is not NULL; check row and column 
       indexes are in valid ranges ... */

    int index = row * (array->Columns) + column;
    array->Elements[index] = value;
}

ReadTxtFile功能中,您可以拨打malloc,而不是致电IntArray2D_Create

struct IntArray2D* ReadTxtFile(const char* filename) 
{ 
    struct IntArray2D* data = NULL;

    /* ... */

    rows = getRows(fp);
    cols = getCols(fp);
    data = IntArray2D_Create(rows, cols);
    if (data == NULL) {
        /* Handle error ... */ 
        return NULL;
    }

    /* Fill the array ... */

特别是你的:

if(EOF==fscanf(fp, "%d", &H[r][c])){

你可以这样做:

    /* int valueReadFromFile */
    if (EOF == fscanf(fp, "%d", &valueReadFromFile)) {
        fprintf(stderr, "The data is insufficient.\n");
    }      
    IntArray2D_SetElement(data, r, c, valueReadFromFile);

然后在函数结束时,您可以:

    return data;
}

答案 1 :(得分:0)

您无法从函数返回数组;返回指向数组的指针。

当然,您可以在任何函数(即“global”)之外创建一个数组(或指向数组的指针),并从同一模块中的任何其他函数(甚至是同一个程序)访问它使用extern关键字),但我不建议您这样做。最好遵循第一个方法。

答案 2 :(得分:0)

一种方法是将行数和列数返回给调用者以及指向数组本身的指针(我还没有尝试编译这个......):

int main(void){

    //  int *H;
    //  H = readTxtFile("H.txt");
    int rows;
    int cols;
    void *array;
    readTxtFile("H.txt",&rows,&cols,&array);

    int (*H)[*cols] = array;

    /* process array here */

    free(array);

    return 0;
}

void readTxtFile(char *filename, int *rows, int *cols, void **array ){
    int rows, cols;
    FILE *fp = fopen(filename, "r");
    if (!fp){
        perror("can't open H.txt\n");
        //return EXIT_FAILURE;
    }
    *rows = getRows(fp);
    *cols = getCols(fp);
    int (*H)[cols] = malloc(sizeof(int[*rows][*cols]));
    if(!H){
        perror("fail malloc\n");
        exit(EXIT_FAILURE);
    }

    for(int r = 0; r < rows; ++r){
        for(int c = 0; c < cols; ++c){
            if(EOF==fscanf(fp, "%d", &H[r][c])){
                fprintf(stderr, "The data is insufficient.\n");
                free(H);
                exit(EXIT_FAILURE);
            }
        }
    }
    fclose(fp);

    /* cast is not necessary - added to clearly indicate that the
       pointer returned carries no row/column information with it */
    *array = ( void * ) H;
}

@ Mr.C64&#39的回答基本上是一样的,我认为这是一种更清洁的方式。