[C] Rombo con asteriscos

Iniciado por dmacias, 1 Marzo 2014, 20:14 PM

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

dmacias

Buenas de nuevo, aqui os vengo otra vez con una duda, Esta vez he solucionado el problema que tengo pero de una manera poco ortodoxa ya que la segunda parte del problema la he ido rellenando por prueba y error.

Asi que no me quedo conforme con ello y os pido ayuda haber que es lo que se me escapa.

El problema es facil, imprimir un rombo tal como este


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


Aqui sale torcido, pero ya os haceis una idea xD.

Aqui el codigo que tengo, que funcionar funciona


#include <stdio.h>

int main()
{
int a, n, n1;
int contador = 1;

for (a = 5; a >= 1; a--){
for (n = 0; n <= a; n++){
printf(" ");
}
for (n1 = 1; n1 <= contador; n1++){
printf("*");
}
printf("\n");                          /*Triangulo superior*/
contador += 2;           /*Asta aqui dominado mas o menos :) */
}
for (a = 4; a >= 1; a--){      /*De aqui en adelante a sido una loteria :( */
for (n = 6; n >= a; n--){        /*Triangulo inferior*/
printf(" ");
}
for (n1 = 2; n1 <= contador-3; n1 ++){
printf("*");
}
printf("\n");
contador -= 2;
}
return 0;

}



Pero como os digo he tenido que ir rellenando esta linea
for (n1 = 2; n1 <= contador-3; n1 ++){

y esta otra

contador -= 2;

haciendo prueba y error asta ajustarlo, un metodo un poco guarro creo, ya que realmente no lo he dominado.

Bueno, pues eso, si alguien me orienta en donde pierdo el control, se lo agradeceria.

Un saludo

leosansan



Sin más comentarios que los que te pongo en el código:

Código (cpp) [Seleccionar]

#include<stdio.h>
int main()
{
  int n,i,j;
  printf("\nTama\xA4o de la mitad superior: \n");
  scanf ("%d",&n);
  printf("\n\n");
  for(i=1;i<=n;i++){  /** fijate que aqui i aumenta **/
    printf("\t\t");
    for(j=1;j<=n-i;j++)/** cada vez un espacio menos **/
        printf(" ");
    for(j=1;j<=2*i-1;j++)/** cada vez dos "*" mas **/
      printf("*");     /** despues de los espacios **/
  printf("\n");
  }

  for(i=n-1;i>=1;i--){  /** fijate que aqui i disminuye **/
    printf("\t\t");
    for(j=1;j<=n-i;j++)/** cada vez un espacio mas **/
      printf(" ");
    for(j=1;j<=2*i-1;j++)/** cada vez dos "*" menos **/
      printf("*");     /** despues de los espacios **/
  printf("\n");
  }
  return 0;
}


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





rir3760

#2
Para imprimir las secuencias de espacios y asteriscos se puede desarrollar una función, por ejemplo:
#include <stdio.h>
#include <stdlib.h>

#define LADO  5

void repetir(int reps, char ch);

int main(void)
{
  int i;
 
  for (i = 1; i < LADO * 2; i += 2){ /* 1, 3, 5, 7, 9 */
     repetir((LADO - 1) - i/2, ' ');
     repetir(i, '*');
     putchar('\n');
  }
 
  for (i -= 4; i > 0; i -= 2){ /* 7, 5, 3, 1 */
     repetir((LADO - 1) - i/2, ' ');
     repetir(i, '*');
     putchar('\n');
  }
 
  return EXIT_SUCCESS;
}

void repetir(int reps, char ch)
{
  int i;
 
  for (i = 0; i < reps; i++)
     putchar(ch);
}


Otra forma de imprimir ese rombo en particular es:

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

int main(void)
{
  char ch[] = "*********";
  int i;
 
  for (i = -4; i < 5; i++)
     printf("%*c%.*s\n", 1 + abs(i), ' ', 1 + (4 - abs(i)) * 2, ch);
 
  return EXIT_SUCCESS;
}


La primera es clara y flexible, la segunda es breve y esta bien para practicar con la biblioteca estándar de C pero es muy limitada (eso es evidente si se trata de modificar para el manejo de casos generales).

----

Editado: una forma ligeramente mas corta donde se evita imprimir si o si un espacio:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   char ch[] = "*********";
   int i;
   
   for (i = -4; i < 5; i++)
      printf("%*.*s\n", 9 - abs(i), 1 + (4 - abs(i)) * 2, ch);
   
   return EXIT_SUCCESS;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

leosansan

#3
Siguiendo los pasos del "maestro==rir3760" por usar funciones que no quede:

Código (cpp) [Seleccionar]

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

int main()
{
 int i,n;
 printf("\n\n");
 printf("\nTama\xA4o de la mitad superior: \n");
 scanf ("%d",&n);

 for(i=1;i<=n;i++)
   repetir (n-i,' ',2*i-1,'*');
 for(i=n-1;i>=1;i--)
   repetir (n-i,' ',2*i-1,'*');
 return EXIT_SUCCESS;
}

void repetir(int reps, char ch,int reps1, char ch1)
{
 int j,k;
 printf("\t\t");
 for (j = 1; j <=reps; j++)
   putchar(ch);
 for (k = 1; k <=reps1; k++)
   putchar(ch1);
 putchar('\n');
}


Ante el "otro" código, el del printf, tan solo mirar boquiabierto y, como siempre, aprender de sus aportaciones, todo un lujo para el foro.

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




MeCraniDOS

Cita de: rir3760 en  2 Marzo 2014, 18:59 PM
la segunda es breve y esta bien para practicar con la biblioteca estándar de C pero es muy limitada (eso es evidente si se trata de modificar para el manejo de casos generales).

Solo breve?  :o  :rolleyes:
"La física es el sistema operativo del Universo"
     -- Steven R Garman

dmacias

Gracias a todos por responder, aun no llegue al tema de las funciones, pero en un par de dias llego.

Veo que me hago aún un lio con estas cosas, espero que con la practica vaya mejorando.

Con lo que me habeis puesto ya tengo trabajo donde comparar y aprender.

rir3760 si  que lo hicistes escueto, casi fugaz diria yo xD


Un saludo

Yoel Alejandro

Buenos días, lamento llegar un poco tarde, tampoco ser entrometido (como me acusaron en otro post  >:()

Inspirándome un poco en el enfoque de rir7360 que "centró" el rombo, es decir tomó los índices de -N a N, en lugar de 0 a 2*N, quiero aportar una función que dibuja un rombo general con cualquier número de líneas (impar positivo) dado.

El main() pide al usuario la cantidad de líneas del rombo, pero esto esta interfaz se puede modificar. Lo importante es el código de la función rombo() que gracias al enfoque de "centrar" los valores no requiere dividir entre la parte de arriba y la parte de abajo, ni entre derecha e izquierda, jeje.

Resultado, con 9 líneas:

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


Básicamente lo que hacemos es calcular el "punto medio" p de N (redondeo por exceso de N/2), para el caso N=9 sería p=5. Luego recorremos tanto i como j desde -p+1 hasta p-1, o sea, desde -4 hasta 4. El asterisco se imprime si abs(j) < p - abs(i), y esto dibuja el rombo de manera correcta, tanto en su parte superior como la inferior. El código:

Código (cpp) [Seleccionar]

#include <stdio.h>
#include <stdlib.h>
 
void rombo (int N);
 
int main(void) {

int N;

printf("Ancho del rombo: ");
scanf("%d", &N);

/* limpia la entrada estandar por caracteres no leidos */
while ( getchar() != '\n' )
;

/* comprueba N impar y positivo */
if ( N > 0 && (N % 2) == 1)
rombo( N );
else
printf("N debe ser impar positivo\n");

return 0;
}

/* Imprime un rombo de N lineas */
void rombo (int N) {

int i, j, p;

p = (int) N / 2 + 1; /* punto medio ente 1 y N */
for (i = -p + 1; i <= p - 1; i++) {
for (j = -p + 1; j <= p - 1; j++)
if ( abs(j) < p - abs(i) )
putchar('*');
else
putchar(' ');
putchar('\n');
}
}
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

leosansan

#7
¡¡¡El mío es más grande!!!


Es de cachondeo.

Pero el uso de una cadena por parte de rir3760 me ha hecho pensar una forma alternativa:parto de una cadena con un solo  asterisco en medio y a medida que bajo añado dos asteriscos por escalón, mientras en la parte inferior los voy quitando. Curioso, ¿verdad?:


Código (cpp) [Seleccionar]

#include <stdio.h>
int main(void){
 int i,n,p;
 do{
   printf("\nBase del rombo(numero impar positivo): \n");
   scanf("%d", &n);
 }while ( n <=0 || (n % 2) == 0);
 char asteriscos[n];
 for (i=0;i<n;i++)
   asteriscos[i]=' ';
 asteriscos[i]='\0';
 p=n/2;
 asteriscos[p]='*';
 for (i=1;i<p+1;i++){
   printf ("\t\t%s\n",asteriscos);
   asteriscos[p-i]=asteriscos[p+i]='*';
 }
 printf ("\t\t%s\n",asteriscos);
 for (i=0;i<=p;i++){
   asteriscos[i]=asteriscos[n-1-i]=' ';
   printf ("\t\t%s\n",asteriscos);
 }
 return 0;
}


O con un solo for:

Código (cpp) [Seleccionar]

#include <stdio.h>
int main(void){
 int i,j,n,p;
 do{
   printf("\nBase del rombo(numero impar): \n");
   scanf("%d", &n);
 }while ( n <=0 || (n % 2) == 0);
 char asteriscos[n];
 for (i=0;i<n;i++)
   asteriscos[i]=' ';
 asteriscos[i]='\0';
 p=n/2;
 asteriscos[p]='*';
 for (i=-p;i<=p;i++){
   if (i<=0){
     printf ("\t\t%s\n",asteriscos);
     if (i<0)
     asteriscos[-i-1]=asteriscos[n+i]='*';
   }
   else{
     j=-i;
     asteriscos[-j-1]=asteriscos[n+j]=' ';
     printf ("\t\t%s\n",asteriscos);
   }
 }
 return 0;
}


Aunque nada supera al printf de rir3760.

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







rir3760

Cita de: yoel_alejandro en  5 Marzo 2014, 21:23 PMBásicamente lo que hacemos es calcular el "punto medio" p de N (redondeo por exceso de N/2), para el caso N=9 sería p=5. Luego recorremos tanto i como j desde -p+1 hasta p-1, o sea, desde -4 hasta 4. El asterisco se imprime si abs(j) < p - abs(i), y esto dibuja el rombo de manera correcta, tanto en su parte superior como la inferior.
Solo un comentario: no es necesario imprimir los espacios al final de cada linea, por cada una basta con los primeros "N - abs(i)" caracteres.

La función con esa y otras modificaciones (todas ellas menores):
void rombo(int N)
{
   int i;
   int j;
   
   for (i = -N/2; i <= N/2; i++){
      for (j = 0; j < N - abs(i); j++)
         putchar(j < abs(i) ? ' ' : '*');
     
      putchar('\n');
   }
}


----

Ya por ultimo la biblioteca estándar de C no incluye una función que permita imprimir N veces un determinado carácter. Las únicas dos excepciones (forzadas, por supuesto) son el espacio y el cero. Un ejemplo de ello es otra versión (mas) del bendito rombo:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   int i;
   
   for (i = -4; i < 5; i++)
      printf("%*c%0*d\n", 1 + abs(i), ' ', 1 + (4 - abs(i)) * 2, 0);
   
   return EXIT_SUCCESS;
}


Produciendo la salida:
     0
    000
   00000
  0000000
000000000
  0000000
   00000
    000
     0


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Yoel Alejandro

Bueno ..... creo que ya hemos dado una tremenda cantidad de opciones al autor del post sobre cómo resolver su problema.

Lástima que él no haya seguido escribiendo, y al final terminamos agarrándonos el tema para nosotros, jeje  :laugh:

Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)