Ayuda con cadenas de caracteres.

Iniciado por GilbertoBrewer, 25 Noviembre 2014, 04:24 AM

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

GilbertoBrewer

Buenas noches.

En mi clase de programación estructurada me encargaron que hiciera un programa que me generara 10 nombres con apellidos y, una vez generada la lista con los 10 nombres y apellidos al azar, se organicen alfabéticamente.

El problema es que por alguna razón que desconozco completamente, no me muestra las cadenas como debería al intentar ordenarlas. Cuando me las genera al azar me las muestra correctamente, pero al seleccionar la opción de que me ordene la misma lista alfabéticamente me escribe cadenas muy largas repitiendo los nombres o me deja algunas vacías. Ya llevo varios días tratando de ver dónde podría estar mal, pero no logro dar con lo que debo cambiar.

El programa lo hice así:
Código (cpp) [Seleccionar]

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

main ()
{
   char nombre[15][10]={"Pedro","Paco","Perla","Paola","Jorge","Jesus","Maria","Jose","Elisa","Angel"};
   char apellido[15][10]={"Perez","Lopez","Barba","Cruz","Robles","Gomez","Gaytan","Duval","Derbez","Padilla"};
   char nom[30][10];
   char nomord[30][10];
   char opcion;
   int a,b,i,j,lugar,comparar,largo[10];
   srand (time (NULL));

   printf ("Escoge una opcion:\n");
       printf ("a-Generar 10 nombres\n");
       printf ("b-Ordenarlos alfabeticamente\n");
       printf ("s-Salir\n");
       scanf("%s",&opcion);

   while (opcion!='s')
   {
       switch (opcion)
       {
       case 'a':
           printf ("\nNombres:\n");
           for (i=0; i<10; i++)
           {
               a=rand()%10;
               b=rand()%10;
               sprintf (nom[i],"%s %s%s",nombre[a],apellido[b],"\0");
               largo[i]=strlen(nom[i]);
               printf ("%d- %s - %d\n",i+1,nom[i],largo[i]);
           }
           printf ("\n");

           break;

       case 'b':
           for (i=0; i<10; i++)
           {
               lugar=0;
               for (j=0; j<10; j++)
               {
                   comparar=strcmp(nom[i],nom[j]);
                   if (comparar>0)
                   {
                       lugar++;
                   }
               }
               while (strcmp(nom[i],nomord[lugar])==0)
               {
                   lugar++;
               }
               sprintf (nomord[lugar],"%s%s",nom[i],"\0");
           }

           for (i=0; i<10; i++)
           {
               printf ("%d - %s\n",i+1,nomord[i]);
           }
           break;
       }

       printf ("Elige una opcion: ");
       scanf ("%s",&opcion); //Lee una opcion; si se elige la "s" se sale del programa
   }

   return 0;
}



Al compilarlo y ejecutarlo, en pantalla siempre me muestra bien los 10 nombres, pero al elegir después la opción de ordenarlos me empalma los nombres y me muestra cadenas de hasta más de 50 caracteres, con varios nombres pegados uno tras otro.
¿Alguna ayuda al respecto? ¿A qué podría deberse eso y cómo lo corrijo?

tremolero

#1
Hola, a ver te digo, asi en una mirada rapida, declaras la variable nomord que deduzco que es donde al final tienes todo ordenado con un tamaño de 10 cuando al sumar el nombre mas largo y el apellido mas largo (5+7=12) mas espacio serian unos 13, ademas veo que creas 15 espacios cuando solo son 10 los que vas a ordenar, asi que diria que te has confundido al declarar las variables, has puesto nomord[30][10] cuando deberias poner nomord[10][30].

Al igual que en nombre y apellido, imagino que es un ejercicio cerrado, asi que no entiendo crear 15, cuando directamente ya has llenado 10, pero nose si el ejercicios mas a ampliarlo y por eso has añadido esos 5 de mas.

Luego se me ocurren varias cosas (aviso que no estoy nada fino y tal vez meta la pata), en mi caso por ahorrar variables, hubiese ordenado la misma variable en vez de crear dos.
Al igual que las variables a,b y comparar, probablemente no las hubiera creado tampoco, ya que las usas para almacenar un dato el cual directamente lo usas una unica vez, es decir:

tu haces:

a=rand()%10;
b=rand()%10;
sprintf (nom[i],"%s %s%s",nombre[a],apellido[b],"\0");



Yo hubiese hecho:

sprintf (nom[i],"%s %s%s",nombre[rand()%10],apellido[rand()%10],"\0");


Bueno en fin se me ocurren mas cosas, si las quieres saber, en mi opinion es como mejorar el codigo, dimelo y encantado te lo dire.

Mi consejo principal es que aprendas a usar el debug, ya que con el, te habrias dado cuenta enseguida, que el nombre que almacena no lo almacena entero y de ahi lo habrias solucionado, lo que no entiendo muy bien es porque teniendo un tamaño de 10 da un error de cadenas muy largas, pero cambiando lo primero de las variables lo solucionas.

La verdad no se como funciona el sprintf, pero creo que el es el culpable de las variables largas, a ver si algun experto puede explicar el funcionamiento y/o porque hace este error.

Un saludo.

Pd: el sistema de ordenacion creo que es erroneo, dale a ordenar dos veces lo mismo y veras.

GilbertoBrewer

#2
Muchas gracias, tremolero.

Ya corregí lo de la declaración de variables y ya funcionó. Por alguna razón estaba convencido de que, al declarar la variable, el primer número representaba el tamaño de cada cadena y el segundo número la cantidad de cadenas. Gracias por hacerme ver ese error.

Respecto al sistema de ordenarlos, ya vi cuál era el problema. Voy a tratar de solucionar eso para cuando se intenta ordenar dos veces seguidas.

Igualmente, gracias por el consejo de las variables a y b. Si tienes algún otro consejo con respecto al código, estoy abierto a escucharlas.

Por cierto, cuando escribas algún código (o parte de uno) en un mensaje, selecciona el botón de código (el que tiene un "gato", #), para que no ocurra lo que pasó con tu mensaje (al poner "i" entre corchetes se puso en itálica el resto del mensaje, y al poner "b" entre corchetes se puso en negrita el resto del mensaje). Lo mismo me pasó en mi pregunta anterior.

Saludos.

tremolero

Bufff la falta de sueño es muy fala xD, no sabia ni lo que escribia, asi que imaginate como para acordarme de poner el code #, por cierto a esto (#) < le llamas "gato"? la primera vez que lo oigo.

A ver que recuerdo:

1.- Al igual que haria con las variables a y b, habria hecho lo mismo con la de comparar.
A lo mejor alguien con mas experiencia, puede aclarar si es buena idea o no, ahorrar en variables, he de decir, que lo mejor es declararlas  por si el proyecto se hace grande y demas, pero de duzco que esto es un ejercicio cerrado, en cuyo caso, esas variables le das un unico uso.

2.- Esto no estoy seguro, pero en el sprintf añades un "\0" y creo que no es necesario. pero no me hagas mucho caso.

3.- luego en el doble bucle for, la variable j la habria iniciado desde i, es decir j=i, de esta manera evitas que recorra lo anterior, supuestamente estas comparando todo con todo, pero todo lo que i ya ha pasado no es necesario que j vuelva a comprobarlo. esta claro que error no te va a dar, porque en tu comparacion no entra ya que lo que hay detras ya esta ordenado y es inferior. pero haces que sea mas rapido, aunque en este caso no lo llegues a apreciar.

4.- y por ultimo, yo seguramente hubiese usado la mismas variable para guardar todo ordenado, es decir, no habria usado dos variables, el metodo de ordenacion que habria usado seguramente habria sido con una variable auxiliar, en la cual almacenas el dato momentaneo mientras pasas un valor de una posicion a otra.
En mi caso me habria ahorrado la variable nomord y el while despues del segundo for, ya que en mi caso, voy almacenando el menor en la variable auxiliar y una vez llegado al final lo coloco en su posicion.

Un saludo.

GilbertoBrewer

No sé de dónde seas; acá en México (o por lo menos en mi ciudad y áreas circunvecinas) al símbolo "#" le decimos "gato" porque en el juego de gato se usa un símbolo similar (el juego llamado Tik-tak-toe en inglés).

Lo del punto 2 sí sabía que no era necesario, pero es una de las tantas cosas que le estuve agregando al código tratando de evitar que me arrojara los errores que me estaba haciendo el programa.

Sobre el punto 3 y 4, voy a analizarlos bien, pero creo que ya sé a qué te refieres. Lo voy a revisar, y en cualquier caso, gracias por las recomendaciones.

Saludos.

tremolero

Soy de españa y aqui se le llama "almohadilla" pero bueno algo mas que sé :P y respecto al tik-tak-toe yo siempre he pensado que eran X(equis) y O :P

De nada y ya sabes, cualquier duda adelante.

Un saludo.

GilbertoBrewer

Sólo una cosa más: ¿a qué te refieres con "usar el debug"? Realmente no estoy familiarizado con el término.

tremolero

Bueno, es una de las partes mas importantes en la programacion, ya que el debug o depuracion, es lo que se utiliza para buscar los errores y solucionarlos.

No se que IDE utilizas, yo ahora mismo tengo aqui el codeblocks, al lado de cada linea puedes añadir un breakpoint pulsado con el raton o haciendo click derecho te salen varias opciones.

Y luego tienes varios botones, para el debug, si quieres que vaya desde el principio o que inicie normal hasta donde le has indicado, etc...

Ademas tienes varais ventanas que te muestran los valores de las variables y todo o eso creo en principio, la verdad es que ando un poco perdido, llevaba un tiempo sin tocar C++

Pero bueno si tienes codeblocks arriba en las pestañas veras que hay una que pone debug, y si buscas un poco de informacion te lo explicaran todo, cualquier duda pregunta.

Un saludo.

GilbertoBrewer

Ah, ok, ok. Sí, yo también uso Code::Blocks, lo voy a revisar.
Y bueno, creo que eso es todo. Muchas gracias.
Por cierto, no sé cómo cerrar el tema.