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

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

问题描述

我需要在 C 中设置一个可变参数函数来并排打印可变数量的二维字符数组.我很难弄清楚如何使用 va_arg() 初始化 boards 变量.

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().

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

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("	");
        }
        printf("
");
    }

    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;
}

推荐答案

其实我和 Eric 得出的结论是一样的,只是我什至没有考虑过仅仅通过 typedef 来解决多维数组问题代码>s.

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.

出于好奇,我尝试写下 OP 的工作版本.当我终于得到一个时,我想展示我的代码(除了 Eric Postpischils 回答之外).

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).

所以,经过一番摆弄之后,我得到了这个工作版本testVarArgMDimArray.c:

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('	');
      for (int col = 0; col < NCOLS; ++col) {
        printf(" %c", boards[i][row][col]);
      }
    }
    putchar('
');
  }
  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;
}

在我开始工作之前,我尝试在 VS2013 中解决了一些问题.太伤心了–VS2013 不支持 VLA.因此,我不得不考虑这样做,但我让它运行了.

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.

正如在我的一条评论中已经推荐的那样,我选择了 char 作为板元素而不是 char*.我也可以为 char* 解决它,但我觉得 char* 可能是 OP 中的意外"选择.

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.

按照Eric的想法,我为2D板阵列做了一个类型:

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];

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

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.

请注意*PBoard周围的括号–这允许 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.

掌握了这一点后,showBoardVariadic() 中的事情就变得相当容易了.

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

板数组声明为:

PBoard boards[nArgs];

va_arg 的赋值很简单:

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

访问板很简单:

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

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

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.)

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

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.

顺便说一句.如果你想知道我为什么引入 NROWSNCOLS:在写这个答案时,我意识到我不会注意到如果我不小心翻转了某处的行和列,因为它们在操作.因此,我将事物分开并使用 NROWS ≠ 进行测试.NCOLS.呼–它仍然可以正常工作.

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.

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

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 –非常聪明的埃里克...

typedef – very clever Eric...

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

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