C ++中的垂直条形图

时间:2012-04-03 06:30:52

标签: c++ graph bar-chart

好的,我正在尝试根据文件中的值制作垂直条形图。下面的代码适用于某一点,并且水平打印,但每行一个星号,这意味着有空格(显然)。没有找到一个勺子的答案,只是朝着正确的方向推进。

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 个答案:

答案 0 :(得分:2)

你有两个问题。显然你想要建立一个直方图,你想要想象这个直方图。

<强>直方图 构建直方图的一种方法要求您预先指定容器的数量(均匀宽度),最小值(包括)和最大值(不包括)。然后,您可以计算每个项目应分配到的bin的索引。

这是一个(未经测试的)示例:

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
  }
}

<强>可视化 this answer中描述的方法似乎是恰当的。对于较大的bin计数,您可能需要一些规范化过程,即将值缩放到[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 :(得分:1)

您应该将数据读入std::vector

使用两个嵌套循环:

  1. 在第一行为“0-&gt; 10”,第二行“10-&gt; 20”等打印的行上循环。
  2. 循环播放vector,如果变量大于(linecount-linenumber)*10,请打印" ",否则打印"*"
  3. 如果您的数据从0到100,则行数应为10.

    linenumber是第一个循环的循环变量

    我不清楚您的数据在文件中的组织方式。如果您的数据文件不包含表示每列应有多少*的值,则应首先计算该值。

答案 2 :(得分:1)

要使你的栏垂直,你需要:

  1. 获取数组中的所有数字
  2. 确定范围,即计算数组的最大值和最小值
  3. 范围上创建一个循环,打印行,在列上留下空格,使其低于当前行的“描绘”值。
  4. 这里我假设步骤1&amp; 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;
    }
    

    输出

       * 
       * 
       * 
       * 
     * * 
     * * 
     * **
    ** **
    *****
    

答案 3 :(得分:1)

玩得开心,练习:) 输入您想要最多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
}

答案 4 :(得分:0)

我猜每个if条件只有一个循环就足够了。

我同意Kleist关于变量的循环和每个变量的打印*

答案 5 :(得分:0)

(类似于Kleist的答案)

  1. 创建一个数组来定义y轴(或基于索引的公式)
  2. 从容器中保存的文件中读取数字,因此您也知道值的数量(x轴)
  3. 双循环,1表示y轴,1表示x轴,并根据1确定是否必须打印星号。
  4. 让y轴计数器递减,因此你的柱子正在上升。