我正在尝试使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”,输出(我想要实现的)类似于
* ***
** * *
* *
* *
* *
* *
*** *****
但是此刻我的输出看起来像这样
*
**
*
*
*
*
***
***
* *
*
*
*
*
*****
答案 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'
部分。您会看到,字符串中的各个字符实际上只是整数,通常称为代码或代码点。在基本上所有字符集中,0
至9
都有连续的代码集,因此,如果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
语句输出)。