Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Error 404: en 27 Junio 2014, 12:33 pm



Título: Programa para distinguir palindromos:
Publicado por: Error 404: en 27 Junio 2014, 12:33 pm
Hola a todos
Os cuento, hoy me he puesto a hacer un programa bastante básico, que consiste en introducir una palabra o una frase y te devuelve si es un palíndromo o no.
Puesto que aún tengo un nivel muy muy básico (por no decir malo) al principio he aclarado que nunca se utilicen espacios, ni mayúsculas, ni acentos, y en fin, cualquier cosa que dificulte mucho más la programación.
Bueno os dejo el programa y la localización y el fallo que me pone, supongo que es importante decir que utilizo DEV-C++.
Espero que me d¡gáis una pista o algo de como solucionarlo, gracias.
Código:
#include <iostream>
#include <cstring>
using namespace std;
int n;
bool palindromo;
int j;
int main(){
    int i;
    char cadena;
   
    cout << "Introduzca una palabra o cadena de ellas sin utilizar espacios y/o" << endl;
    cout << " mayusculas, minusculas, acentos, etc. El programa le dira si la" << endl;
    cout << " cadena introducida es un palindromo."<< endl;
   
    cin >> cadena;
    cin.get();
    if (palindromo) cout<< "Es un palindromo.";
    else cout<< " No es un palindromo.";

cin.get();
return 0;
}

bool palindromo
{        //AQUI MARCA EL FALLO Y PONE: INVALID FUNCTION DECLARATION
     int j = sizeof(cadena)/sizeof(cadena[1]);
     int k = 1;
     do{
         if(strcmp(cadena[k],cadena[j])==0) k++ j-- n=1;
         else n=0;
         } while( k != j+1 && n!=0);
         if (n==1) return true; else return false;
}

Gracias por adelantado.


Título: Re: Programa para distinguir palindromos:
Publicado por: eferion en 27 Junio 2014, 12:55 pm
Respeta la nomenclatura de las funciones

Todas las funciones en C y C++ tienen la siguiente forma:

Código:
TIPO_RETORNO nombreFuncion( [ARGUMENTOS] ){ }

En tu caso, palindromo no respeta esta nomenclatura ya que, por ejemplo, no tiene los paréntesis (nota que "argumentos" está entre corchetes... esto es porque son opcionales... sin embargo el resto es obligatorio).

No uses variables globales

Es muy cómodo declarar una variable global al inicio del programa y después olvidarse de pasar argumentos a las funciones. El pero es que esta forma de trabajar provoca más problemas que beneficios.

Declarar una variable dentro de una función es prácticamente gratis y usar los argumentos te permite aislar el código de forma más eficaz. Además el código queda mucho más legible.

Para gestionar cadenas, usa char* o, mejor aún, la clase string

char únicamente permite almacenar un carácter. Es decir, para leer una cadena necesitas un array de caracteres. Los arrays de caracteres se declaran tal que "char* cadena". Eso sí has de tener en cuenta que ahora cadena es un puntero y hay que tener cuidado a la hora de utilizar punteros.

Por ejemplo, para copiar una cadena de caracteres en otra no puedes hacer "cadena1 = cadena2" como queda claro con el siguiente ejemplo:

Código
  1. char cadena1[10] = "Hola";
  2. char *cadena2;
  3.  
  4. cadena2 = cadena1;
  5.  
  6. cadena2[ 0 ] = 'S';
  7.  
  8. // Imprime por pantalla: Sola
  9. std::cout << cadena1 << std::endl;

Lo que hace la asignación es que el puntero "cadena2" apunta al mismo sitio que "cadena1", por lo que cualquier cambio que se haga en una de las variables afecta directamente a la otra. La forma correcta de copiar cadenas de caracteres es (una de ellas):

Código
  1. char cadena1[10] = "Hola";
  2. char cadena2[10];
  3.  
  4. strcpy( cadena2, cadena1 );
  5.  
  6. cadena2[ 0 ] = 'S';
  7.  
  8. // Imprime por pantalla: Hola
  9. std::cout << cadena1 << std::endl;

Nota para los del foro: Se que hay formas más seguras de copiar las cadenas de caracteres... esto es un ejemplo ;)

La opción b es hacer uso de una clase diseñada específicamente para gestionar cadenas de caracteres. Hablo de la clase string. string se encarga de hacer todas las operaciones engorrosas de los arrays de caracteres de forma transparente para el programador:

Código
  1. std::string cadena1 = "Hola";
  2. std::string cadena2;
  3.  
  4. cadena2 = cadena1;
  5.  
  6. cadena2[ 0 ] = 'S';
  7.  
  8. // Imprime por pantalla: Hola
  9. std::cout << cadena1 << std::endl;

Además, string dispone de otras tantas "cosas buenas":

Código
  1. std::string cadena = "ABCDEF";
  2. std::string cadena2 = cadena + "GHI";
  3.  
  4. std::cout << "Contenido:" << cadena << std::endl;
  5. std::cout << "Longitud: " << cadena.size( ) << std::endl;
  6. std::cout << "Probando la concatenacion: " << cadena2 << std::endl;
  7. // ...

Aprende a leer los mensajes de error de compilación

Al principio te costará, pero es un paso necesario con el que tienes que pegarte. El compilador te va a dar mucha información, pero has de saber interpretarla correctamente. No tengas miedo a pegarte con ello.

Aprende a usar los depuradores de código

Después de entender los mensajes de compilación, el siguiente paso es meterse de lleno en la depuración de código. Mano de santo para corregir errores a la hora de diseñar la algoritmia de la aplicación.


Título: Re: Programa para distinguir palindromos:
Publicado por: leosansan en 27 Junio 2014, 14:30 pm
Además de lo ya mencionado por eferion:

* Si declaras n y j como variables globales no tiene sentido que las vuellvas a declarar en la función bool. Mejor no las declaras como globales y sí en bool ya que sólo las usas en ésta.

* La función strcmp"" está pensada para comparar cadenas. En el caso de caracteres se pueden comparar directamente:

Código
  1. if( cadena[k] != cadena[j-1] )

* Tienes un error lógico. Si el último caracter de la cadena coincide con el primero n=1 y devuelve true, cuando a lo mejor en otros no son iguales.

* En realidad basta recorrer la mitad del array o cadena para saber si es o no palindromo.

* Los índices de los arrays empiezan en cero y tú los empiezas desde 1 (k=1), con lo que se quedara sin comparar el primer caracter.

Con las observaciones de eferion y las que te expongo, una posible solución sería:

Código
  1. #include <iostream>
  2. #include <cstring>
  3.  
  4. using namespace std;
  5.  
  6. bool palindromo ( char cadena[100] );
  7.  
  8. int main(){
  9.  char cadena[100];
  10.  cout << "Introduzca una palabra o cadena de ellas sin utilizar espacios y/o" << endl;
  11.  cout << " mayusculas, minusculas, acentos, etc. El programa le dira si la" << endl;
  12.  cout << " cadena introducida es un palindromo."<< endl;
  13.  cin >> cadena;
  14.  cin.get();
  15.  if ( palindromo ( cadena ) )
  16.    cout<< "Es un palindromo.";
  17.  else
  18.    cout<< " No es un palindromo.";
  19.  cin.get();
  20.  return 0;
  21. }
  22.  
  23. bool palindromo ( char cadena[100] ){
  24.  int k = 0, j = tam;
  25.  for ( k = 0; k < tam/2; k++, j-- )
  26.    if( cadena[k] != cadena[j-1] )
  27.      return false;
  28.  return true;
  29. }

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


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


Título: Re: Programa para distinguir palindromos:
Publicado por: Error 404: en 27 Junio 2014, 17:07 pm
Antes de todo muchas gracias por la ayuda tan rápida y buena. He realizado algunos cambios pero sigue habiendo algún problema. Aquí va el código:

Código
  1. #include <iostream>
  2.  
  3. #include <cstring>
  4.  
  5. using namespace std;
  6.  
  7. bool palindromo();
  8.  
  9. char *cadena;
  10.  
  11.  
  12.  
  13.  
  14. int main(){
  15.  
  16.  
  17.    cout << "Introduzca una palabra o cadena de ellas sin utilizar espacios y/o" << endl;
  18.  
  19.    cout << " mayusculas, minusculas, acentos, etc. El programa le dira si la" << endl;
  20.  
  21.    cout << " cadena introducida es un palindromo."<< endl;
  22.  
  23.  
  24.  
  25.    cin >> cadena;
  26.  
  27.    cin.get();
  28.  
  29.    if (palindromo()) cout<< "Es un palindromo.";
  30.  
  31.    else cout<< " No es un palindromo.";
  32.  
  33.  
  34.  
  35.  
  36. cin.get();
  37.  
  38. return 0;
  39.  
  40. }
  41.  
  42. bool palindromo(int n)
  43.  
  44. {
  45.  
  46.     int j = sizeof(cadena)/sizeof(cadena[1]);
  47.  
  48.     int k = 0;
  49.  
  50.     do{
  51.  
  52.         if (&cadena[k]!=&cadena[j])( n=0); //AQUI NO ESTOY SEGURO DE QUE
  53.                                       // TENGA QUE USAR LA DIRECCION
  54.         else{        
  55.                     k++;
  56.                     j--;
  57.                     n=1;
  58.                }
  59.  
  60.  
  61.         } while(k != j-1 || n!=0);
  62.  
  63.         if (n==1) return false; else return true;
  64.  
  65. }

El fallo que me pone es: [LINKER ERROR] UNDEFINIED REFERENCE TO ' palíndromo()'
ID RETURNED 1 EXIT STATUS


Título: Re: Programa para distinguir palindromos:
Publicado por: Eternal Idol en 27 Junio 2014, 17:31 pm
Obviando el resto del codigo, ese es un error en el momento de enlazar, la funcion palindromo en su prototipo no recibe parametros y cuando la llamas no le pasas ningun parametro, despues implementas otra que si recibe un parametro de tipo int, en definitiva no hay codigo para la primera y no usas la segunda, arregla el prototipo para que coincida con la implementacion y llama a la funcion con sus parametros correspondientes.


Título: Re: Programa para distinguir palindromos:
Publicado por: Error 404: en 27 Junio 2014, 17:36 pm
Entonces donde he puesto :
Código
  1. if (palíndromo())cout<<"es un palíndromo"
  2.  

Debería poner esto otro:  :huh:

Código
  1. if (palíndromo(int n))cout<<"es un palíndromo"
  2.  
Es que si hago ese cambio me sale el error : EXPECTED PRIMARY EXPRESSION BEFORE "int"


Título: Re: Programa para distinguir palindromos:
Publicado por: Eternal Idol en 27 Junio 2014, 17:42 pm
No ... como vas a poner eso ... no se puede programar haciendo copy/paste.

Conseguite un buen libro o al menos un tutorial para empezar desde el princpio.


Título: Re: Programa para distinguir palindromos:
Publicado por: Error 404: en 27 Junio 2014, 17:46 pm
Estoy con el manual de conclase, ese es un ejercicio que manda  :-\
Si me pudieras explicar lo que me has dicho con un ejemplo te lo agradecería mucho  :-(


Título: Re: Programa para distinguir palindromos:
Publicado por: Eternal Idol en 27 Junio 2014, 17:58 pm
No lo conozco ... por lo menos aca muestra como llamar a una funcion (me resulta increible que en el capitulo 3 no muestren como hacerlo):
http://c.conclase.net/curso/?cap=015#inicio

¿Por donde vas?


Título: Re: Programa para distinguir palindromos:
Publicado por: Error 404: en 27 Junio 2014, 18:02 pm
Vale, he conseguido que me compile, pero cuando lo uso me sale que tiene problemas, el típico cuadro de enviar o no informe de errores. Así lo deje:
Código
  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. bool palindromo();
  5. char *cadena;
  6. int main(){
  7.  
  8. // Voy a obviar la introduccion
  9.    cin >> cadena;
  10.    cin.get();
  11.    if (palindromo(cadena)) cout<< "Es un palindromo.";
  12.    else cout<< " No es un palindromo.";
  13. cin.get();
  14. return 0;
  15. }
  16. bool palindromo(char *cadena)
  17. {
  18.          int n;    
  19.          int j = sizeof(cadena)/sizeof(cadena[1]);
  20.          int k = 0;
  21.          do{
  22.               if (&cadena[k]!=&cadena[j])( n=0);                                      
  23.               else{        
  24.                      k++;
  25.                      j--;
  26.                      n=1;
  27.                     }
  28.         } while(k != j-1 || n!=0);
  29.         if (n==1) return true; else return false;
  30.  
  31.  
  32.  


Título: Re: Programa para distinguir palindromos:
Publicado por: Eternal Idol en 27 Junio 2014, 18:05 pm
¿Y que valor tiene la variable global cadena? Copiar y pegar codigo sin sentido no es programar.


Título: Re: Programa para distinguir palindromos:
Publicado por: Error 404: en 27 Junio 2014, 18:13 pm
No copio y pego, simplemente he empezado hace poco y aún no se hacerlo muy bien, nadie empieza sabiendo... Si copiara y pegara simplemente habría cogido el código que me ha dejado de ayuda leosansan.

Cuando le doy a depurar me sale que hay una violación de acceso a memoria (fallo de segmentación), ¿alguien me puede explicar lo que significa?


Título: Re: Programa para distinguir palindromos:
Publicado por: Eternal Idol en 27 Junio 2014, 18:16 pm
No copio y pego, simplemente he empezado hace poco y aún no se hacerlo muy bien, nadie empieza sabiendo... Si copiara y pegara simplemente habría cogido el código que me ha dejado de ayuda leosansan.

Por supuesto, por eso en lugar de intentar sin ton ni son te recomiendo que adquieras las bases minimas indispensables para continuar. Y si, siempre hay algun iluminado que le hace el codigo a otro ...

Cuando le doy a depurar me sale que hay una violación de acceso a memoria (fallo de segmentación), ¿alguien me puede explicar lo que significa?

La variable global cadena es un puntero invalido, acostumbrate a inicializar las variables, no podes pretender escribir en el.