1 (16.10.2012 11:32:28 отредактировано ShooricG)

Всем привет! ab

Начну с небольшой предыстории. bx
Когда-то давно (лет 5-7 назад), когда я учился на 1-2 курсе универа мы изучали язык программирования Си. С его пониманием у меня тогда проблем не возникало и практически все схватывал на лету: строки, массивы, указатели, функции - со всем был в ладах. По окончании 2 курса даже экзамен на 5 сдал. Но с тех пор прошло более 5 лет, и на "Сях" я больше не писал. Соответственно многое (да чего уж там таить - практически все) уже позабыто.

И вот, по истечении этих более 5 лет, я обнаруживаю, что на работе бывает появляется немного свободного времени. Чтобы даром его не терять, решил вспомнить тот самый Си. В связи с чем купил книгу "Язык программирования С" (Б.Керниган, Д.Ритчи; 2-е издание, "Вильямс", 2012г.) и установил на рабочий комп в (к сожалению) виртуалку Debian Wheezy.
Начал читать книгу с интересом. И вот, на середине первой главы (1.6 Массивы) встал в ступор при выполнении упражнения.

Упражнение 1.13: Напишите программу для вывода гистограммы длин слов во входном потоке. Построить гистограмму с горизонтальными рядами довольно легко, а вот с вертикальными столбцами труднее.

Так вот, в чем трудность: горизонтальную гистограмму построить довольно-таки легко, но вот с вертикальной - ступор! :angry:  Никак не удается ее правильно вывести на экран.

В книге 1 глава называется "Вводный урок" - соответственно ни о каких двумерных массивах речи не идет. Возникает вопрос - как решить данную задачу, используя только одномерный массив?

P.S.: во вложении два варианта моих мучений - 1-ый с одномерным массивом, 2-ой с двумерным массивом. Но по условию нужно дорабатывать первый вариант!

P.P.S.: заранее благодарен за любые наставления и тычиния носом! ag

+ открыть спойлер

Вариант решения с одномерным массивом:

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

#define IN 1     /* in word */
#define OUT 0    /* out of word */

/* diagram of input's symbols */

main()
{
    int c, s, nw, i, j, state, max;
    int diagram[20], invertion[20];

    system("clear");

    printf("Enter text with some words\n\n");

    state = OUT;
    s = nw = j = 0;

    /* determine the number of words */

    while ((c = getchar()) != EOF) {

    /* symbol is not from word */
    if (c == ' ' || c == '\n' || c == '\t')
        state = OUT;

    /* symbol is from word and ++word*/
    else if (state == OUT) {
        state = IN;
        ++nw;
        }

    /* number of symbols in a word */
    if (state == IN)
        ++s;

    /* if number of symbols in a word not equal 0 (more that 0)
    then j's element in array assign number of symbols in a word;
    after this for the next word number of symbols for a start
    is equal 0 and enlarge number array's element */
    else if (s != 0) {
        diagram[j] = s;
        s = 0;
        ++j;
        }
    }

    printf("\n");

    /* horisontal diagram */

    for (j = 0; j < nw; ++j) {
    for (s = 0; s < diagram[j]; ++s)
        printf("*");
    printf("\n");
    }

    printf("\n");

    /* determine the maximum lenght of the words */

    for (j = 0; j < nw; ++j)
    if (max < diagram[j])
        max = diagram[j];

    /* inverting number of symbols to the vertical diagram
    with 1 and 0 */

    for (s = 0; s < max; ++s) {
    invertion[s] = 0;
    for (j = 0; j < nw; ++j) {
        if (diagram[j] != 0) {
        invertion[s] = ((invertion[s])*10 + 1);
        diagram[j]--;
        }
        else if (diagram[j] == 0)
        invertion[s] = (invertion[s])*10;
        }
    }

    printf("\n");

    /* printing vertical diagram with '*' and ' ' */

    for (s = 0; s < max; ++s) {
    for (j = 0; j < nw; ++j) {
        if ((invertion[s] / (10^(nw - j))) == 1)
        printf("*");
        else if (((invertion[s] / (10^(nw - j))) % 10) == 1)
        printf("*");
        else if ((invertion[s] / (10^(nw - j))) == 0)
        printf(".");
        else if (((invertion[s] / (10^(nw - j))) % 10) == 0)
        printf(".");
        }
    printf("\n");
    }

}
+ открыть спойлер

Вариант решения с двумерным массивом:

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

#define IN 1     /* in the word */
#define OUT 0    /* out of the word */

/* diagram of input's symbols */

main()

{
    int nw, i, j, state, max;
    char diagram[20][20];

    system("clear");

    printf("Enter text with some words\n\n");

    state = OUT;
    nw = i = j = max = 0;

    /* determine the number of words 
    and write the words to array */

    /* nw (i) - number of words (rows);
    j - number of columns; */

    while ((i = getchar()) != EOF) {

    if (i == ' ' || i == '\n' || i == '\t') {
        state = OUT;
        j = 0;
        }

    else if (state == OUT) {
        state = IN;
        ++nw;
        }

    if (state == IN) {
        ++j;
        if (max < j)
        max = j;
        diagram[j-1][nw-1] = i;
        }

    }

    for (j = 0; j < max; ++j) {
    for (i = 0; i < nw; ++i)
        printf(" %c ", diagram[j][i]);
    printf("\n");
    }

}

2 (16.10.2012 13:05:42 отредактировано bormant)

Что-то вроде (только идея построения диаграммы по готовым данным):

#include <stdio.h>

print_vd(int ncol, int* data) {
    int i, j, max;
    max=data[0];
    for (i=1; i<ncol; i++) if (data[i]>max) max=data[i];
    for (j=max; j>0; j--) {
        for (i=0; i<ncol; i++) printf(" %c", data[i]>=j?'*':' ');
        printf("\n");
    }
}

int
main(void) {
    int testdata[] = {2, 3, 4, 5, 3, 7, 2};
    print_vd(sizeof(testdata)/sizeof(testdata[0]), testdata);
    return 0;
}
           *  
           *  
       *   *  
     * *   *  
   * * * * *  
 * * * * * * *
 * * * * * * *

3 (16.10.2012 14:05:00 отредактировано ShooricG)

bormant, спасибо!

Получилось примерно так:

+ открыть спойлер

Решение с одномерным массивом:

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

#define IN 1     /* in word */
#define OUT 0    /* out of word */

/* diagram of input's symbols */

main()
{
    int c, s, nw, i, j, state, max;
    int diagram[20], invertion[20];

    system("clear");

    printf("Enter text with some words\n\n");

    state = OUT;
    s = nw = j = 0;

    /* determine the number of words */

    while ((c = getchar()) != EOF) {

    /* symbol is not from word */
    if (c == ' ' || c == '\n' || c == '\t')
        state = OUT;

    /* symbol is from word and ++word*/
    else if (state == OUT) {
        state = IN;
        ++nw;
        }

    /* number of symbols in a word */
    if (state == IN)
        ++s;

    /* if number of symbols in a word not equal 0 (more that 0)
    then j's element in array assign number of symbols in a word;
    after this for the next word number of symbols for a start
    is equal 0 and enlarge number array's element */
    else if (s != 0) {
        diagram[j] = s;
        s = 0;
        ++j;
        }
    }

    printf("\n");

    /* determine the maximum lenght of the words */

    for (j = 0; j < nw; ++j)
    if (max < diagram[j])
        max = diagram[j];

    /* printing vertical diagram with '*' and ' ' */

    for (s = max; s > 0; --s) {
        for (j = 0; j < nw; ++j) {
            putchar(diagram[j] >= s ? '*' : ' ');
        }
        putchar('\n');
    }

}

Так же спасибо за помощь NickLion

4 (16.10.2012 16:23:44 отредактировано ShooricG)

Хотелось бы, чтобы эту тему не закрывали, т.к. наверняка в ходе прочтения книги еще наверняка возникнут вопросы, а однородные темы плодить не хочется!  bf
Спасибо!