以时尚的方式并排放置char矩阵

时间:2019-01-21 19:41:51

标签: c

我正在尝试使C代码类似于著名的bigdigits.py

为获得此结果,我已经尝试了串联的for循环。

这产生了我能找到的最接近的结果

scanf("%s", nums);

system("cls");

printf("\n");

x = strlen(nums);

for(int i = 0; i < x; i++){
    if(nums[i] == '1'){
        printf("%s",n[1].number);
    }else if(nums[i] == '2'){
        printf("%s",n[2].number);
    }else if(nums[i] == '3'){
        printf("%s",n[3].number);
    }else if(nums[i] == '4'){
        printf("%s",n[4].number);
    }else if(nums[i] == '5'){
        printf("%s",n[5].number);
    }else if(nums[i] == '6'){
        printf("%s",n[6].number);
    }else if(nums[i] == '7'){
        printf("%s",n[7].number);
    }else if(nums[i] == '8'){
        printf("%s",n[8].number);
    }else if(nums[i] == '9'){
        printf("%s",n[9].number);
    }else if(nums[i] == '0'){
        printf("%s",n[0].number);
        }
}

这就是我试图找到所需结果的原因(前面提到的for循环)

Ps .:惨败

scanf("%s", nums);

x = strlen(nums);

for(int k = 0; k < x; k++){
    for(int i = 0; i < 7; i++){
        for(int j = 0; j < 3; j++){
           if(nums[k] == '1'){
                printf("%s", n[i][j]);
           }if(nums[k] == '2'){
                printf("%s", n2[i][j]);
           }
        }
        printf("\n");
    }
}

输入类似于“ 12”,输出(我想要实现的)类似于

 *     ***
**    *   *
 *       *
 *      *
 *    *
 *    *
***   *****

但是此刻我的输出看起来像这样

 *     
**    
 *    
 *    
 * 
 * 
***

 ***
*   *
   *
  *
*
*
*****

1 个答案:

答案 0 :(得分:2)

让我们回溯一下,在编写代码之前,先了解一下通用逻辑。

您显然有一大堆数字,例如

#define  DIGITS  10
#define  ROWS    5

const char *const bigdigit[ROWS][DIGITS] = {
    { " 0 ", " 1 ", "22 ", "33 ", "  4", "555", " 66", "777", " 8 ", " 9 " },
    { "0 0", " 1 ", "  2", "  3", " 44", "5  ", "6  ", "  7", "8 8", "9 9" },
    { "0 0", " 1 ", " 2 ", " 3 ", "444", "55 ", "66 ", " 7 ", " 8 ", " 99" },
    { "0 0", " 1 ", "2  ", "  3", "  4", "  5", "6 6", " 7 ", "8 8", "  9" },
    { " 0 ", " 1 ", "222", "33 ", "  4", "55 ", " 6 ", " 7 ", " 8 ", "99 " }
};

,以便bigdigit[row][digit]描述数字row(0..9)的行digit(0..4)。在上方,每个数字的宽度为3个字符,但这没有关系,只要任何特定字符的行都具有相同的宽度(即"对齐!)即可。

假设您希望使用这些大数字打印251

因为printf()的输出是从上到下,从左到右的,所以我们需要先打印2的第一行,然后再打印5的第一行,然后再打印1,最后一行,直到我们打印其余行。

因此,循环显然必须是

/* char *message;                    or 
   char  message[MAXSIZE];           contains the digits to be printed
   int   columns = strlen(message);  is the number of digits */

for (row = 0; row < ROWS; row++) {

    for (column = 0; column < columns; column++) {
        switch (message[column]) {
            case '0': fputs(bigdigit[row][0], stdout); break;
            case '1': fputs(bigdigit[row][1], stdout); break;
            case '2': fputs(bigdigit[row][2], stdout); break;
            case '3': fputs(bigdigit[row][3], stdout); break;
            case '4': fputs(bigdigit[row][4], stdout); break;
            case '5': fputs(bigdigit[row][5], stdout); break;
            case '6': fputs(bigdigit[row][6], stdout); break;
            case '7': fputs(bigdigit[row][7], stdout); break;
            case '8': fputs(bigdigit[row][8], stdout); break;
            case '9': fputs(bigdigit[row][9], stdout); break;
        }
    }

    fputc('\n', stdout);
}

如果您不熟悉fputs(),则fputs(stuff, stdout)等同于printf("%s", stuff)。同样,fputc('\n', stdout)等效于printf("\n");

换句话说,外部循环位于行上方,内部循环位于要显示的每个大数字上方。是的,我们确实在消息上循环了ROWS次,但这没关系;我们确实需要这样做。


虽然我也建议不要显示完整的解决方案,但OP的问题实际上只是循环顺序,所以让我们作一个例外,然后看一下完整的示例程序:

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

#define  DIGITS  10
#define  ROWS    7

const char *const bigdigit[ROWS][DIGITS] = {
    { " 00 ", " 1", " 22 ", "333 ", "  44 ", "5555", " 666", "7777", " 88 ", " 99 " },
    { "0  0", "11", "2  2", "   3", " 4 4 ", "5   ", "6   ", "   7", "8  8", "9  9" },
    { "0  0", " 1", "   2", "   3", "4  4 ", "5   ", "6   ", "  7 ", "8  8", "9  9" },
    { "0  0", " 1", "  2 ", " 33 ", "44444", "555 ", "666 ", " 7  ", " 88 ", " 999" },
    { "0  0", " 1", " 2  ", "   3", "   4 ", "   5", "6  6", " 7  ", "8  8", "   9" },
    { "0  0", " 1", "2   ", "   3", "   4 ", "5  5", "6  6", " 7  ", "8  8", "   9" },
    { " 00 ", " 1", "2222", "333 ", "   4 ", " 55 ", " 66 ", " 7  ", " 88 ", "999 " }
};

int main(void)
{
    char  message[100];
    int   row, col;

    while (scanf(" %99[0-9]", message) == 1) {

        for (row = 0; row < ROWS; row++) {

            for (col = 0; message[col] != '\0'; col++) {
                fputs(bigdigit[row][message[col] - '0'], stdout);
                fputc(' ', stdout);
            }

            fputc('\n', stdout);
        }

        fputc('\n', stdout);
    }

    return EXIT_SUCCESS;
}

bigdigit是字符串文字的二维数组。外部(左侧)维是行(0到ROWS-1),内部(右侧)维是数字(0到9)。如您所见,这使我们能够以易于阅读的形式定义数组。

message的char数组限制为100个字符,包括字符串末尾nul字节'\0',因此转换说明符将输入转换限制为99个字符。转换为[0-9],表示包含ASCII数字0到9的字符串。

scanf()函数返回成功的转换次数。如果scanf(" %99[0-9]", message)转换由十进制数字组成的字符串,则返回1,否则转换为0或EOF。转换前面的空格表示所有空白(制表符,空格,换行符)都将首先被跳过。

因此,此示例程序一次转换一次这样的数字,直到不再提供任何输入,或者输入中包含空格或数字以外的内容。例如,任何字母都将结束程序。

重要的是要意识到,当scanf()系列函数中的任何一个遇到无法按要求转换的输入时,该输入将保留在输入缓冲区中。 不可转换的数据不会被丢弃。如果您愿意,则需要丢弃该数据。 (scanf("%*[\n]");可用于丢弃此类数据,如果转换模式以空格开头。它基本上会丢弃其余输入行,但不包括行尾的换行符。*表示转换会被跳过;结果不会存储在任何地方,并且没有与该转换相对应的参数。)

行循环与此答案开头所解释的相同。

列循环有两个特点:与从0到比message的字符串长度少一个循环不同,该循环从0到字符串中的结尾。 message。请记住,在C中,字符串以nul字符'\0'结尾。 (strlen()仅计算非null字符的数量,直到看到nul字符为止。)

列循环还在每个数字之间打印一个空格。只是这样,您不需要在bigdigit[][]数组本身中包含字母空间。

bigdigit[row][message[col] - '0']表达式中的“棘手”部分是message[col] - '0'部分。您会看到,字符串中的各个字符实际上只是整数,通常称为代码或代码点。在基本上所有字符集中,09都有连续的代码集,因此,如果message []中的第col个字符为零位,则message[col] - '0'的值为零,如果为{一位,依此类推,最多9位。

第二个fputc('\n', stdout);在每个大数字字符串之后打印一个空行。就是程序了。

如果您编译上述程序,并输入1237 543,则该程序将输出

 1  22  333  7777 
11 2  2    3    7 
 1    2    3   7  
 1   2   33   7   
 1  2      3  7   
 1 2       3  7   
 1 2222 333   7   

5555   44  333  
5     4 4     3 
5    4  4     3 
555  44444  33  
   5    4     3 
5  5    4     3 
 55     4  333  

请注意,在C中,标准输入是行缓冲的。 (也就是说,当您键入输入内容时,程序实际上会立即看到整行,但只有在您按Enter键时才能看到。)由于大数字打印是在循环中完成的,因此一次可以从输入中获取一位数字字符串,这两个字符串分别打印在不同的行上。

如果要按行中指定的那样打印输入,则需要读取整行(使用fgets()),并至少实现空格字符(在{{1}中) }),然后将bigdigit[][]改回switch语句,以便输出空格。例如:

fputs(bigdigit[row][message[col] - '0'], stdout)

如果您增加#include <stdlib.h> #include <string.h> #include <stdio.h> #define DIGITS 10 #define ROWS 7 const char *const bigdigit[ROWS][DIGITS] = { { " 00 ", " 1", " 22 ", "333 ", " 44 ", "5555", " 666", "7777", " 88 ", " 99 " }, { "0 0", "11", "2 2", " 3", " 4 4 ", "5 ", "6 ", " 7", "8 8", "9 9" }, { "0 0", " 1", " 2", " 3", "4 4 ", "5 ", "6 ", " 7 ", "8 8", "9 9" }, { "0 0", " 1", " 2 ", " 33 ", "44444", "555 ", "666 ", " 7 ", " 88 ", " 999" }, { "0 0", " 1", " 2 ", " 3", " 4 ", " 5", "6 6", " 7 ", "8 8", " 9" }, { "0 0", " 1", "2 ", " 3", " 4 ", "5 5", "6 6", " 7 ", "8 8", " 9" }, { " 00 ", " 1", "2222", "333 ", " 4 ", " 55 ", " 66 ", " 7 ", " 88 ", "999 " } }; int main(void) { char message[100], *line; int row, col; while (1) { line = fgets(message, sizeof message, stdin); if (line == NULL) break; if (strcspn(line, "\r\n") < 1) break; for (row = 0; row < ROWS; row++) { for (col = 0; line[col] != '\0'; col++) { switch (line[col]) { case '0': fputs(bigdigit[row][0], stdout); fputc(' ', stdout); break; case '1': fputs(bigdigit[row][1], stdout); fputc(' ', stdout); break; case '2': fputs(bigdigit[row][2], stdout); fputc(' ', stdout); break; case '3': fputs(bigdigit[row][3], stdout); fputc(' ', stdout); break; case '4': fputs(bigdigit[row][4], stdout); fputc(' ', stdout); break; case '5': fputs(bigdigit[row][5], stdout); fputc(' ', stdout); break; case '6': fputs(bigdigit[row][6], stdout); fputc(' ', stdout); break; case '7': fputs(bigdigit[row][7], stdout); fputc(' ', stdout); break; case '8': fputs(bigdigit[row][8], stdout); fputc(' ', stdout); break; case '9': fputs(bigdigit[row][9], stdout); fputc(' ', stdout); break; case ' ': fputs(" ", stdout); break; } } fputc('\n', stdout); } fputc('\n', stdout); } return EXIT_SUCCESS; } ,则可以在DIGITS的情况下添加bigdigit[row][10],依此类推,例如打印字母等。

因为空间始终只是空间,所以我没有使用switch条目,而是将其设置为五个空格字符宽,包括字母间空格。

如果编译并运行该程序,它将一直运行,直到您为其提供空行。对于相同的bigdigit输入,此输出

1237 543

与上一个程序相比,该程序中只有两个真正的新东西:首先,将整个输入行(而不是 1 22 333 7777 5555 44 333 11 2 2 3 7 5 4 4 3 1 2 3 7 5 4 4 3 1 2 33 7 555 44444 33 1 2 3 7 5 4 3 1 2 3 7 5 5 4 3 1 2222 333 7 55 4 333 读入scanf()缓冲区中(限于长度大于message[]的大小)。表达式message[]的计算结果为sizeof message数组中的字符数,其中包括为字符串末尾nul字符保留的字符数。仅在message是数组的情况下有效,而在它是指针的情况下则无效。

(如果您为message动态分配内存,那么您确实需要将分配的字符数保留在一个单独的变量中,并将其提供给char *message。没有标准的查找方法找出之后为一个指针分配了多少个字符;在C语言中,如果需要,您必须自己跟踪该字符。)

第二个变化是时髦的strcspn(line, "\r\n")函数调用。它返回fgets()中的字符数,直到字符串的末尾,或者直到列出的任何字符(此处为回车符或换行符),这两个字符用于不同操作系统中的各种组合中的换行符),以先发生的为准。

(有时您会看到line在第一个回车符或换行符处用于修剪line[strcspn(line, "\r\n")] = '\0';的内容,在line所在的字符串末尾删除换行符。只要fgets()不为NULL并包含一个字符串(即使它不包含回车符或换行符)就可以保证安全,因为在这种情况下,line只是返回字符串的长度。)

strcspn()行可以理解为“如果if (strcspn(line, "\r\n") < 1)中没有字符,或者第一个字符是回车符或换行符,则为。我本可以将其写为line,但我认为在这里显示这样一个漂亮的小标准函数将是适当的。

由于if (line[0] == '\0' || line[0] == '\r' || line[0] == '\n')语句中没有default:大小写,因此除数字和空格(以及您添加的字符,如果增加switch并将其字符串添加到{ {1}}数组并作为新的DIGITS语句输出)。