Alinear texto (Solucionado)

Iniciado por nolasco281, 24 Marzo 2014, 04:45 AM

0 Miembros y 1 Visitante están viendo este tema.

nolasco281

Hola a todos como esta.

Mi pregunta es la siquiente estoy trabajando con archivos que quiero alinear o darle formato a los datos.

estoy intentando con la libreria iomanip

ya use el setw(int), para dar le espacio entre datos, ya intente el right y el left pero nada no los alinea talves alquien sabe de alguna funcion que haga este tipo de instruccion.

dejo una imagen.



como ven no se aliena el texto. : (
Lo que se puede imaginar... se puede programar.

eferion

y el código que genera esta salida es...

Yoel Alejandro

Bueno, hace falta indicar que tipo de justificación quieres para los datos dentro de la columna, si a la izquierda, al centro o a la derecha. Yo voy a suponer que a la izquierda, por ser lo más usual. La solución que voy a proponer la he usado varias veces en mis programas, y no usa nada sofisticado, de hecho se puede compilar en C.

La idea es calcular el mayor ancho entre todos los campos de cada columna, e ir depositando el resultado en un arreglo ColumnsWidth[] de "anchos de columna". Luego, al imprimir los campos, pones al final los espacios en blanco necesarios para completar el ancho establecido para esa columna. Supuse también dos espacios adicionales entre columnas, sino aparece todo pegado.
Código (cpp) [Seleccionar]

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

/* Imprimir una tabla alineada en columnas, con justificación a la izquierda
* By Yoel, xD */
int main() {

   int i, j;
   int ColumnsWidth[4];
   size_t width;

   /* Contenido de la tabla, pones luego el código que la genera */
   char *tabla[2][4] = {{"Hacker", "Perro", "Labrador", "Macho"},
      {"Fugi", "Camaleon", "Silvestre", "Hembra"}
   };
   char *titulos[4] = {"Nombre", "Animal", "Raza", "Sexo"};

   for ( j = 0; j < 4; j++ ) {
      ColumnsWidth[j] = 0;
      /* calcula el mayor ancho entre todos los campos de la columna j */
      if ( ( width = strlen(titulos[j]) ) > ColumnsWidth[j] )
         ColumnsWidth[j] = width;
      for ( i = 0; i < 2; i++ )
         if ( ( width = strlen(tabla[i][j]) ) > ColumnsWidth[j] )
            ColumnsWidth[j] = width;
      /* dos espacios adicionales */
      ColumnsWidth[j] += 2;
   }

   /* Ahora luego de imprimir cada palabra, colocas espacios en blanco hasta completar
    * el ancho que debe tener la columna, más dos espacios adicionales */
   for ( j = 0; j < 4; j++ ) {
      width = strlen( titulos[j] );
      printf( "%s", titulos[j] );
      while ( width++ < ColumnsWidth[j] ) putchar(' ');
   }
   printf( "\n\n" );
   for ( i = 0; i < 2; i++ ) {
      for ( j = 0; j < 4; j++ ) {
         width = strlen( tabla[i][j] );
         printf( "%s", tabla[i][j] );
         while ( width++ < ColumnsWidth[j] ) putchar(' ');
      }
      printf( "\n" );
   }

   return 0;
}


Salida:

Nombre  Animal    Raza       Sexo   

Hacker  Perro     Labrador   Macho   
Fugi    Camaleon  Silvestre  Hembra


¿Era lo que querías? Si vas a compilar en C++, cambia <stdlib.h>, <stdio.h>, <string.h> por <cstlib>, <cstdio>, <iostream>, y los respectivos printf() por instrucciones de flujo cout.
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

eferion

Presuponiendo que el ancho va a ser fijo es más sencillo usar printf


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

int main()
{
int i, j;
int ColumnsWidth[4] = { 10, 10, 20, 10 };

/* Contenido de la tabla, pones luego el código que la genera */
char *tabla[2][4] = { {"Hacker", "Perro", "Labrador", "Macho"},
                       {"Fugi", "Camaleon", "Silvestre", "Hembra"} };

char *titulos[4] = {"Nombre", "Animal", "Raza", "Sexo"};

char config[8];
int total = 0;
for ( j = 0; j < 4; j++ )
{
   sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
   printf( config, titulos[ j ] );
   total += ColumnsWidth[ j ];
}

putchar( '\n' );

while ( total )
{
   putchar( '-' );
   total--;
}

putchar( '\n' );

for ( i = 0; i < 2; i++ )
{
   for ( j = 0; j < 4; j++ )
   {
     sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
     printf( config, tabla[ i ][ j ] );
   }
   printf( "\n" );
}

return 0;
}


Y bueno, ya puestos no es complicado adaptar este código a anchos variables.


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

int main()
{
int i, j;
int ColumnsWidth[4] = { 0 };

/* Contenido de la tabla, pones luego el código que la genera */
char *tabla[2][4] = { { "Hacker", "Perro", "Labrador", "Macho" },
                       { "Fugi", "Camaleon", "Silvestre", "Hembra" } };

char *titulos[4] = { "Nombre", "Animal", "Raza", "Sexo" };

for ( j = 0; j < 4; j++ )
{
   size_t width = strlen( titulos[ j ] );
   if ( width > ColumnsWidth[ j ] )
     ColumnsWidth[ j ] = width;

   for ( i = 0; i < 2; i++ )
   {
     width = strlen( tabla[ i ][ j ] );
     if ( width > ColumnsWidth[ j ] )
       ColumnsWidth[ j ] = width;
   }

   ColumnsWidth[ j ] += 2;
}

char config[8];
int total = 0;
for ( j = 0; j < 4; j++ )
{
   sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
   printf( config, titulos[ j ] );
   total += ColumnsWidth[ j ];
}

putchar( '\n' );

while ( total )
{
   putchar( '-' );
   total--;
}

putchar( '\n' );

for ( i = 0; i < 2; i++ )
{
   for ( j = 0; j < 4; j++ )
   {
     sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
     printf( config, tabla[ i ][ j ] );
   }
   printf( "\n" );
}

return 0;
}


He aprovechado tu código yoel_alejandro para poner mi idea... estoy un poco apurado de tiempo. Espero que no te importe.

leosansan

#4

Con ancho variable pero haciendo uso de las opciones de la función printf:

Código (cpp) [Seleccionar]

Nombre  Animal    Raza       Sexo    Color      Edad  Servicio          Costo

Hacker  Perro     Labrador   Macho   Cafe       3     Servicio Simple   600

Fugi    Camaleon  Silvestre  Hembra  Muticolor  8     Servicio Premium  1200


Process returned 0 (0x0)   execution time :  0.023 s
Press any key to continue.


Código (cpp) [Seleccionar]
#include <stdio.h>
#include <string.h>

int main() {
int i, j,mayor ,ancho[8]={0};
 char *tabla[2][8] = {{"Hacker", "Perro", "Labrador", "Macho", "Cafe", "3", "Servicio Simple", "600"},
     {"Fugi", "Camaleon", "Silvestre", "Hembra", "Muticolor", "8",  "Servicio Premium", "1200"}};
 char *titulos[8] = {"Nombre", "Animal", "Raza", "Sexo", "Color", "Edad", "Servicio", "Costo"};
 for ( i = 0; i < 1; i++ )
   for ( j = 0; j < 8; j++ ){
     if ((mayor= strlen(tabla[i][j])>strlen(tabla[i+1][j]) ? strlen(tabla[i][j]):strlen(tabla[i+1][j]))>(strlen(titulos[j])))
       ancho[j]=mayor;
     else
       ancho[j]=strlen(titulos[j]);
   }
 for ( j = 0; j < 8; j++ )
 printf( "%-*s", ancho[j]+2, titulos[j]);
 printf( "\n\n" );
 for ( i = 0; i < 2; i++ ) {
   for ( j = 0; j < 8; j++ ) {
   printf( "%-*s", ancho[j]+2,tabla[i][j] );
   }
   printf( "\n\n" );
 }
  return 0;
}


¡¡¡¡ Saluditos! ..... !!!!



nolasco281

#5
Hola primero comentando a lo que indica eferion del codigo.

Código (cpp) [Seleccionar]
// Almacenar datos en archivo.
        archivo << nombreAni << setw(15)
                << tipoAnimalAni << setw(15)
                << razaAni       << setw(15)
                << sexoAni       << setw(15)
                << colorAni      << setw(15)
                << edadAni       << setw(15);


Seria demasiado si lo pongo todo. ahora probare lo que comenta yoel y leosansan y comento luego como me fue.

saludos y gracias por contestar.




Hola ya lo logre. agradezco mucho por su ayuda era tan facil como hacer lo siquiente

Código (cpp) [Seleccionar]
archivo << setw(10) << "Nombre" << setw(15) << "Animal" << setw(15) << "Raza" << setw(15)
            << "Sexo" << setw(15) << "Color" << setw(15) << "Edad" << setw(23)
            << "Servicio" << setw(16) << "Costo" << endl << endl;


Código (cpp) [Seleccionar]
// Almacenar datos en archivo.
         archivo << setw(10) << nombreAni << setw(15)
                 << right << tipoAnimalAni << setw(15)
                 << razaAni       << setw(15)
                 << sexoAni       << setw(15)
                 << colorAni      << setw(15)
                 << edadAni;




el de servicio y costo esta en otra clase asi que por eso no se ve aca.

Saludos y muchas gracias no queria complicarmela con los for.
Lo que se puede imaginar... se puede programar.

Yoel Alejandro

Bueno, nolasco las soluciones que te dimos eran usando herramientas elementales. Claro que también se puede con los métodos más avanzados de manipulación de flujo E/S de C++.

Muy creativo tu método eferion, usar sprintf() para crear la cadena de formato que luego es pasada a printf(). Y por supuesto que no me molesta que hayas tomado mi idea, e incluso haberla mejorado  :D

Amigo leosansan, si me permites la opinión me parece bien tu código pero está como "críptico", me costó leerlo. Es como si tratara de meter varias cosas en una sola, y no se hasta que punto ese estilo puede resultar claro para un tercero. ¿Por qué no lo haces un poquito más "despejado"?
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

leosansan

#7
La idea es sencilla a la vez que ingeniosa.

Se trata de "calcular para cada columna el ancho" o largo de la mayor cadena de dicha columna. Esto hay que hacerlo para cada una de las 8 columnas por lo que uso un array para guardar esos largos y/o anchos, "ancho[8]".

Una vez calculados los anchos uso una opción de printf, "%-*s" donde el signo menos es para que alinee a la izquierda y el "*" es para incluir el ancho que se introduce como primer argumento del printf y así cada columna ocupa un ancho especifico, añadiendo +2 a ancho[j] en el printf para que ademas deje dos espacios en blanco.

Calculé el ancho haciendo uso del "operador condicional o ternario", más que nada porque es una de las primeras cosas que se ve al empezar el C, al menos a mi me paso, y que sin embargo no se le suele dar mucha utilidad. Suele acortar los códigos aunque reconozco que para los que se inician en el lenguaje es más fácil no usarlo y hacer uso de "if" y compañía.

Aquí dejo una versión de lo mismo sin el mencionado operador condicional y espero que ahora haya quedado clara la idea básica del método que, como comenté al principio, me pareció ingeniosa a la vez que sencilla, de ahí que el código resultante fuera tan "cortito" .


Código (cpp) [Seleccionar]
#include <stdio.h>
#include <string.h>

int main() {
int i, j,mayor=0 ,ancho[8]={0};
 char *tabla[2][8] = {{"Hacker", "Perro", "Labrador", "Macho", "Cafe", "3", "Servicio Simple", "600"},
     {"Fugi", "Camaleon", "Silvestre", "Hembra", "Muticolor", "8",  "Servicio Premium", "1200"}};
 char *titulos[8] = {"Nombre", "Animal", "Raza", "Sexo", "Color", "Edad", "Servicio", "Costo"};
 for ( i = 0; i < 1; i++ )
   for ( j = 0; j < 8; j++ ){
     if (strlen(tabla[i][j])>mayor)
         mayor = strlen(tabla[i][j]);
     if (strlen(tabla[i+1][j])>mayor)
         mayor = strlen(tabla[i+1][j]);
     if (strlen(titulos[j])>mayor)
         mayor = strlen(titulos[j]);
     ancho[j] = mayor;
     mayor=0;
   }
 for ( j = 0; j < 8; j++ )
   printf( "%-*s", ancho[j]+2, titulos[j]);
 printf( "\n\n" );
 for ( i = 0; i < 2; i++ ) {
   for ( j = 0; j < 8; j++ ) {
   printf( "%-*s", ancho[j]+2,tabla[i][j] );
   }
   printf( "\n\n" );
 }
  return 0;
}


¡¡¡¡ Saluditos! ..... !!!!





Yoel Alejandro

#8
Ahora sí lo entiendo mucho más fácilmente  :), está más "despejadito". Mira, pero si acortas el código a fuerza de usar el operador ternario estás haciendo "trampa", jajaja. En esencia es el mismo if, pero escrito más brevemente  :rolleyes:

O sea, produce prácticamente el mismo ejecutable, sólo se reduce el fuente. Es lo mismo que yo cambiara

a = 1;
b = 2;
c = 3;

por

a = 1; b = 2; c = 3;

(jajaja)

Por otra parte lo de "%-*s" está genial.
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

leosansan

Cita de: yoel_alejandro en 26 Marzo 2014, 15:16 PM
Ahora sí lo entiendo mucho más fácilmente  :), está más "despejadito". Mira, pero si acortas el código a fuerza de usar el operador ternario estás haciendo "trampa", jajaja. En esencia es el mismo if, pero escrito más brevemente  :rolleyes:

O sea, produce prácticamente el mismo ejecutable, sólo se reduce el fuente. Es lo mismo que yo cambiara

a = 1;
b = 2;
c = 3;

por

a = 1; b = 2; c = 3;

(jajaja)

Por otra parte lo de "%-*s" está genial.

Yo habría hecho:


a = 1, b = 2, c = 3;


Y gracias por lo de genial, yo sólo lo calificaría de ingenioso y oportuno.

Un fuerte saludo.


¡¡¡¡ Saluditos! ..... !!!!