可变参数C函数可打印多个二维char数组 [英] Variadic C function printing multiple 2-D char arrays

查看:115
本文介绍了可变参数C函数可打印多个二维char数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在C中设置一个可变参数函数,该函数可以并排打印可变数量的2-D字符数组。我很难弄清楚如何使用 va_arg()初始化 boards 变量。



有问题的关键行是: boards [i] = va_arg(ap,char * [] [BOARDSIZE]); 该行产生编译器错误(当前,'va_arg'的第二个参数的类型不完整'char * [] [10]'),但是基本上我确定我是没有做正确的事。我只是不确定那是什么。我尝试了几种变体,但均无济于事。其余代码应该没问题。



(谢谢您的帮助。)

  #include< stdio.h> 
#include< stdarg.h>

#define BOARDSIZE 10

void showBoardVariadic(int numArgs,...){

va_list ap;
va_start(ap,numArgs);

//分配一个二维char数组。
char * boards [numArgs] [BOARDSIZE] [BOARDSIZE];
for(int i = 0; i board [i] = va_arg(ap,char * [] [BOARDSIZE]); // TODO:修正此行

//打印二维数组
for(int row = 0; row< BOARDSIZE; row ++){
对于(int i = 0; i< numArgs; i ++){
对于(int列= 0; column< BOARDSIZE; column ++){
printf(%c,* boards [i ][行列]);
}
printf( \t);
}
printf( \n);
}

va_end(ap);
}

int main(){

char * playerBoard [BOARDSIZE] [BOARDSIZE];
char * opponentBoard [BOARDSIZE] [BOARDSIZE];

//将playerBoard和对手Board初始化为所有波浪号。
for(int row = 0; row< BOARDSIZE; row ++){
for(int column = 0; column< BOARDSIZE; column ++){
playerBoard [row] [column] = 〜;
endererBoard [row] [column] =〜;
}
}

showBoardVariadic(2,playerBoard,对手Board);

返回0;
}


解决方案

实际上,我来了像Eric一样的结论,只是我什至不考虑仅仅通过 typedef s解决多维数组问题。



出于好奇,我试图写下OP的有效版本。当我终于得到一个代码时,我想展示我的代码(除了 Eric Postpischils 答案)。



所以,经过一番摆弄之后,我得到了这个工作版本 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);
/ *注意! VLA是C11的可选功能。 * /
PBoard板[nArgs];
for(int i = 0; i boards [i] = va_arg(ap,PBoard);
}
/ *并排打印2D数组* /
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()
{
董事会球员;
董事会对手
/ *初始化板* /
for(int row = 0; row< NROWS; ++ row){
#ifdef CHECK / *检查* /
/ *在col 0中插入一些模式以检查* /
playerBoard [row] [0] ='a'+行;
endererBoard [row] [0] =‘A’+行;
for(int col = 1; col< NCOLS; ++ col){
playerBoard [row] [col] =对手Board [row] [col] =’〜’;
}
#else / *生产代码* /
for(int col = 0; col< NCOls; ++ col){
playerBoard [row] [col] = endererBoard [row] [col] ='〜';
}
#endif / * 1 * /
}
showBoardVariadic(2,playerBoard,对手Board);
/ *完成* /
返回0;
}

在我使用它之前,有一些问题我曾尝试在VS2013中解决。太难过– VS2013不支持 VLA 。因此,我必须牢记这一点,但要使其运行。



正如我的评论之一所建议的那样,我选择了 char 作为板元素,而不是 char * 。我也可以用 char * 解决它,但是我觉得 char * 可能是偶然的



按照埃里克(Eric)的想法,我为2D板阵列创建了一个类型:

  typedef char Board [NROWS] [NCOLS]; 

更重要的可能是第二个:

  typedef char(* PBoard)[NCOLS]; 

请记住,函数参数中的数组始终被编译为指针。 C从不将数组作为参数传递。因此,如果我们调用参数为 Board 的函数,我们将收到类型为 PBoard 的参数。



请注意 * PBoard 的括号。这会授予 PBoard 是指向数组的指针。如果删除它们,则会得到一个指针数组,而不是–



掌握了这一点, showBoardVariadic()中的内容就变得很容易。 / p>

板的数组声明为:

  PBoard板[nArgs ]; 

使用 va_arg 的赋值很简单:

 板[i] = va_arg(ap,PBoard); 

进入董事会的方法很简单:

  printf(%c,boards [i] [row] [col]); 

这可能令人惊讶,但在这种情况下,指向数组的指针的行为类似于数组的数组。它只是具有不同的类型。 (例如,您不应将 sizeof PBoard 一起使用,因为在这种情况下,不同的类型将生效。)



由于在此开发状态下每个董事会元素都包含相同的内容,因此我担心董事会索引的问题是否会被忽略。因此,我实现了一个替代的初始化,其中列的每个第一个元素都获得另一个字符:对于 playerBoard 'a'+行,为 opponentBoard 'A'+行。通过定义宏 CHECK 激活此测试分配。在我的测试会话中,我一次使用 -D CHECK 进行一次编译。



Btw。如果您想知道为什么我引入了 NROWS NCOLS :在编写此答案时,我意识到我不会注意到由于行和列在OP中具有相同的大小,因此意外地将行和列翻转到某个位置。因此,我将东西分开并用 NROWS ≠进行了测试。 NCOLS 。 ew



最后但并非最不重要的是,我在Cygwin中的示例会话(因为我在Windows 10上):

  $ gcc --version 
gcc(GCC)6.4.0

$ gcc -std = c11 -D检查-o testVarArgMDimArray testVarArgMDimArray.c

$ ./testVarArgMDimArray
a ~~~~~~~~~~ A ~~~~~~~~
b〜 〜〜〜〜〜〜〜〜B〜〜〜〜〜〜〜〜〜
c〜〜〜〜〜〜〜〜〜C〜〜〜〜〜〜〜〜〜
d〜〜〜〜〜〜 〜〜〜〜D〜〜〜〜〜〜〜〜
e〜〜〜〜〜〜〜〜〜E〜〜〜〜〜〜〜〜〜
f〜〜〜〜〜〜〜〜〜 F〜〜〜〜〜〜〜〜〜
g〜〜〜〜〜〜〜〜〜G〜〜〜〜〜〜〜〜〜〜
h〜〜〜〜〜〜〜〜〜〜H〜〜〜 ~~~~~~
i ~~~~~~~~~我~~~~~~~~
j ~~~~~~~~~~ J ~~~~~~~ 〜〜

$ gcc -std = c11 -o testVarArgMDimArray testVarArgMDimArray.c

$ ./testVarArgMDimArray
~~~~~~~~~~~~ ~~~~~~~~
~~ 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜 〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜 〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜 ~~~~~~~~~~

$

typedef –非常聪明的埃里克...


I need to set up a variadic function in C that prints a variable number of 2-D char arrays side-by-side. I'm having a hard time figuring out how to initialize the boards variable with va_arg().

The key problematic line is: boards[i] = va_arg(ap, char*[][BOARDSIZE]); The line produces a compiler error (currently, Second argument to 'va_arg' is of incomplete type 'char *[][10]'), but basically I'm sure I'm not doing something right. I'm just not sure what that something is. I've tried several variations to no avail. The rest of the code should be okay though.

(Thank you in advance for any help.)

#include <stdio.h>
#include <stdarg.h>

#define BOARDSIZE 10

void showBoardVariadic(int numArgs, ...) {

    va_list ap;
    va_start(ap, numArgs);

    // Assign an array of 2-D char arrays.
    char *boards[numArgs][BOARDSIZE][BOARDSIZE];
    for (int i = 0; i < numArgs; i++)
        boards[i] = va_arg(ap, char*[][BOARDSIZE]); // TODO: Fix this line

    // Print the 2-D arrays side-by-side
    for (int row = 0; row < BOARDSIZE; row++) {
        for (int i = 0; i < numArgs; i++) {
            for (int column = 0; column < BOARDSIZE; column++) {
                printf(" %c", *boards[i][row][column]);
            }
            printf("\t");
        }
        printf("\n");
    }

    va_end(ap);
}

int main() {

    char *playerBoard[BOARDSIZE][BOARDSIZE];
    char *opponentBoard[BOARDSIZE][BOARDSIZE];

    // Initialize playerBoard and opponentBoard to all tildes.
    for (int row = 0; row < BOARDSIZE; row++) {
        for (int column = 0; column < BOARDSIZE; column++) {
            playerBoard[row][column] = "~";
            opponentBoard[row][column] = "~";
        }
    }

    showBoardVariadic(2, playerBoard, opponentBoard);

    return 0;
}

解决方案

Actually, I came to the same conclusion like Eric except that I even didn't consider to solve multi-dimension array issues by mere typedefs.

Out of curiosity, I tried to write down a working version of the OP. As I finally got one I want to present my code (in addition to Eric Postpischils answer).

So, after some fiddling I got this working version 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;
}

Before I got it working there were issues which I tried solve in VS2013. Too sad – VS2013 does not support VLAs. Hence, I had to do it in mind but I got it running.

As already recommended in one of my comments, I chose char as board element instead of char*. I could've solved it for char* as well but I feel that char* could've been an "accidental" choice in the OP.

Following the idea of Eric, I made a type for the 2D board array:

typedef char Board[NROWS][NCOLS];

The more important is probably the second:

typedef char (*PBoard)[NCOLS];

Remember that arrays in function parameters are always compiled as pointers. C never passes arrays as arguments. Hence, if we call a function with an argument of type Board we will receive an argument of type PBoard.

Please, note the parentheses around *PBoard – this grants that PBoard is a pointer to array. If you remove them you get an array of pointers instead – big difference and not what is intended.

Having mastered this, things in showBoardVariadic() become rather easy.

The array of boards is declared as:

PBoard boards[nArgs];

The assignment with va_arg is simply:

boards[i] = va_arg(ap, PBoard);

The access to the boards is simply:

printf(" %c", boards[i][row][col]);

This might be surprising but in this case the pointer to array behaves like an array of arrays. It just has a different type. (E.g. you should not use sizeof with PBoard as in this case the different types would take effect.)

As every board element contains the same contents in this state of development, I was afraid whether issues in board indexing could be unnoticed. Therefore I implemented an alternative initialization where each first element of column gets another character: for playerBoard 'a' + row, for opponentBoard 'A' + row. This test assignment is activated by defining the macro CHECK. In my test session, I compiled once with -D CHECK once without.

Btw. if you wonder why I introduced NROWS and NCOLS: While writing this answer I realized that I wouldn't notice if I accidentally flipped rows and columns somewhere as they have equal size in OP. Thus, I separated things and tested with NROWSNCOLS. Phew – it still worked properly.

Last but not least, my sample session in Cygwin (as I'm on Windows 10):

$ gcc --version
gcc (GCC) 6.4.0

$ gcc -std=c11 -D CHECK -o testVarArgMDimArray testVarArgMDimArray.c 

$ ./testVarArgMDimArray
 a ~ ~ ~ ~ ~ ~ ~ ~ ~     A ~ ~ ~ ~ ~ ~ ~ ~ ~
 b ~ ~ ~ ~ ~ ~ ~ ~ ~     B ~ ~ ~ ~ ~ ~ ~ ~ ~
 c ~ ~ ~ ~ ~ ~ ~ ~ ~     C ~ ~ ~ ~ ~ ~ ~ ~ ~
 d ~ ~ ~ ~ ~ ~ ~ ~ ~     D ~ ~ ~ ~ ~ ~ ~ ~ ~
 e ~ ~ ~ ~ ~ ~ ~ ~ ~     E ~ ~ ~ ~ ~ ~ ~ ~ ~
 f ~ ~ ~ ~ ~ ~ ~ ~ ~     F ~ ~ ~ ~ ~ ~ ~ ~ ~
 g ~ ~ ~ ~ ~ ~ ~ ~ ~     G ~ ~ ~ ~ ~ ~ ~ ~ ~
 h ~ ~ ~ ~ ~ ~ ~ ~ ~     H ~ ~ ~ ~ ~ ~ ~ ~ ~
 i ~ ~ ~ ~ ~ ~ ~ ~ ~     I ~ ~ ~ ~ ~ ~ ~ ~ ~
 j ~ ~ ~ ~ ~ ~ ~ ~ ~     J ~ ~ ~ ~ ~ ~ ~ ~ ~

$ gcc -std=c11 -o testVarArgMDimArray testVarArgMDimArray.c 

$ ./testVarArgMDimArray
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~     ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

$

typedef – very clever Eric...

这篇关于可变参数C函数可打印多个二维char数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆