пятница, 3 января 2014 г.

Упражнение 1.13.

Напишите программу, печатающую гистограммы длин вводимых слов. Гистограмму легко рисовать горизонтальными полосами. Рисование вертикальными полосами — более трудная задача.


Печать горизонтальной гистрограммы длин слов
$ vim ex_1_13.c

#include <stdio.h>

#define IN 1
#define OUT 0

int main(void)
{
        /* ограничим длину слова в 10 символов */
        int c, state, i, nc, ndigit[11], j;
        state = OUT;
        nc = 0;

        /* заполняем массив нолями */
        for (i = 0; i < 11; ++i)                
                ndigit[i] = 0;

        while ((c = getchar()) != EOF)
        {
                ++nc;                          /* новый символ */

                if (c == ' ' || c == '\n' || c == '\t')
                {
                        state = OUT;            /* конец слова */
                        /* символ разделитель не принадлежит слову */
                        --nc;
                        if (nc <= 10)  /* проверка длины слова */
                                ++ndigit[nc];/* прирост гистрограммы */
                        nc = 0; /* сбрасываем счетчик символов */
                }

                else if (state == OUT)
                {
                        state = IN;            /* начало слова */
                }
        }

        /* Печать горизонтальной гистрограммы длин слов */

        /* Внешний цикл. Проход по массиву ndigit[11] сверху вниз,
         * от ndigit[1] до ndigit[10].
         * Слово - минимум один символ. Поэтому цикл начинаем с единицы,
         * не интересует нулевая позиция в массиве.
         * Ограничение цикла - 10. Из условия ограничения
         * длины слова в 10 символов */

        for (i = 1; i < 11; ++i)
        {
                /* вывод параметров гистрограммы - длин (от 1 до 10) */
                printf("%d: ", i);
                /* Внутренний цикл. Обработка конкретного элемента
                 * массива и вывод гистрограммы длин слов.
                 * Слово - минимум символ. Начинаем со значения единицы.
                 * Ограничением цикла может быть только значение ndigit -
                 * количество слов определенной длины.
                 * А в роли значения длины выступает индекс i */

                for (j = 1; j <= ndigit[i]; ++j)
                        printf("#");
                printf("\n");
        }

        return 0;
}


$ cc -g -O0 -Wall -o a.out ex_1_13.c
$ ./a.out
test
maximum
foo
C
language
sony
darkstar
start
stop
Russia
programming
characters
<Ctrl>+<D>
1: #
2:
3: #
4: ###
5: #
6: #
7: #
8: ##
9:
10: #

Печать вертикальной гистрограммы длин слов
$ vim ex_1_13_4.c
#include <stdio.h>

#define IN 1
#define OUT 0

int main(void)
{
        /* ограничим длину слова в 10 символов */
        int c, state, i, nc, ndigit[11], j;
        int maximum = 0;
        state = OUT;
        nc = 0;

        for (i = 0; i < 11; ++i) /* заполняем массив нолями */
                ndigit[i] = 0;

        while ((c = getchar()) != EOF)
        {
                ++nc;   /* новый символ */

                if (c == ' ' || c == '\n' || c == '\t')
                {
                        state = OUT;            /* конец слова */
                        --nc;/* "крайний" символ не входит в слово */
                        if (nc <= 10) /* проверка длины слова */
                        {
                                ++ndigit[nc];/* прирост гистрограммы */
                                if (ndigit[nc] > maximum)
                     /* максимум по вертикали для гистрограммы */
                                        maximum = ndigit[nc];
                        }
                        nc = 0; /* сбрасываем счетчик символов */
                }

                else if (state == OUT)
                {
                        state = IN;             /* начало слова */
                }
        }

        /* Печать вертикальной гистрограммы длин слов */

        /* Внешний цикл. Проход сверху вниз по количеству символов. 
         * Начинается со значения максимального
         * кол-ва символов в слове. Ограничением служит единица,
         * слово - минимум один символ */

        for (i = maximum; i >= 1; --i)
        {
                /* Проход по элементам массива. Слева на право.
                 * От одного символа в слове до десяти */
                for (j = 1; j <= 10; ++j)
                {
                        /* Если позиция в массиве (количество
                         * символов в слове)больше количества
                         * слов, то ничего не выводим (слов
                         * длиной i "еще" нет) */
                        if (i > ndigit[j])
                                printf("  ");
                        else
                                /* если такие слова появляются
                                 * печатаем гистрограмму */
                                printf("# ");
                }
                printf("\n");
        }

        for (i = 1; i < 11; ++i)
                printf("%d ", i);

        printf("\n");

        return 0;
}


$ cc -g -O0 -Wall -o a.out ex_1_13_4.c
$ ./a.out
test
maximum
foo
C
language
sony
darkstar
start
stop
Russia
programming
characters
<Ctrl>+<D>
      #
      #       #
#   # # # # # #   #
1 2 3 4 5 6 7 8 9 10

Комментариев нет:

Отправить комментарий