可变C函数打印多个二维字符阵列
我需要在C中设置一个可变函数,它可以并排打印可变数量的二维字符数组。我很难弄清楚如何使用可变C函数打印多个二维字符阵列,c,arrays,2d,variadic,C,Arrays,2d,Variadic,我需要在C中设置一个可变函数,它可以并排打印可变数量的二维字符数组。我很难弄清楚如何使用va_arg()初始化boards变量 关键问题是:boards[i]=va_arg(ap,char*[[BOARDSIZE])该行产生了一个编译器错误(目前,到'va_arg'的第二个参数的类型是不完整的'char*[[10]'),但基本上我确信我没有做正确的事情。我只是不确定那是什么。我试过几种变体,但都没有用。不过,代码的其余部分应该还可以 (提前感谢您的帮助。) #包括 #包括 #定义板尺寸10 无效
va_arg()
初始化boards
变量
关键问题是:boards[i]=va_arg(ap,char*[[BOARDSIZE])代码>该行产生了一个编译器错误(目前,到'va_arg'的第二个参数的类型是不完整的'char*[[10]'
),但基本上我确信我没有做正确的事情。我只是不确定那是什么。我试过几种变体,但都没有用。不过,代码的其余部分应该还可以
(提前感谢您的帮助。)
#包括
#包括
#定义板尺寸10
无效显示板可变(整数numArgs,…){
va_列表ap;
va_启动(ap、numArgs);
//分配一个二维字符数组。
字符*板[numArgs][BOARDSIZE][BOARDSIZE];
对于(int i=0;i
va_arg的C规范要求“参数类型应为指定的类型名称,以便通过将*后固定到类型即可获得指向具有指定类型的对象的指针的类型。”字符串char*[][BOARDSIZE]
不满足此要求。您应该使用typedef
为类型命名
此外,在函数声明的参数列表中,char*[][BOARDSIZE]
自动调整为char*(*}[BOARDSIZE]
。在va_arg
(或typedef
)中,它不是。您应该使用调整后的表单
因此,您应该为类型定义一个名称,该类型是指向BOARDSIZE
指向char
的指针数组的指针:
typedef char *(*MyType)[BOARDSIZE];
您应该将电路板
更改为这些电路板的阵列,而不是阵列的阵列:
MyType boards[numArgs];
您应该更改va_arg
以使用新类型:
boards[i] = va_arg(ap, MyType);
还请注意,您正在将电路板的每个元素设置为字符串“~”。这会将它们全部设置为指向字符串文字,这可能不是您想要的。您不允许修改此字符串文字中的字符,因此更改电路板包含的内容的唯一方法是将它们更改为指向不同的字符串
如果每个电路板元素都是单个字符,则应使用char
而不是char*
。如果它们是固定的或少量的多个字符,则可能需要一个char
数组,而不是指向char
的指针。如果它们是相当多的多个字符您可能希望使用<代码> char */COD>但为每个板元素分配空间。 < P>实际上,我得出了与埃里克相同的结论,只是我甚至没有考虑通过<代码> TyBuffF S.解决多维数组问题。
出于好奇,我试着写下一个操作的工作版本。当我最终得到一个时,我想展示我的代码(除了答案)
因此,经过一些修改,我得到了这个工作版本testVarArgMDimArray.c
:
#include <stdio.h>
#include <stdarg.h>
#define BOARDSIZE 10
#define NCOLS BOARDSIZE
#define NROWS BOARDSIZE
typedef char Board[NROWS][NCOLS];
typedef char (*PBoard)[NCOLS];
void showBoardVariadic(int nArgs, ...)
{
va_list ap;
va_start(ap, nArgs);
/* Attention! VLAs are an optional feature of C11. */
PBoard boards[nArgs];
for (int i = 0; i < nArgs; ++i) {
boards[i] = va_arg(ap, PBoard);
}
/* print the 2D arrays side-by-side */
for (int row = 0; row < NROWS; ++row) {
for (int i = 0; i < nArgs; ++i) {
if (i) putchar('\t');
for (int col = 0; col < NCOLS; ++col) {
printf(" %c", boards[i][row][col]);
}
}
putchar('\n');
}
va_end(ap);
}
int main()
{
Board playerBoard;
Board opponentBoard;
/* initialize boards */
for (int row = 0; row < NROWS; ++row) {
#ifdef CHECK /* for checking */
/* insert some pattern in col 0 for checking */
playerBoard[row][0] = 'a' + row;
opponentBoard[row][0] = 'A' + row;
for (int col = 1; col < NCOLS; ++col) {
playerBoard[row][col] = opponentBoard[row][col] = '~';
}
#else /* productive code */
for (int col = 0; col < NCOlS; ++col) {
playerBoard[row][col] = opponentBoard[row][col] = '~';
}
#endif /* 1 */
}
showBoardVariadic(2, playerBoard, opponentBoard);
/* done */
return 0;
}
更重要的可能是第二点:
typedef char (*PBoard)[NCOLS];
请记住,函数参数中的数组总是作为指针编译的。C从不将数组作为参数传递。因此,如果我们使用Board
类型的参数调用函数,我们将收到PBoard
类型的参数
请注意*PBoard
周围的括号–这意味着PBoard
是指向数组的指针。如果删除它们,则会得到一个指针数组–这是一个很大的区别,而不是预期的
掌握了这一点后,showBoardVariadic()
中的内容变得相当简单
电路板阵列声明为:
PBoard boards[nArgs];
带有va_arg
的赋值很简单:
boards[i] = va_arg(ap, PBoard);
printf(" %c", boards[i][row][col]);
进入配电盘的途径很简单:
boards[i] = va_arg(ap, PBoard);
printf(" %c", boards[i][row][col]);
这可能会令人惊讶,但在本例中,指向数组的指针的行为类似于数组数组。它只是具有不同的类型。(例如,您不应将sizeof
与PBoard
一起使用,因为在本例中,不同的类型将生效。)
由于在这种开发状态下,每个board元素都包含相同的内容,我担心board索引中的问题是否会被忽略。因此,我实现了一个替代初始化,其中列的每个第一个元素都会获得另一个字符:forPlayboard
'a'+row
,foropponentBoard
'A'+行
。通过定义宏检查
激活此测试分配。在我的测试会话中,我用-D检查编译了一次
,没有
顺便说一句,如果你想知道为什么我引入了NROWS
和NCOLS
:在写这个答案的时候,我意识到如果我不小心在某个地方翻转了行和列,我不会注意到,因为它们在OP中的大小相同。因此,我将事情分开,并使用NROWS
≠ NCOLS
.Phew–它仍然工作正常
最后但并非最不重要的一点是,我在Cygwin中的示例会话(因为我在Windows 10上):
$gcc--ve