Вертикальные гистограммы в C ++ - PullRequest
1 голос
/ 03 апреля 2012

Хорошо, я пытаюсь сделать вертикальную гистограмму из значений в файле.Приведенный ниже код работает до точки, которая печатается горизонтально, но по одной звездочке на строку, что означает наличие пробелов (очевидно).Не ищите ложного ответа, просто толчок в правильном направлении.

using namespace std;

int main()  
{
int counter;
cout<<"Please enter a number"<< "\n";
counter=0;

char *fname = "C:/Users/Jordan Moffat/Desktop/coursework/problem2.txt";
int x;

ifstream infile(fname);

while (infile >> x)
{ 
    if (x==0 && x<=10){
        cout<<"*"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\n";
        }
    else if (x>=10 && x<=20){
        cout<<"\t"<<"*"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\n";
    }
    else if (x>=20 && x<=30){
        cout<<"\t"<<"\t"<<"*"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\n";
    }
    else if (x>=30 && x<=40){
        cout<<"\t"<<"\t"<<"\t"<<"*"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\n";
    }
    else if (x>= 40 && x<=50){
        cout<<"\t"<<"\t"<<"\t"<<"\t"<<"*"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\n";
    }
    else if (x>=50 && x<=60){
        cout<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"*"<<"\t"<<"\t"<<"\t"<<"\t"<<"\n";
    }
    else if (x>=60 && x<=70){
        cout<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"*"<<"\t"<<"\t"<<"\t"<<"\n";
    }
    else if (x>=70 && x<=80){
        cout<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"*"<<"\t"<<"\t"<<"\n";
    }
    else if (x>=80 && x<=90){
        cout<<"*"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"*"<<"\t"<<"\n";
    }
    else if (x>=90 && x<=100){
        cout<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"\t"<<"*"<<"\n";

    }

}
cout<<"====================================================================================="<< "\n";   
cout<<"0-9"<<"10-19"<<"20-29"<<"30-39"<<"40-49"<<"50-59"<<"60-69"<<"70-79"<<"80-89"<<"90-100"<<"\n";
system("PAUSE");
 }

Ответы [ 6 ]

2 голосов
/ 03 апреля 2012

У вас две проблемы. Очевидно, вы хотите построить гистограмму и хотите визуализировать эту гистограмму.

Гистограмма Один из подходов к построению гистограммы требует предварительного указания количества бинов (однородной ширины), минимального значения (включительно) и максимального значения (не включительно). Затем вы можете вычислить индекс корзины, которой должен быть присвоен каждый элемент.

Вот (непроверенный) пример:

const int nbins = 10;
const double minval = .0, maxval = 100.;
std::vector<int> bins(nbins, 0);
for (double x; infile >> x; ) {
  if (x >= minval && x < maxval) {
    // note that integer rounding is probably towards zero, not towards -inf
    int idx = floor((x-minval)/(maxval-minval)*nbins);
    bins[idx]++;
  }
  else {
    // handle outlier
  }
}

Визуализация Подход, описанный в этом ответе , представляется целесообразным. Для большого количества бинов вам может потребоваться некоторая процедура нормализации, то есть масштабирование значений до диапазона [0,10] или аналогичного.

Посмотрите на этот (непроверенный) пример:

const int chart_height = 10;
const int max_count = *std::max_element(bins.begin(), bins.end());
for (int current_height = chart_height; current_height > 0; --current_height) {
    for (int count : bins) {
        const int bar_height = (count*chart_height)/max_count;
        if (bar_height < current_height)
            std::cout << "     "; // we're still above the bar
        else if (bar_height == current_height)
            std::cout << "  _  "; // reached the top of the bar
        else // bar_height > current_height
            std::cout << " | | "; // now the rest of the bar ...
    }
    std::cout << '\n';
}

С помощью небольшого количества магии и трюков вы также можете расширить ее для создания пограничной гибкой визуализации, такой как this :

   11 |              _______    _______                                   
      |             |       |  |       |                                  
      |             |       |  |       |                                  
      |             |       |  |       |                                  
      |             |       |  |       |   _______                        
    5 |             |       |  |       |  |       |                       
      |             |       |  |       |  |       |                       
      |             |       |  |       |  |       |              _______  
      |   _______   |       |  |       |  |       |   _______   |       | 
      |  |       |  |       |  |       |  |       |  |       |  |       | 
      +------v----------v----------v----------v----------v----------v-----
         3.7 - 4.3  4.3 - 4.9  4.9 - 5.6  5.6 - 6.2  6.2 - 6.8  6.8 - 7.4 
1 голос
/ 10 октября 2014

Просто развлекаюсь и тренируюсь :) введите любую последовательность цифр до 100 номеров и нажмите 0, чтобы остановить и построить график:)

#include <iostream>
#include <limits>
using namespace std;


int main()
{
    const int MAX = 100;
    int values[MAX];
    int input_number;
    int total_number =0;
    int largest_number = 0;


    for (int i = 0; i < MAX; i++)
    {
        cin >> input_number;
        if (input_number != 0)
        {
                   total_number++;
                   values[i] = input_number;
                   }
        else if (input_number == 0){
             for (int t = 0;t<total_number;t++){
                 if(values[t]>largest_number)
                 largest_number = values[t];
                 }

             for (int j = 0; j <largest_number; ++j){
             for (int i = 0; i <total_number; ++i)
                 cout << (j+values[i] >= largest_number ? '*' : ' ') ;
                 cout << endl;
             }
             break;  
        }

    }



    system ("PAUSE");
    return 0; // everything ok
}
1 голос
/ 03 апреля 2012

Чтобы сделать ваши бары по вертикали вам необходимо:

  1. получить все числа в массиве
  2. определить диапазон, то есть вычислить максимальное и минимальное значениемассив
  3. делает цикл в диапазоне , печатая строки, оставляя пробелы в столбцах, связанные со значениями, меньшими, чем текущая строка, 'изображает'.

здесьЯ предполагаю, что шаги 1 и 2 выполнены, просто покажите цикл и закрасьте некоторые детали (обратите внимание, что код не использует min и цикл из 0)

int values[] = {2,5,1,9,3}, cols = 5, max = 9;

for (int r = 0; r < max; ++r) {
    for (int c = 0; c < cols; ++c)
        cout << (r + values[c] >= max ? '*' : ' ');
    cout << endl;
}

здесь вывод

   * 
   * 
   * 
   * 
 * * 
 * * 
 * **
** **
*****
1 голос
/ 03 апреля 2012

Вы должны прочитать ваши данные в std::vector

Использовать два вложенных цикла:

  1. Цикл по строкам, которые вы печатаете, где первая строка равна "0-> 10", втораястрока "10-> 20" и т. д.
  2. Цикл по vector, если переменная больше (linecount-linenumber)*10, печать " ", иначе печать "*".

Если ваши данные идут от 0 до 100, количество строк должно быть 10.

белья - это переменная цикла из первого цикла

Мне не ясно, как ваши данные организованы в файле.Если ваш файл данных не содержит значений, в которых указано, сколько * s должен иметь каждый столбец, вы должны сначала рассчитать это.

0 голосов
/ 03 апреля 2012

(аналогично ответу Kleist)

  1. Создать массив для определения оси Y (или формулы, основанной на индексе)
  2. Считать числа изсохраните файл в контейнере, чтобы вы также знали количество значений (ось x)
  3. двойной цикл, 1 для оси y, 1 для оси x и выясните, должна ли быть звездочканапечатано, на основе 1.

Позвольте счетчику оси y уменьшиться, чтобы ваши бары выросли.

0 голосов
/ 03 апреля 2012

Я предполагаю, что только один цикл для каждого, если написанное вами условие является достаточным.

И я согласен с Kleist, что цикл по переменным и печать * для каждой переменной

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