在C中创建网格形状(为什么还要创建一条额外的线?)

时间:2018-11-08 18:31:05

标签: c for-loop grid-layout shapes

我正在尝试使用这种形式在C中创建网格

+--+--+--+
|  |  |  |
+--+--+--+
|  |  |  |
+--+--+--+

,依此类推。用户将确定所需的列和行数。 在下面的代码中,逻辑是执行一次行循环将创建此形状

   +--+--+
   |  |  |
   +--+--+  

我的意思是,一行是这种形状而不是单条线。 由于某种原因,它在乘法样式示例中创建的行比所需的多,对于n = 3,它创建4行,对于n = 6,它创建另外2行,对于9,它创建另外4行,等等。 请记住,n = 3 * n(程序的开始)是因为我们希望上述形状为一行,这也是我这样做的主要原因,因为网格必须以+-+行结尾。 / p>

#include <stdio.h>

int main(void)
{
    int n,m,i,j;
    scanf("%d",&n);
    scanf("%d",&m);
    n=3*n;

    for(i=0;i<n;i++){
        if(i%2==0){
            printf("+");
        }
        for(j=0;j<m;j++){

            if(i%2!=0 && i!=n-1){
                printf("|  ");
            }
            if(i%2==0){

                printf("--+");
            }
        }
        if(i%2!=0 && i!=n-1){
            printf("|  ");
        }

        printf("\n");
    }
}

2 个答案:

答案 0 :(得分:2)

一些建议:

  1. 使用有意义的变量名
  2. 提示用户输入

您需要打印的基本形状是:

+--
|

请记住,这是一个简单的解决方案:

#include <stdio.h>

int main(void)
{
    int row, col, r, c;

    printf("Enter Number Of Rows And Columns: ");
    scanf("%d", &row);
    scanf("%d", &col);

    for(r = 0; r < row; r++)
    {
        /* Draw Top */
        for(c = 0; c < col; c++)
            printf("+--");
        printf("+\n");

        /* Draw Middle */
        for(c = 0; c < col; c++)
            printf("|  ");
        printf("|\n");
    }

    /* Draw Bottom */
    for(c = 0; c < col; c++)
        printf("+--");
    printf("+\n");
}

输出

$ ./main.exe
Enter Number Of Rows And Columns: 1 1
+--+
|  |
+--+

$ ./main.exe
Enter Number Of Rows And Columns: 2 6
+--+--+--+--+--+--+
|  |  |  |  |  |  |
+--+--+--+--+--+--+
|  |  |  |  |  |  |
+--+--+--+--+--+--+

$ ./main.exe
Enter Number Of Rows And Columns: 6 2
+--+--+
|  |  |
+--+--+
|  |  |
+--+--+
|  |  |
+--+--+
|  |  |
+--+--+
|  |  |
+--+--+
|  |  |
+--+--+

答案 1 :(得分:2)

在user3386109评论该问题时,问题出在n = 3*n;上。应该为n = 2*n + 1;,因为每个单元格为2×2个字符,并且您需要多排一行字符。

考虑以下反例:

#include <stdlib.h>
#include <locale.h>
#include <wchar.h>
#include <stdio.h>

const wchar_t  names[] = L"123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

static void wide_grid(FILE *out, const int rows, const int cols)
{
    int  row, col;

    /* We can only do single-character cell names. */
    if (rows > wcslen(names) || cols > wcslen(names))
        return;    

    /* Top left corner of the grid, including the top edge of that cell. */
    fwprintf(out, L"┌──");

    /* Top edges of each cell in the topmost row, except the leftmost cell. */
    for (col = 2; col <= cols; col++)
        fwprintf(out, L"┬──");

    /* Top right corner of the grid. */
    fwprintf(out, L"┐\n");

    /* Cells for the top row, including their left edges. */
    for (col = 1; col <= cols; col++)
        fwprintf(out, L"│%lc%lc", names[0], names[col-1]);

    /* The right edge of the last cell in the top row. */
    fwprintf(out, L"│\n");

    /* Loop over the rest of the cell rows. */
    for (row = 2; row <= rows; row++) {

        /* Top edge of the first cell on this row. */
        fwprintf(out, L"├──");

        /* Top edges of the rest of the cells. */
        for (col = 2; col <= cols; col++)
            fwprintf(out, L"┼──");

        /* Right edge of the grid. */
        fwprintf(out, L"┤\n");

        /* Cells themselves, including their left edges. */
        for (col = 1; col <= cols; col++)
            fwprintf(out, L"│%lc%lc", names[row-1], names[col-1]);

        /* Right edge of the grid. */
        fwprintf(out, L"│\n");
    }

    /* Bottom left corner of the grid, including the cell bottom. */
    fwprintf(out, L"└──");

    /* Bottom edges of the rest of the cells. */
    for (col = 2; col <= cols; col++)
        fwprintf(out, L"┴──");

    /* Bottom right corner of the grid. */
    fwprintf(out, L"┘\n");
}


int main(int argc, char *argv[])
{
    const int  max = wcslen(names);
    int        rows, cols;
    char       dummy;

    if (!setlocale(LC_ALL, ""))
        fprintf(stderr, "Warning: Your C library does not support your current locale.\n");

    if (fwide(stdout, 1) < 1)
        fprintf(stderr, "Warning: Your C library does not support wide character standard output.\n");

    if (argc != 3) {
        fprintf(stderr, "\n");
        fprintf(stderr, "Usage: %s [ help ]\n", argv[0]);
        fprintf(stderr, "       %s ROWS COLUMNS\n", argv[0]);
        fprintf(stderr, "\n");
        return EXIT_SUCCESS;
    }

    if (sscanf(argv[1], " %d %c", &rows, &dummy) != 1 || rows < 1) {
        fprintf(stderr, "%s: Invalid number of rows.\n", argv[1]);
        return EXIT_FAILURE;
    }
    if (rows > max) {
        fprintf(stderr, "%s: Too many rows. The maximum is %d.\n", argv[1], max);
        return EXIT_FAILURE;
    }

    if (sscanf(argv[2], " %d %c", &cols, &dummy) != 1 || cols < 1) {
        fprintf(stderr, "%s: Invalid number of columns.\n", argv[2]);
        return EXIT_FAILURE;
    }
    if (cols > max) {
        fprintf(stderr, "%s: Too many columns. The maximum is %d.\n", argv[2], max);
        return EXIT_FAILURE;
    }

    wide_grid(stdout, rows, cols);

    return EXIT_SUCCESS;
}

此程序使用宽字符输出,因此您应该能够使用终端字体支持的任何Unicode字形。这些来自“盒子图纸”集中。 (某些Windows用户可能需要上述特定于Microsoft的扩展名才能获得正确的输出,但是由于我不使用Windows,因此省略了这些扩展名。)

您还需要在命令行上提供行数和列数。不带任何参数运行将显示简短的帮助文本。

每个单元格都带有标签,行和列标签均来自names数组。您可以通过向该数组添加标签字符来允许更大的网格。

wide_grid()中的每一行或每个循环进行注释,以解释每个代码段的目的。

我们将逐个构建网格,而不是单个嵌套循环以及其中的条件条件:

┌──  ┬──  ..  ┬──  ┐

│11  │12  ..  │1c  │

├──  ┼──  ..  ┼──  ┤   ╲
                        row = 2 .. rows
│r1  │r2  ..  │rc  │   ╱

:    :        :    :

└──  ┴──  ..  ┴──  ┘

如果使用参数5 12运行它,您将看到以下内容:

┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
│11│12│13│14│15│16│17│18│19│1A│1B│1C│
├──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┤
│21│22│23│24│25│26│27│28│29│2A│2B│2C│
├──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┤
│31│32│33│34│35│36│37│38│39│3A│3B│3C│
├──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┤
│41│42│43│44│45│46│47│48│49│4A│4B│4C│
├──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┤
│51│52│53│54│55│56│57│58│59│5A│5B│5C│
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘