Матрица бок о бок в моде - PullRequest
       0

Матрица бок о бок в моде

0 голосов
/ 21 января 2019

Я пытаюсь сделать код на 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 голосов
/ 21 января 2019

Давайте немного вернемся назад и посмотрим на общую логику, прежде чем писать код.

У вас, очевидно, есть массив больших цифр, что-то вроде

#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..4) цифры digit (0..9).Выше каждая цифра имеет ширину 3 символа, но это не имеет значения, если строки для любого конкретного символа имеют одинаковую ширину (т. Е. " align!).

Допустим, вы хотитечтобы напечатать 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 ограничен 100 символами, включая нулевой байт конца строки, '\0'поэтому спецификатор преобразования ограничивает входное преобразование 99 символами.Преобразование - [0-9], что означает строку, содержащую цифры ASCII от 0 до 9.

Функция scanf() возвращает количество успешных преобразований.scanf(" %99[0-9]", message) возвращает 1, если преобразует строку, состоящую из десятичных цифр, 0 или EOF в противном случае.Пробел перед преобразованием означает, что любые пробелы (табуляции, пробелы, новые строки) пропускаются первыми.

Поэтому в этом примере программы такие числа преобразуются по одному, пока не будет предоставлен ввод, или покавход содержит что-то кроме пробела или числа.Например, любая буква завершит программу.

Важно понимать, что когда любая из семейства функций scanf() встречает ввод, который не может быть преобразован в соответствии с запросом, этот ввод останется во входном буфере., Неконвертируемые данные не отбрасываются. Если вы хотите, вам нужно будет отбросить эти данные.(scanf("%*[\n]"); может использоваться для отбрасывания таких данных, если шаблоны преобразования начинаются с пробела. В основном это отбрасывает остальную часть входной строки, исключая символ новой строки в конце строки. * означает, что преобразование пропускается;результат нигде не сохраняется, и нет параметра, соответствующего этому преобразованию.)

Цикл строки такой же, как объяснено в начале этого ответа.

Цикл столбца отличается в дваособенности: вместо цикла от 0 до значения, меньшего длины строки в message, цикл от 0 до конца строки в message.Помните, что в C строки заканчиваются нулевым символом, '\0'.(strlen() просто считает количество ненулевых символов, пока не увидит нулевой символ.)

Цикл столбца также печатает пробел между каждой цифрой.Это просто так, что вам не нужно иметь буквенное пространство в самом массиве bigdigit[][].

"хитрой" частью в выражении bigdigit[row][message[col] - '0'] является часть message[col] - '0'.Видите ли, отдельные символы в строках на самом деле являются просто целыми числами, обычно называемыми кодами или кодовыми точками.Практически во всех наборах символов от 0 до 9 имеют непрерывный набор кодов, так что message[col] - '0' оценивается как ноль, если четвертый символ в сообщении [] - это ноль, один - одна цифра и т. Д., до девяти.

Второй 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()) и реализовать по крайней мере пробел (в bigdigit[][], я имею в виду ) и измените fputs(bigdigit[row][message[col] - '0'], stdout) обратно на оператор switch, чтобы вы могли вывести пробел. Например:

#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 соответствует количеству символов в массиве message, включая зарезервированное для нулевого символа конца строки. Это работает только если message является массивом, а не если это указатель.

(Если вы динамически выделяете память для char *message, тогда вам нужно сохранить количество символов, выделенных вами, в отдельной переменной и указать это значение fgets(). Стандартного способа определения количества символов не существует. впоследствии вы выделили указатель, в C вы должны сами отследить его, если он вам нужен.

Вторым изменением является вызов функции strcspn(line, "\r\n"). Он возвращает количество символов в line до конца строки или до любого из перечисленных символов (здесь, возврат каретки или перевод строки, два символа, которые используются для перевода строки в различных комбинациях в разных ОС), что произойдет первым.

(Иногда вы видите line[strcspn(line, "\r\n")] = '\0';, используемый для обрезки содержимого line при первом возврате каретки или переводе строки, удаляя новую строку в конце строки, которую оставляет fgets(). Это безопасно до тех пор, пока line не равно NULL и содержит строку, даже если она не содержит возврата каретки или перевода строки, потому что в этом случае strcspn() просто возвращает длину строки.)

Строка if (strcspn(line, "\r\n") < 1) может читаться как «Если в line нет символов, или первый символ - это возврат каретки или перевод строки, то» . Я мог бы написать это как if (line[0] == '\0' || line[0] == '\r' || line[0] == '\n'), но я подумал, что показывать такую ​​изящную небольшую стандартную функцию было бы уместно здесь.

Поскольку в операторе switch нет регистра default:, все остальные символы, кроме цифр и пробела (и те, которые вы добавляете, увеличиваете DIGITS и добавляете их строки в массив bigdigit[][] и выводите как новый оператор case), полностью игнорируются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...