Gráfica de barras horizontales en la terminal con C++

Ya en un post anterior había escrito sobre la STL de C++; el código siguiente simula una gráfica de barras horizontales en modo texto y aprovecho para ejemplificar el uso de algunas funciones y algoritmos de la STL.
El programa consiste en pedirle al usuario que capture números positivos y los va almacenando en un vector, para terminar la captura el usuario debe introducir un número negativo. Una vez terminada la captura, se copian los valores almacenados en el vector a otro vector y después se ordenan para que en el vector original los números queden en el mismo orden en que el usuario los fue capturando. Esta parte de copiar los valores de un vector a otro y ordenar los valores en el segundo vector no es necesaria para el funcionamiento del programa, sólo lo pongo para ejemplificar com se haría esto usando la STL.

En el programa utilizo funciones de la STL para encontrar el valor menor y el valor mayor en el vector original sin tener que ordenarlo.

Aquí está el código
Archivo grafica_barrash.cpp

#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>

using namespace std;

int main()
{
 int i_x=0, i_y=0;
 double dbl_valor=0, dbl_escala=0;
 vector<double> v_valores, v_ordenados;
 vector<double>::iterator v_valores_it, v_ordenados_it;
 vector<double>::const_iterator menor_it, mayor_it, valor_it;

 cout << "Teclee un número, (cualquier número negativo para terminar):" << endl;
 /* Mientras el usuario teclee números positivos (incluido el cero), guardamos en el vector
    v_valores los números que el usuario va tecleando
 */
 while (dbl_valor >= 0)
       {
        cin >> dbl_valor;
        if (dbl_valor >= 0)
            v_valores.push_back(dbl_valor);
       }

 cout << endl << "Estos son los números que Ud. introdujo:" << endl;
 // Muestra los valores almacenados en el vector v_valores
 for ( v_valores_it = v_valores.begin(); v_valores_it != v_valores.end(); v_valores_it++)
      cout << *v_valores_it << endl;

 // Hace el vector v_ordenados del mismo tamaño que el vector v_valores
 v_ordenados.resize (v_valores.size());
 // Copia los valores del vector v_valores al vector v_ordenados
 copy (v_valores.begin(), v_valores.end(), v_ordenados.begin());
 // Ordena el vector v_ordenados
 std::sort(v_ordenados.begin(), v_ordenados.end());

 cout << endl << "Estos son los números ordenados:" << endl;
 // Muestra los valores almacenados en el vector v_ordenados
 for ( v_ordenados_it = v_ordenados.begin(); v_ordenados_it != v_ordenados.end(); v_ordenados_it++)
      cout << *v_ordenados_it << endl;

 menor_it = min_element(v_valores.begin(), v_valores.end());
 mayor_it = max_element(v_valores.begin(), v_valores.end());

 cout << endl << "El valor menor es: " << *menor_it << endl;
 cout << "El valor mayor es: " << *mayor_it << endl;

 // Obtiene la escala
 dbl_escala = *mayor_it - *menor_it;
 cout << "La escala es: " << dbl_escala << endl << endl;

 for (i_x=0; i_x<8; i_x++)
      cout << " ";

 cout << ceil(*menor_it);
 for (i_x=0; i_x<=34; i_x++)
      cout << " ";
 cout << ceil((dbl_escala/2)+*menor_it);
 for (i_x=0; i_x<=34; i_x++)
      cout << " ";
 cout << ceil(*mayor_it);
 cout << endl;
 for (i_x=0; i_x<8; i_x++)
      cout << " ";
 cout << "|";
 for (i_x=0; i_x<=34; i_x++)
      cout << " ";
 cout << "|";
 for (i_x=0; i_x<=34; i_x++)
      cout << " ";
 cout << "|" << endl;

 // Dibuja las barras
 i_x=1;
 for ( v_valores_it = v_valores.begin(); v_valores_it != v_valores.end(); v_valores_it++)
     {
      cout << "Valor"<< i_x;
      /* Si el valor de x es de un sólo dígito, deja 2 espacios antes de empezar a dibujar la barra, de lo contrario
         deja sólo uno
      */
      cout << (i_x < 10 ? "  " : " ");
      valor_it = v_valores_it;
      for (i_y=1; i_y<= ((double)(*valor_it - *menor_it)/dbl_escala)*72+1; i_y++)
           cout << "*";
      cout << endl;
      i_x++;
     }

 return 0;
}

A continuación pongo una captura de pantalla
Como se puede ver, la gráfica muestra los valores como fueron introducidos por el usuario, así que:
valor1 = 100, valor2 = 40, valor3 = 75, valor4 = 50,valor5 = 25, valor6 = 30, valor7 = 10

Esto porque recibí un correo de una persona que dijo ser estudiante y me reclamaba que “estaba todo mal” y le habían puesto 1 de calificación.
En primer lugar, como la captura de pantalla demuestra, el programa funciona bien; en segundo lugar, este blog no es para que eviten hacer su tarea si son estudiantes; y en tercer lugar, las críticas constructivas a cualquier post que publique, son bienvenidas, pero si como en este caso, sólo escribe tonterías como “esta todo mal” y no aporta argumentos de en que se basa para hacer tal afirmación, es obvio que voy a ignorarlo.
Por último, mis post generalmente serán para personas con conocimientos mínimos de programación, por lo menos que sepan deducir un algoritmo a partir del código fuente que leen.

Etiquetas: , ,

3 comentarios to “Gráfica de barras horizontales en la terminal con C++”

  1. Jimmy Quiroga Says:

    me gustan sus conclusiones…. y bueno el tip sobre el codigo para un algoritmo que muestre representaciones de barras. Gracias por el Post.

  2. Cristian Feldman Says:

    un ejemplo bien explicado gracias y no entendi el porque del 34? sera por la resolución de la terminal?

    • rtmex Says:

      La idea es que la gráfica no ocupe más de 80 columnas. Desde la palabra Valorxx hasta el último asterisco que forma la barra que representa el valor mayor. Los ciclos en donde x va de 0 a 34 es para dejar el mismo espacio entre las marcas del valor menor, el valor de enmedio y el valor mayor.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


A %d blogueros les gusta esto: