Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: nolasco281 en 24 Marzo 2014, 04:45 am



Título: Alinear texto (Solucionado)
Publicado por: nolasco281 en 24 Marzo 2014, 04:45 am
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.

(http://3.bp.blogspot.com/-Z5zYcLG4l0c/Uy-qNHbknHI/AAAAAAAAAkw/j9gciEUwAKE/s1600/ForoPregunta1.png)

como ven no se aliena el texto. : (


Título: Re: Alinear texto
Publicado por: eferion en 24 Marzo 2014, 14:58 pm
y el código que genera esta salida es...


Título: Re: Alinear texto
Publicado por: Yoel Alejandro en 24 Marzo 2014, 17:47 pm
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
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. /* Imprimir una tabla alineada en columnas, con justificación a la izquierda
  6.  * By Yoel, xD */
  7. int main() {
  8.  
  9.   int i, j;
  10.   int ColumnsWidth[4];
  11.   size_t width;
  12.  
  13.   /* Contenido de la tabla, pones luego el código que la genera */
  14.   char *tabla[2][4] = {{"Hacker", "Perro", "Labrador", "Macho"},
  15.      {"Fugi", "Camaleon", "Silvestre", "Hembra"}
  16.   };
  17.   char *titulos[4] = {"Nombre", "Animal", "Raza", "Sexo"};
  18.  
  19.   for ( j = 0; j < 4; j++ ) {
  20.      ColumnsWidth[j] = 0;
  21.      /* calcula el mayor ancho entre todos los campos de la columna j */
  22.      if ( ( width = strlen(titulos[j]) ) > ColumnsWidth[j] )
  23.         ColumnsWidth[j] = width;
  24.      for ( i = 0; i < 2; i++ )
  25.         if ( ( width = strlen(tabla[i][j]) ) > ColumnsWidth[j] )
  26.            ColumnsWidth[j] = width;
  27.      /* dos espacios adicionales */
  28.      ColumnsWidth[j] += 2;
  29.   }
  30.  
  31.   /* Ahora luego de imprimir cada palabra, colocas espacios en blanco hasta completar
  32.     * el ancho que debe tener la columna, más dos espacios adicionales */
  33.   for ( j = 0; j < 4; j++ ) {
  34.      width = strlen( titulos[j] );
  35.      printf( "%s", titulos[j] );
  36.      while ( width++ < ColumnsWidth[j] ) putchar(' ');
  37.   }
  38.   printf( "\n\n" );
  39.   for ( i = 0; i < 2; i++ ) {
  40.      for ( j = 0; j < 4; j++ ) {
  41.         width = strlen( tabla[i][j] );
  42.         printf( "%s", tabla[i][j] );
  43.         while ( width++ < ColumnsWidth[j] ) putchar(' ');
  44.      }
  45.      printf( "\n" );
  46.   }
  47.  
  48.   return 0;
  49. }

Salida:
Código:
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.


Título: Re: Alinear texto
Publicado por: eferion en 24 Marzo 2014, 20:52 pm
Presuponiendo que el ancho va a ser fijo es más sencillo usar printf

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. int main()
  6. {
  7. int i, j;
  8. int ColumnsWidth[4] = { 10, 10, 20, 10 };
  9.  
  10. /* Contenido de la tabla, pones luego el código que la genera */
  11. char *tabla[2][4] = { {"Hacker", "Perro", "Labrador", "Macho"},
  12.                       {"Fugi", "Camaleon", "Silvestre", "Hembra"} };
  13.  
  14. char *titulos[4] = {"Nombre", "Animal", "Raza", "Sexo"};
  15.  
  16. char config[8];
  17. int total = 0;
  18. for ( j = 0; j < 4; j++ )
  19. {
  20.   sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
  21.   printf( config, titulos[ j ] );
  22.   total += ColumnsWidth[ j ];
  23. }
  24.  
  25. putchar( '\n' );
  26.  
  27. while ( total )
  28. {
  29.   putchar( '-' );
  30.   total--;
  31. }
  32.  
  33. putchar( '\n' );
  34.  
  35. for ( i = 0; i < 2; i++ )
  36. {
  37.   for ( j = 0; j < 4; j++ )
  38.   {
  39.     sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
  40.     printf( config, tabla[ i ][ j ] );
  41.   }
  42.   printf( "\n" );
  43. }
  44.  
  45. return 0;
  46. }
  47.  

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

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. int main()
  6. {
  7. int i, j;
  8. int ColumnsWidth[4] = { 0 };
  9.  
  10. /* Contenido de la tabla, pones luego el código que la genera */
  11. char *tabla[2][4] = { { "Hacker", "Perro", "Labrador", "Macho" },
  12.                       { "Fugi", "Camaleon", "Silvestre", "Hembra" } };
  13.  
  14. char *titulos[4] = { "Nombre", "Animal", "Raza", "Sexo" };
  15.  
  16. for ( j = 0; j < 4; j++ )
  17. {
  18.   size_t width = strlen( titulos[ j ] );
  19.   if ( width > ColumnsWidth[ j ] )
  20.     ColumnsWidth[ j ] = width;
  21.  
  22.   for ( i = 0; i < 2; i++ )
  23.   {
  24.     width = strlen( tabla[ i ][ j ] );
  25.     if ( width > ColumnsWidth[ j ] )
  26.       ColumnsWidth[ j ] = width;
  27.   }
  28.  
  29.   ColumnsWidth[ j ] += 2;
  30. }
  31.  
  32. char config[8];
  33. int total = 0;
  34. for ( j = 0; j < 4; j++ )
  35. {
  36.   sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
  37.   printf( config, titulos[ j ] );
  38.   total += ColumnsWidth[ j ];
  39. }
  40.  
  41. putchar( '\n' );
  42.  
  43. while ( total )
  44. {
  45.   putchar( '-' );
  46.   total--;
  47. }
  48.  
  49. putchar( '\n' );
  50.  
  51. for ( i = 0; i < 2; i++ )
  52. {
  53.   for ( j = 0; j < 4; j++ )
  54.   {
  55.     sprintf( config, "%%-%ds", ColumnsWidth[ j ] );
  56.     printf( config, tabla[ i ][ j ] );
  57.   }
  58.   printf( "\n" );
  59. }
  60.  
  61. return 0;
  62. }
  63.  

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


Título: Re: Alinear texto
Publicado por: leosansan en 24 Marzo 2014, 21:36 pm

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

Código
  1. Nombre  Animal    Raza       Sexo    Color      Edad  Servicio          Costo
  2.  
  3. Hacker  Perro     Labrador   Macho   Cafe       3     Servicio Simple   600
  4.  
  5. Fugi    Camaleon  Silvestre  Hembra  Muticolor  8     Servicio Premium  1200
  6.  
  7.  
  8. Process returned 0 (0x0)   execution time :  0.023 s
  9. Press any key to continue.
  10.  

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. int main() {
  5. int i, j,mayor ,ancho[8]={0};
  6.  char *tabla[2][8] = {{"Hacker", "Perro", "Labrador", "Macho", "Cafe", "3", "Servicio Simple", "600"},
  7.      {"Fugi", "Camaleon", "Silvestre", "Hembra", "Muticolor", "8",  "Servicio Premium", "1200"}};
  8.  char *titulos[8] = {"Nombre", "Animal", "Raza", "Sexo", "Color", "Edad", "Servicio", "Costo"};
  9.  for ( i = 0; i < 1; i++ )
  10.    for ( j = 0; j < 8; j++ ){
  11.      if ((mayor= strlen(tabla[i][j])>strlen(tabla[i+1][j]) ? strlen(tabla[i][j]):strlen(tabla[i+1][j]))>(strlen(titulos[j])))
  12.        ancho[j]=mayor;
  13.      else
  14.        ancho[j]=strlen(titulos[j]);
  15.    }
  16.  for ( j = 0; j < 8; j++ )
  17.  printf( "%-*s", ancho[j]+2, titulos[j]);
  18.  printf( "\n\n" );
  19.  for ( i = 0; i < 2; i++ ) {
  20.    for ( j = 0; j < 8; j++ ) {
  21.    printf( "%-*s", ancho[j]+2,tabla[i][j] );
  22.    }
  23.    printf( "\n\n" );
  24.  }
  25.   return 0;
  26. }

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


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)


Título: Re: Alinear texto
Publicado por: nolasco281 en 24 Marzo 2014, 23:05 pm
Hola primero comentando a lo que indica eferion del codigo.

Código
  1. // Almacenar datos en archivo.
  2.         archivo << nombreAni << setw(15)
  3.                 << tipoAnimalAni << setw(15)
  4.                 << razaAni       << setw(15)
  5.                 << sexoAni       << setw(15)
  6.                 << colorAni      << setw(15)
  7.                 << 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
  1. archivo << setw(10) << "Nombre" << setw(15) << "Animal" << setw(15) << "Raza" << setw(15)
  2.            << "Sexo" << setw(15) << "Color" << setw(15) << "Edad" << setw(23)
  3.            << "Servicio" << setw(16) << "Costo" << endl << endl;

Código
  1. // Almacenar datos en archivo.
  2.         archivo << setw(10) << nombreAni << setw(15)
  3.                 << right << tipoAnimalAni << setw(15)
  4.                 << razaAni       << setw(15)
  5.                 << sexoAni       << setw(15)
  6.                 << colorAni      << setw(15)
  7.                 << edadAni;

(http://2.bp.blogspot.com/-PrkCvknJG14/UzDblf5O7HI/AAAAAAAAAl0/S2YnVjKrPyw/s1600/TEXTO.png)

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.


Título: Re: Alinear texto (Solucionado)
Publicado por: Yoel Alejandro en 25 Marzo 2014, 19:01 pm
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"?


Título: Re: Alinear texto (Solucionado)
Publicado por: leosansan en 25 Marzo 2014, 19:44 pm
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
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. int main() {
  5. int i, j,mayor=0 ,ancho[8]={0};
  6.  char *tabla[2][8] = {{"Hacker", "Perro", "Labrador", "Macho", "Cafe", "3", "Servicio Simple", "600"},
  7.      {"Fugi", "Camaleon", "Silvestre", "Hembra", "Muticolor", "8",  "Servicio Premium", "1200"}};
  8.  char *titulos[8] = {"Nombre", "Animal", "Raza", "Sexo", "Color", "Edad", "Servicio", "Costo"};
  9.  for ( i = 0; i < 1; i++ )
  10.    for ( j = 0; j < 8; j++ ){
  11.      if (strlen(tabla[i][j])>mayor)
  12.          mayor = strlen(tabla[i][j]);
  13.      if (strlen(tabla[i+1][j])>mayor)
  14.          mayor = strlen(tabla[i+1][j]);
  15.      if (strlen(titulos[j])>mayor)
  16.          mayor = strlen(titulos[j]);
  17.      ancho[j] = mayor;
  18.      mayor=0;
  19.    }
  20.  for ( j = 0; j < 8; j++ )
  21.    printf( "%-*s", ancho[j]+2, titulos[j]);
  22.  printf( "\n\n" );
  23.  for ( i = 0; i < 2; i++ ) {
  24.    for ( j = 0; j < 8; j++ ) {
  25.    printf( "%-*s", ancho[j]+2,tabla[i][j] );
  26.    }
  27.    printf( "\n\n" );
  28.  }
  29.   return 0;
  30. }

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


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)




Título: Re: Alinear texto (Solucionado)
Publicado por: 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.


Título: Re: Alinear texto (Solucionado)
Publicado por: leosansan en 26 Marzo 2014, 17:18 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! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)



Título: Re: Alinear texto (Solucionado)
Publicado por: eferion en 26 Marzo 2014, 17:28 pm
yo de hecho no me había topado nunca con esa sintaxis. si cuando digo que programar es un arte en el que no se deja de aprender...


Título: Re: Alinear texto (Solucionado)
Publicado por: leosansan en 26 Marzo 2014, 17:46 pm
yo de hecho no me había topado nunca con esa sintaxis. si cuando digo que programar es un arte en el que no se deja de aprender...

Tengo la suerte de seguir minuciosamente los códigos que cuelga rir3760 desde hace más de un año hasta el punto de tener una carpeta exclusiva para sus códigos. No paro de aprender y cuanto más los releo más aprendo y más amplio mi campo de programación.

Es una pena que el moderador decidiera dar carpetazo al tema de los rombos con asteriscos. Para los que somos curiosos y nos gusta aprender de los demás ha sido una pena. Precisamente ahí colgó un código el amigo rir que aún me tiene anonadado. Usa lo que yo he usado del printf pero con un arte que  no veas.

Sólo me pica una curiosidad y es el 3760. Podría ser la fecha de su nacimiento pero me da que oculta otra cosa. ;)


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


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)