在C语言中返回一个二维字符数组

5

我把这个东西搞了一阵子,但我真的不明白。

我想做的事情是:在函数中以2D字符数组作为输入,更改其中的值,然后返回另一个2D字符数组。

简单的想法,但在C语言中实现并不容易。

有没有什么简单的方法可以让我开始呢?谢谢。


你到目前为止尝试了什么?你不明白什么?你如何尝试定义二维数组? - David Heffernan
你知道什么是“结构体”吗? - Mooing Duck
我刚在SO上搜索了“c二维数组”,得到了很多答案。从那里开始吧。 - drdwilcox
我的平常建议:阅读 comp.lang.c FAQ 的第6节。 - Keith Thompson
6个回答

10

C语言不会从函数中返回数组。

您可以做一些相似的事情:

  • You can package your array in struct and return that. C will return structs from functions just fine. The downside is this can be a lot of memory copying back and forth:

    struct arr {
        int arr[50][50];
    }
    
    struct arr function(struct arr a) {
        struct arr result;
        /* operate on a.arr[i][j]
           storing into result.arr[i][j] */
        return result;
    }
    
  • You can return a pointer to your array. This pointer must point to memory you allocate with malloc(3) for the array. (Or another memory allocation primitive that doesn't allocate memory from the stack.)

    int **function(int param[][50]) {
        int arr[][50] = malloc(50 * 50 * sizeof int);
        /* store into arr[i][j] */
        return arr;
    }
    
  • You can operate on the array pointer passed into your function and modify the input array in place.

    void function(int param[][50]) {
        /* operate on param[i][j] directly -- destroys input */
    }
    
  • You can use a parameter as an "output variable" and use that to "return" the new array. This is best if you want the caller to allocate memory or if you want to indicate success or failure:

    int output[][50];
    
    int function(int param[][50], int &output[][50]) {
        output = malloc(50 * 50 * sizeof int);
        /* write into output[i][j] */
        return success_or_failure;
    }
    

    Or, for the caller to allocate:

    int output[50][50];
    
    void function(int param[][50], int output[][50]) {
        /* write into output[i][j] */
    }
    

哇,谢谢!我正想问如何访问结构体中数组的索引。 - Dave
你的帖子更加详尽,这就是我选择它作为答案的原因。同时非常感谢@pmg! - Dave
@pmg的帖子详细介绍了避免使用固定大小数组的机制,因此在这方面获得了额外的加分。 :) - sarnold

5

函数无法返回数组。

有几种选择:

  • 在结构体内包装数组
struct wraparray {
    int array[42][42];
};
struct wraparray foobar(void) { struct wraparray ret = {0}; return ret; }
  • 将目标数组作为指向其第一个元素的指针(及其大小),传递给函数;并更改该数组
int foobar(int *dst, size_t rows, size_t cols, const int *src) {
    size_t len = rows * cols;
    while (len--) {
        *dst++ = 42 + *src++;
    }
    return 0; /* ok */
}
// 例子 int x[42][42]; int y[42][42]; foobar(x[0], 42, 42, y[0]);
  • 更改原始数组
int foobar(int *arr, size_t rows, size_t cols) {
    size_t len = rows * cols;
    while (len--) *arr++ = 0;
    return 0; /* ok */
}

我喜欢结构体的想法。那么,我该怎么在结构体中的数组元素后追加值呢?我只需要说ret [0] [0],ret [0] [1]来实际引用该数组的索引吗? - Dave
哦,如下帖子中解决了。ret.array [i] [j]就是答案。谢谢你的帮助! - Dave
如果变量声明为 struct wrap w;,那么你应该使用 w.array[i][j]。如果它声明为 struct wrap *w;,那么你应该使用 w->array[i][j] - sarnold

1

这里有另一个例子。已经测试并且可行。

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

void test(char**,unsigned int,unsigned int);

const unsigned int sz_fld = 50 + 1;
const unsigned int sz_ffld = 10;

int main(void) {
    char fld[sz_ffld][sz_fld];
    for (unsigned char i=0;i<sz_ffld;++i) {
        strcpy(fld[i],"");
    }

    strcpy(fld[0],"one");
    strcpy(fld[1],"two");
    strcpy(fld[2],"three");

    char** pfld = malloc(sz_ffld*sizeof(char*));
    for (unsigned int i=0;i<sz_ffld;++i) {
        *(pfld+i) = &fld[i][0];
    }

    test(pfld,sz_ffld,sz_fld);

    printf("%s\n",fld[0]);
    printf("%s\n",fld[1]);
    printf("%s\n",fld[2]);

    free(pfld);

    return(0);
}

void test(char** fld,unsigned int m,unsigned int n) {
    strcpy(*(fld+0),"eleven");
    strcpy(*(fld+1),"twelve");
    return;
}

请注意以下内容:
为了编译,我使用带有C99选项的gcc。
我定义了包含两个大小信息的函数,但我编写的代码非常基础,实际上根本没有使用这些信息,只是使用了strcpy(),因此这绝对不是安全的代码(即使我展示了这种功能的“m”和“n”)。它仅仅展示了一种制作静态二维字符数组并通过指向该数组“字符串”的指针数组在函数中处理它的技巧。

1
char **foo(const char * const * bar, size_t const *bar_len, size_t len0) {
    size_t i;        
    char** arr = malloc(sizeof(char *) * len0);
    for (i = 0; i < len0; ++i) {
        arr[i] = malloc(bar_len[i]);
        memcpy(arr[i], bar[i], bar_len[i]);
    }
    /* do something with arr */
    return arr;
}

在你的代码的其他地方:

char **pp;
size_t *pl;
size_t ppl;
/* Assume pp, pl are valid */
char **pq = foo(pp, pl, ppl);
/* Do something with pq */
/* ... */
/* Cleanup pq */
{
    size_t i;
    for (i = 0; i < ppl; ++i)
        free(pq[i]);
    free(pq);
} 

因为你是通过指针而不是值传递,且想要写入输入数组,所以你必须先复制它。


0
当您将一个二维数组作为参数传递给函数时,需要明确告诉它数组第二个维度的大小。
void MyFunction(array2d[][20]) { ... }

它是50x50的。但函数不是void,它也应该返回50x50数组。 - Dave
是的,如果你正在处理实际的二维数组(即数组的数组)。问题在于它的维度在编译时被固定。为了合理的灵活性,你可能想要使用动态分配的指针数组来模拟二维数组(这需要更多的工作)。 - Keith Thompson
使用以下代码定义一个函数:int[][50] MyFunction(int[][50] array2d) { ... } - aleph_null

0
以下代码将实现您想要的功能。它将打印出"One"和"Ten"。请注意,它的数组维度精确地为10和8。
char my_array[10][8] = 
{
{"One"},
{"Two"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"Nine"},
{"Ten"},
};

void foo ( char (**ret)[10][8] )
{
  *ret = my_array;
}

void main()
{
  char (*ret)[10][8];
  foo(&ret);

  printf("%s\r\n", (*ret)[0] )
  printf("%s\r\n", (*ret)[9] )
}

原始问题是关于返回数组,所以我将其更新为显示返回一个值。你不能直接"返回一个数组",但是可以使用数组的typedef并返回它。。。
char my_array[10][8];
typedef char ReturnArray[8];
ReturnArray* foo()
{
  return my_array;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接