【问题标题】:Using 2D arrays, my arrays don't appear使用二维数组,我的数组不会出现
【发布时间】:2015-10-30 18:52:18
【问题描述】:

我的程序编译好了,没问题。当我启动它并输入“AB”时,它们出现在一行上,但是当我输入“BAAB”时,“AB”在“BA”下方。我被困在这里很长时间了。如果你能解决这个问题,我会很高兴。

//它需要从键盘读取输入并出现由astersks构造的每个字母

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

char line[100] = { 'A', 'B' };
int i;
int row;
int col;

bool A[7][6] = { {0, 0, 1, 0, 0, 0},    //letter A
                {1, 0, 0, 0, 1, 0},
                {1, 0, 0, 0, 1, 0},
                {1, 1, 1, 1, 1, 0},
                {1, 0, 0, 0, 1, 0},
                {1, 0, 0, 0, 1, 0},
                {1, 0, 0, 0, 1, 0} };

bool B[7][6] = { {1, 1, 1, 0, 0, 0},    //letter B
                {1, 0, 0, 1, 0, 0},
                {1, 0, 0, 1, 0, 0},
                {1, 1, 1, 1, 0, 0},
                {1, 0, 0, 0, 1, 0},
                {1, 0, 0, 0, 1, 0},
                {1, 1, 1, 1, 0, 0} };

int main () {

    //reads the input
    printf ("Type a word or number, or both: ");
    scanf ("%s", line);

    // loop for every row of every letter
    for (row = 0; row < 7; row++) 
    {
        // loop for every inputed letter
        for (i = 0; line[i]; i++) 
        {
            // if letter is A do this...
            if (line[i] == 'A')
            {
                // lopp for every column to read the asterisks
                for (col = 0; col < 5; col++) {
                    if (A[row][col])
                        printf ("*");
                    else
                        printf (" ");
                }
                printf ("\n");
            }

            if (line[i] == 'B') {
                for (col = 0; col < 5; col++) {
                    if (B[row][col])
                        printf ("*");
                    else
                        printf (" ");

                }
            }

        }

    }
    return (0);
}

【问题讨论】:

    标签: c arrays for-loop multidimensional-array


    【解决方案1】:

    Trex,您首先需要了解的是“如果我没有输入,我的代码会做什么?”。所以注释掉你最初的printfscanf 并检查:

    //reads the input
    // printf ("Type a word or number, or both: ");
    // scanf ("%s", line);
    

    输出:

    $ ./bin/multi_array_mess
      *
    ***  *   *
    *  * *   *
    *  * *****
    **** *   *
    *   **   *
    *   **   *
    **** 
    

    line 的哪些值会产生该输出? {'A', 'B'} 如果line 包含AB 以外的任何内容会怎样?试试'A':

    $ Type a word or number, or both: A
      *
    *   *
    *   *
    *****
    *   *
    *   *
    *   *
    

    然后'B':

    $ ./bin/multi_array_mess
    Type a word or number, or both: B
    ***  *  * *  * **** *   **   ***** 
    

    很明显,在打印B 的循环中的某处缺少newline。更改您的逻辑以匹配您打印'A' 的方式,类似于:

    if (line[i] == 'B') {
        for (col = 0; col < 5; col++) {
            if (B[row][col])
                printf ("*");
            else
                printf (" ");
    
        }
        printf ("\n");
    }
    

    如果您只输入 'B' 以响应您的提示,则提供所需的输出:

    $ ./bin/multi_array_mess
    Type a word or number, or both: B
    ***
    *  *
    *  *
    ****
    *   *
    *   *
    ****
    

    如果您输入除'A''B' 以外的任何内容,会打印什么?没有。如果同时输入'A''B' 会发生什么? (你弄得一团糟)。

    所以它看起来只是通过修改您的程序,它被设计为使用 '*' 作为字符打印 AB,具体取决于数组中 01 的值。您可以修复逻辑以处理包含'A''B'line,也可以将输入限制为一次输入一个字符。

    由于您的意图似乎能够一次处理line 中的多个字符,如果我们稍微调整一下循环逻辑会发生什么。例如:

    // loop for every inputed letter
    for (i = 0; line[i]; i++) 
    {
        // loop for every row of every letter
        for (row = 0; row < 7; row++) 
        {
            // if letter is A do this...
            if (line[i] == 'A')
            {
    

    试一试……

    接下来,想想你是如何提示输入的:

    printf ("Type a word or number, or both: ");
    

    将您的请求限制为您的代码将提供输出的内容不是更有意义吗?

    printf ("Please enter A or B, or both: ");
    

    在收到输入后,在盲目地将输入传递给程序的其余部分之前检查用户提供的内容不是更有意义吗?一些简单的事情就可以了:

    for (i = 0; i < (int)strlen (line); i++)
        if (line[i] != 'A' || line[i] != 'B') {
            fprintf (stderr, "error: invalid input '%c'.\n", line[i]);
            return 1;
        }
    

    现在再次尝试您的程序。

    在一行上打印每个字母

    好的。既然我知道你的意图是什么,它就更容易提供帮助了。为了将每个数组打印为'*'' ' 在同一行上,您基本上必须遍历每一行,检查是否在line 中指定了给定字母并为您需要打印的每个字符打印该行.您可以通过创建一个函数来打印每个数组的行来减少代码重复(您实际上可以使用宏,但我们稍后再讨论)。

    为了与前面的讨论保持一致,我添加了一些完整性检查并创建了一个新的字符数组allowed,其中包含您为数组创建的当前字符的列表(允许的字符)。只需在添加数组时添加即可。您还会注意到我将您所有的全局变量都移到了main 中。使用全局变量并没有错,但要谨慎使用,仅在必要时使用。

    将各个部分放在一起,您可以执行以下操作:

    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    
    #define MAXL 100
    #define ROWS 7
    #define COLS 5
    
    void prn_letter_row (bool a[][COLS+1], size_t row);
    
    int main (void) {
    
        char line[MAXL] = {0};
        char allowed[] = "AB";
        size_t i, row, len;
        i = row = len = 0;
    
        bool A[ROWS][COLS+1] = {{0, 0, 1, 0, 0, 0},    //letter A
                                {1, 0, 0, 0, 1, 0},
                                {1, 0, 0, 0, 1, 0},
                                {1, 1, 1, 1, 1, 0},
                                {1, 0, 0, 0, 1, 0},
                                {1, 0, 0, 0, 1, 0},
                                {1, 0, 0, 0, 1, 0}};
    
        bool B[ROWS][COLS+1] = {{1, 1, 1, 0, 0, 0},    //letter B
                                {1, 0, 0, 1, 0, 0},
                                {1, 0, 0, 1, 0, 0},
                                {1, 1, 1, 1, 0, 0},
                                {1, 0, 0, 0, 1, 0},
                                {1, 0, 0, 0, 1, 0},
                                {1, 1, 1, 1, 0, 0}};
    
        /* prompt for input */
        while (!*line)
        {
            printf ("\nType a word or number, or both [A-B only]: ");
            if (!fgets (line, MAXL, stdin))
                fprintf (stderr, "error: no input provided - 'ctrl+d'.\n");
    
            len = strlen (line);    /* get length, remove trailing \n */
            if (line[len-1] == '\n')
                line[--len] = 0;
    
            char *p = line;
            while (*p) { /* check each character against 'allowed' */
                if (!strchr (allowed, *p)) {
                    fprintf (stderr, "error: invalid character '%c'.\n", *p);
                    *line = 0;
                }
                p++;
            }
        }
    
        printf ("valid: %s\n\n", line);
    
        for (row = 0; row < ROWS; row++) {
    
            for (i = 0; i < len; i++) {
    
                switch (line[i]) {
                    case 'A' : prn_letter_row (A, row);
                        break;
                    case 'B' : prn_letter_row (B, row);
                        break;
                }
    
            }
            putchar ('\n');
        }
    
        return 0;
    }
    
    /* print given row for letter */
    void prn_letter_row (bool a[][COLS+1], size_t row)
    {
        size_t i;
    
        putchar (' ');  /* provide a space before each letter */
    
        for (i = 0; i < COLS; i++)
            if (a[row][i])
                putchar ('*');
            else
                putchar (' ');
    }
    

    使用/输出

    $ ./bin/chars_from_arrays
    
    Type a word or number, or both [A-B only]: A
    valid: A
    
       *
     *   *
     *   *
     *****
     *   *
     *   *
     *   *
    
    $ ./bin/chars_from_arrays
    
    Type a word or number, or both [A-B only]: B
    valid: B
    
     ***
     *  *
     *  *
     ****
     *   *
     *   *
     ****
    
    $ ./bin/chars_from_arrays
    
    Type a word or number, or both [A-B only]: AB
    valid: AB
    
       *   ***
     *   * *  *
     *   * *  *
     ***** ****
     *   * *   *
     *   * *   *
     *   * ****
    

    【讨论】:

    • 非常感谢!但是有一个问题,我的输入文本需要出现在一行中。我试图只用 A 和 B 来做,但我需要用大写和小写字母以及每个数字和符号的整个字母表来做。所以我只需要出现在一行中,而不是在另一行下。那是我的问题,我无法用重复的字母来做到这一点。
    • 好的,我晚饭后看看。您将需要在所有字母中保留间距,这样您就不必将“A”的顶部重新置于“B”的顶部,等等。
    • 再次感谢兰金先生,帮了大忙!
    • 当然,很高兴我能帮上忙(我有一段时间不用像点阵打印机一样思考......)。希望您已经掌握了一些有关如何解决编程问题的技巧,这些技巧将帮助您继续前进。由于您是 Stack Overflow 的新手,因此您需要做的一件事是选择一个您认为对回答问题最有帮助的答案。它可以是页面上的任何一个。您可以通过单击每个问题左上角数字旁边的复选标记来做到这一点。这很重要,因为它标志着问题已解决,因此可以从未回答列表中删除。祝你好运。
    • 先生。 Rankin 能给我一些你的联系方式吗,你有脸书吗?
    【解决方案2】:

    这是你的固定代码

    #include <stdio.h>
    #include <stdbool.h>
    #include <string.h>
    #include <ctype.h>
    
    
    char line[100] = {'A','B'};
    
    int i;
    
    int row;
    
    int col;
    
    // Support only latin aphabet, easly expandable
    bool chars[26][7][6] = {
    
                       {  {0,0,1,0,0,0 },   //letter A        
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 },
                          {1,1,1,1,1,0 },
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 }},
    
                       {  {1,1,1,0,0,0 },   //letter B   
                          {1,0,0,1,0,0 },
                          {1,0,0,1,0,0 },
                          {1,1,1,1,0,0 },
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 },
                          {1,1,1,1,0,0 }},
                        // to Z
    };
    
    
      int main()
      {
           printf ("Type a word or number, or both: ");
    
           scanf ("%s",line);
           //reads the input
           for (row = 0;row<7;row++)
           // loop for every row of every letter
           { 
                for (i = 0; line[i]; i++)      //loop for every inputed letter
                {
    
                    for (col = 0;col < 6;col++)  // lopp for every column to read the asterisks
                    {
                        if (chars[toupper(line[i]) - 'A'][row][col])
                        {
                            printf("*");
                        }
                        else 
                            printf(" ");
                    }
                }
                printf("\n");
            }
            return (0);
    }
    

    您可以通过形成 3d 数组来添加多个字符支持

    bool chars[26][7][6] = {
    
                       {  {0,0,1,0,0,0 },   //letter A        
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 },
                          {1,1,1,1,1,0 },
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 }},
    
                       {  {1,1,1,0,0,0 },   //letter B   
                          {1,0,0,1,0,0 },
                          {1,0,0,1,0,0 },
                          {1,1,1,1,0,0 },
                          {1,0,0,0,1,0 },
                          {1,0,0,0,1,0 },
                          {1,1,1,1,0,0 }},
                        // to Z
    };
    

    比访问数组成员

    chars[toupper(line[i]) - 'A'][row][col];
    

    在这种情况下,您不能使用任何字符 if 仅检查 for 循环

    这仅适用于小字符串,因为标准控制台最多支持 80 个字符的长度,要处理它,您可以设置控制台宽度,或使用控制台光标执行一些操作以正确分解形成的字符串(如 SetConsoleCursorPosition)在 Windows 中。

    如果你想支持所有可打印的字符,你的 3d 数组应该从空白字符开始,最多 128 个字符。有关更多信息,请查看 ASCII 字符表。

    【讨论】:

    • 非常感谢!但是有一个问题,我的输入文本需要出现在一行中。我试图只用 A 和 B 来做,但我需要用大写和小写字母以及每个数字和符号的整个字母表来做。所以我只需要出现在一行中,而不是在另一行下。那是我的问题,我无法用重复的字母来做到这一点。
    • 在使用toupper()并减去'A'之前,您至少应该使用isalpha()来确定字符值是否为实际字母,因为如果您有@字符,例如@ 987654330@ 将返回 64(对于 ASCII),从 64 中减去 65 得到 -1,这将调用未定义的行为。另外,您应该始终检查scanf的返回值。
    • 非常有用,一切正常,感谢您的帮助和支持!
    • 不要忘记将您的问题标记为已回答。
    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    相关资源
    最近更新 更多