【问题标题】:Pointer to character array and pass to 2d character array function argument指向字符数组的指针并传递给二维字符数组函数参数
【发布时间】:2021-06-10 01:04:29
【问题描述】:

所以我在 C 中尝试了几行代码,并遇到了这个问题。 我有一个具有以下定义的结构:

typedef struct menuScreen
{
    char *lines[MENU_MAX_LINES];
}menuScreen;

这样,我有一个二维字符数组声明为:

static char array1[][MENU_MAX_CHAR_PER_LINE] = {
    "Line 1",
    "Line 2",
    "Line 3",
    "Line 4"
};

那么我有一个函数:

void buildMenu(menuScreen *menu, const char lines[][MENU_MAX_CHAR_PER_LINE])
{
    int i = 0;
    for(i = 0; i < MENU_MAX_LINES; i++)
    {
        menu->lines[i] = (char *) lines[i];
    }
}

最后是菜单的打印功能:

void printMenu(menuScreen *menu)
{
    int i = 0;
    for(i = 0; i < MENU_MAX_LINES; i++)
    {
        printf("%s\n", menu->lines[i]);
    }
}

在 main.c 中:

    menuScreen selectMenu[2];
    buildMenu(&selectMenu[0], array1);
    printMenu(&selectMenu[0]);

现在一切正常。印刷也不错。 然后我决定将我的字符数组转换如下:

static char *array1[MENU_MAX_CHAR_PER_LINE] = {
    "Line 1",
    "Line 2",
    "Line 3",
    "Line 4"
};

并将函数更改为:

void buildMenu(menuScreen *menu, const char **lines)
{
    int i = 0;
    for(i = 0; i < MENU_MAX_LINES; i++)
    {
        menu->lines[i] = (char *) lines[i];
    }
}

最后在 main.c 中,我将函数称为:

    menuScreen selectMenu[2];
    buildMenu(&selectMenu[0], (const char**) array1);
    printMenu(&selectMenu[0]);

再一次,一切都很棒。按要求工作。

现在,鉴于以上所有内容,我想知道如何概括 buildMenu() 函数,以便我可以在一个函数本身中同时传递 char[][] 和 char *[]。 不能使用函数重载,因为我使用的是 C,而不是 C++。也许可以用函数指针来完成,但只是想知道是否可以通过调整函数的参数来实现。

【问题讨论】:

  • 是的。似乎是一个错字。已编辑原帖。但问题仍然是如何概括它。
  • 我认为不可能按照你想要的方式概括它。一方面,你有char line[][N],它被调整为char (*line)[N]。另一方面,你有char *line[],它被调整为char **line。这些是不兼容的类型。特别是,后者需要比前者多一次的内存访问。所以任何这样的函数都需要知道它正在处理哪种样式,并且需要根据样式以不同的方式访问数组。
  • 嗯。说得通。我也在想类似的。好吧,我想我必须坚持一个。谢谢。

标签: arrays c pointers


【解决方案1】:

如果你的编译器支持C11,你可以使用_Generic重载函数:

#define buildMenu(a,b) _Generic((&b), \
    char (*)[][MENU_MAX_CHAR_PER_LINE] : buildMenu1(a,(const char (*)[MENU_MAX_CHAR_PER_LINE])(b)), \
    char *(*)[MENU_MAX_CHAR_PER_LINE]  : buildMenu2(a,(const char**)(b)))

(见https://stackoverflow.com/a/43500229/6874310https://gustedt.wordpress.com/2012/05/19/type-generic-functions-taking-pointers-or-arrays/)

#include <stdio.h>

#define MENU_MAX_CHAR_PER_LINE (100)
#define MENU_MAX_LINES (4)

#define buildMenu(a,b) _Generic((&b), \
    char (*)[][MENU_MAX_CHAR_PER_LINE] : buildMenu1(a,(const char (*)[MENU_MAX_CHAR_PER_LINE])(b)), \
    char *(*)[MENU_MAX_CHAR_PER_LINE]  : buildMenu2(a,(const char**)(b)))

typedef struct menuScreen
{
    char *lines[MENU_MAX_LINES];

} menuScreen;

static char array1[][MENU_MAX_CHAR_PER_LINE] = {
    "array1_Line 1",
    "array1_Line 2",
    "array1_Line 3",
    "array1_Line 4"
};

static char *array2[MENU_MAX_CHAR_PER_LINE] = {
    "array2_Line 1",
    "array2_Line 2",
    "array2_Line 3",
    "array2_Line 4"
};

void buildMenu2(menuScreen *menu, const char **lines)
{
    int i = 0;
    for(i = 0; i < MENU_MAX_LINES; i++)
    {
        menu->lines[i] = (char *)lines[i];
    }
}

void buildMenu1(menuScreen *menu, const char lines[][MENU_MAX_CHAR_PER_LINE])
{
    int i = 0;
    for(i = 0; i < MENU_MAX_LINES; i++)
    {
        menu->lines[i] = (char *) lines[i];
    }
}

void printMenu(menuScreen *menu)
{
    int i = 0;
    for(i = 0; i < MENU_MAX_LINES; i++)
    {
        printf("%s\n", menu->lines[i]);
    }
}

int main()
{
    menuScreen selectMenu[2] = {0,};

    buildMenu(&selectMenu[0], array1);
    printMenu(&selectMenu[0]);

    printf("\n");

    buildMenu(&selectMenu[1], array2);
    printMenu(&selectMenu[1]);

    return 0;
}

这个输出:

array1_Line 1
array1_Line 2
array1_Line 3
array1_Line 4

array2_Line 1
array2_Line 2
array2_Line 3
array2_Line 4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多