Гистограмма (С, K&R)

Модератор: Модераторы разделов

Current_Density
Сообщения: 773
Статус: Участник

Гистограмма

Сообщение Current_Density »

Нужно подсчитать частоту с которой в вводимом тексте встречаются цифры (0-9) и нарисовать вертикальную гистограмму.
Потом то-же самое сделать с буквами.

Пока сделал только цифры, поругайте код пожалуйста.

Код: Выделить всё

#include <stdio.h>

main() /*подсчет числа появлений каждой цифры и
         построение гистограммы*/
{
      int  c, i, n, max, s;
      int  ndigit[10];
      char nstars[1000];
/* обнуляем массив */
      for (i = 0; i < 10; ++i)
      ndigit[i] = 0;
/* заполняем массив ndigit[10] */
   while ((c = getchar()) != EOF)
         if (c >= '0' && c <= '9')
         ++ndigit[c-'0'];
/* выводим его содержимое */
printf("\nгистограмма\n");
     for (i = 0; i < 10; ++i)
     printf(" %d", ndigit[i]);
   printf("\n");
/* ищем максимум max в массиве digit[10]*/
     max = ndigit[0];
   for (i = 1; i <= 9; ++i)
        if ((max -ndigit[i]) <= 0)
        max = ndigit[i];
/* вычисляем длинну массива со звездочками n */
n = max * 10;
/* заполняем массив со звездочками  nstars[s] */
  s = 0;
  while (s < n)
    for (i = 9; i >= 0; --i){
        if (ndigit[i] != 0){
        nstars[s] = '*';
        --ndigit[i];
       }
       else nstars[s] = ' ';
       ++s;
    }
/* выводим его содержимое кусками по 10
с переводом строки после каждого десятка*/
  i = 1;
  for (s = (n - 1); s > 0; --s){
      if (i != 10){
      printf(" %c", nstars[s]);
      ++i;
      }
      else {
      i = 1;
      printf("\n");
      }
  }
/* выводим цифры от 0 до 9 внизу для наглядности*/
     printf("\n");
     for (i = 0; i < 10; ++i)
     printf(" %d", i);
     printf("\n");
}


Подозреваю что куски

Код: Выделить всё

/* заполняем массив со звездочками  nstars[s] */
  s = 0;
  while (s < n)
    for (i = 9; i >= 0; --i){
        if (ndigit[i] != 0){
        nstars[s] = '*';
        --ndigit[i];
       }
       else nstars[s] = ' ';
       ++s;
    }

и

Код: Выделить всё

/* выводим его содержимое кусками по 10
с переводом строки после каждого десятка*/
  i = 1;
  for (s = (n - 1); s > 0; --s){
      if (i != 10){
      printf(" %c", nstars[s]);
      ++i;
      }
      else {
      i = 1;
      printf("\n");
      }
  }

можно покрасивше организовать, но как - не могу придумать.
Спасибо сказали:
Аватара пользователя
Uncle_Theodore
Сообщения: 3339
ОС: Slackware 12.2, ArchLinux 64

Re: Гистограмма

Сообщение Uncle_Theodore »

Я бы сделал гистограмму не вертикальную, а горизонтальную. Вот такую

0 *************
1 *******
2 *
3 **************

Ну и так далее. Тогда никакого массива звездочек не нужно, и отпадает куча головной боли. Просто после каждой цифры надо печатать столько звездочек, сколько указано в массиве ndigit.
Спасибо сказали:
Current_Density
Сообщения: 773
Статус: Участник

Re: Гистограмма

Сообщение Current_Density »

Uncle_Theodore
Керниган и Ритчи хотят чтобы я сделал и горизонтальную и вертикальную.
Горизонтальную я сделал, сделал вертикальную перевернутую (звездочки свешиваются сверху вниз), теперь вот эта.
Она строится, все нормально, но как-то код мне не очень нравится, а что бы такого в нем улучшить не приходит в голову.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Гистограмма

Сообщение promov »

Какое упражнение ты делаешь? 1.14? Я их делал и программы сохранял. Обратившись к своей программе, мне проще будет понять о чём идёт речь. Но для этого я должен знать номер выполняемого упражнения.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Current_Density
Сообщения: 773
Статус: Участник

Re: Гистограмма

Сообщение Current_Density »

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

Только не длины слов считаю, а количество цифр, то есть как в примере перед заданием. Длины слов потом.
Спасибо сказали:
Аватара пользователя
BlackStar
Сообщения: 1338
Статус: We are all Kosh
ОС: Fedora 10

Re: Гистограмма

Сообщение BlackStar »

Поиск максимума подозрителен
Current_Density писал(а):
09.04.2008 16:05
* ищем максимум max в массиве digit[10]*/
max = ndigit[10];
for (i = 1; i <= 9; ++i)
if ((max -ndigit[i]) <= 0)
max = ndigit[i];

т.к. int ndigit[10] предпологает индексы 0..9. И зачем в условии нужно делать вычитание а не просто сравнить max и ndigit[i] ?
LightLang Team
Спасибо сказали:
Current_Density
Сообщения: 773
Статус: Участник

Re: Гистограмма

Сообщение Current_Density »

BlackStar

Код: Выделить всё

max = ndigit[10];

опечатка, хотел ndigit[0].
И зачем в условии нужно делать вычитание а не просто сравнить max и ndigit[i] ?

спасибо, не догадался просто.

Максимум определяется правильно даже с этой опечаткой. Видимо поэтому и не заметил.

upd
Ага, он определяется правильно только если максимум не ndigit[0].
Спасибо сказали:
Аватара пользователя
Uncle_Theodore
Сообщения: 3339
ОС: Slackware 12.2, ArchLinux 64

Re: Гистограмма

Сообщение Uncle_Theodore »

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

Код: Выделить всё

for(k=max;k>0;k--)
      for(i=0;i<10;i++)
           if(ndigit[i] >=k) printf("*"); else printf(" ");

А потом -- линию из цифирь в самом низу...
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5422
ОС: Gentoo

Re: Гистограмма

Сообщение /dev/random »

Uncle_Theodore писал(а):
09.04.2008 20:22
Ну хорошо, как бы я печатал вертикальную гистограмму... Я бы "печатал" не звездочки, а пропуски звездочек. То есть,

Код: Выделить всё

for(k=max;k>0;k--)
      for(i=0;i<10;i++)
           if(ndigit[i] >=k) printf("*"); else printf(" ");

А потом -- линию из цифирь в самом низу...

Вывода перевода строк не хватает
Спасибо сказали:
Аватара пользователя
Uncle_Theodore
Сообщения: 3339
ОС: Slackware 12.2, ArchLinux 64

Re: Гистограмма

Сообщение Uncle_Theodore »

/dev/random писал(а):
09.04.2008 21:47
Вывода перевода строк не хватает

Угум. Сглупил, на коленке писал... :) Соответственно, так:

Код: Выделить всё

for(k=max;k>0;k--){
      for(i=0;i<10;i++)
           if(ndigit[i] >=k) printf("*"); else printf(" ");
          printf("\n");
}
Спасибо сказали:
Current_Density
Сообщения: 773
Статус: Участник

Re: Гистограмма

Сообщение Current_Density »

Uncle_Theodore
Да, действительно пробелами гораздо лучше.
И с ещё одним массивом связываться не надо. И строк в программе стало почти в два раза меньше. :)
Спасибо сказали:
Аватара пользователя
uptime
Сообщения: 1661
Статус: Drinker with computing problems
ОС: kubuntu 8.04

Re: Гистограмма

Сообщение uptime »

Замечание по стилю.
Численные константы в тексте на желательны.

Код: Выделить всё

      int  ndigit[10];
      char nstars[1000];

Т.е. в этом куске размерности массивов лучше определить макросами.
Тогда и ошибки бы не случилось.
The answer, my friend, is blowin' in the wind.
The answer is blowin' in the wind.
Спасибо сказали:
Current_Density
Сообщения: 773
Статус: Участник

Re: Гистограмма

Сообщение Current_Density »

uptime
Макросами в смысле через
?
Понял, спасибо.
Спасибо сказали: