Foros aprenderaprogramar.com

Aprender a programar => C, C++, C#, Java, Visual Basic, HTML, PHP, CSS, Javascript, Ajax, Joomla, MySql y más => Mensaje iniciado por: rackdon en 09 de Junio 2014, 19:41

Título: recursivo comprobar palabra palíndromo búsqueda lineal en arreglo C (lenguajec)
Publicado por: rackdon en 09 de Junio 2014, 19:41
Buenas tardes.

He  escrito el siguiente código para ver si una palabra es un palíndromo a través de una función recursiva.

El problema está en que curiosamente siempre devuelve 0 ¡¡¡Aunque por probar puse que fuera o no palíndromo devolviera 1!!!  La verdad esque por más que he buscado, no encuentro el fallo de porque devuelve siempre el valor 0:

Pongo el código a continuación.

Muchas gracias por todo

Código: [Seleccionar]
// Ejercicio 6.33: Palíndromos //

#include <stdio.h>

int pruebaPalindromo(char palabra[], int longitud );

main()
{
      int palindromo;
      char palabra[20];
      int longitud = 0;
     
      printf("Por favor, introduzca una palabra: ");
      scanf("%s", palabra);
     
      while(palabra[longitud] != '\0' )
      {
            longitud++;
      }
     
      palindromo = pruebaPalindromo(palabra, longitud - 1 );
      printf("\npalindromo  %d\n\n",palindromo);
     
      if(palindromo == 1)
         printf("\nLa palabra introducida ES un pal%cndromo\n\n", 161);
         
      if(palindromo == 0)
         printf("\nLa palabra introducida NO ES un pal%cndromo\n\n", 161);
     
     
      system("pause");
      return 0;
}

int pruebaPalindromo (char palabra[], int longitud )
{
    static int letra = 0;
   
    printf("%d\n", letra);
   
             if (palabra[letra] != palabra[longitud-letra] || letra > longitud/2 )
             {
                 printf("Longitud es %d\n", longitud);
                 printf("La letra es %d\n", letra);
                 if(letra <= longitud / 2   )
                    return 1;
                 else
                    return 1; // Debería de ser 0, pero puse 1 para ver si aún así seguía devolviendo 0//
             }
             
             else
             {
                     
                 printf("'%c' es igual a '%c'\n", palabra[letra],palabra[longitud  - letra] );     
                 letra++;
                 pruebaPalindromo(palabra, longitud );
                 
             }
   
}
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: Ogramar en 09 de Junio 2014, 20:23
Para plantear una función recursiva tienes que definir cuál es el caso base que te permite terminar la recursión, así como una condición que haga ir evolucionando la recursión.

Pareces tratar de hacer evolucionar la recursión usando la variable letra, pero letra está declarada dentro de la función recursiva, con lo cual se crean tantas copias de esta variable como llamadas se hagan a la función.

La llamada pruebaPalindromo(palabra, longitud ); siempre te estaría devolviendo lo mismo, no habría evolución... no veo claro cómo lo quieres plantear ¿cuál es tu idea?
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: rackdon en 09 de Junio 2014, 20:32
A ver, mi idea (que creo que es lo que he hecho aunque no estoy muy seguro ya) es que la función recursiva acabe cuando deje de haber coincidencia entre las letras, o se llegue a la mitad de la palabra, a través de la variable letra(por eso la puse static, para que guarde los resultados).
Y todo transcurre de forma correcta hasta que acaba la función recursiva, que en ese caso devuelve siempre 0 (aunque no he marcado que devuelva 0 en ningún sitio para ver si veía el error).
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: rackdon en 09 de Junio 2014, 20:39
mira, he hecho otro ejercicio de recursividad(esta vez de búsqueda lineal a través de una matriz)  y me pasa lo mismo, se ejecuta todo bien,pero luego al devolver un resultado, devuelve lo que no debe.
Pongo el código a continuación, porque creo que el fallo es el mismo que en el ejercicio de los palíndromos.

Código: [Seleccionar]
// Ejercicio 6.34: búsqueda lineal (recursivo) //

#include <stdio.h>
#define TAMANIO 100

/* prototipo de la función */
int busquedaLineal( const int arreglo[], int llave, int tamanio );

/* la función main comienza la ejecución del programa */
int main()
{   
   int a[ TAMANIO ]; /* crea el arreglo a */
   int x; /* contador para inicializar los elementos de 0 a 99 del arreglo a */
   int llaveBusqueda; /* valor para localizar en el arreglo a */
   int elemento; /* variable para almacenar la ubicación de llaveBusqueda o -1 */

   /* crea los datos */
   for ( x = 0; x < TAMANIO; x++ ) {
      a[ x ] = 2 * x;
   } /* fin de for */

   printf( "Introduzca la llave de busqueda entera:\n" );
   scanf( "%d", &llaveBusqueda );

   /* intenta localizar llaveBusqueda en el arreglo a */
   elemento = busquedaLineal( a, llaveBusqueda, TAMANIO );

   /* despliega los resultados */
   if ( elemento != -1 ) {
      printf( "Encontre el valor en el elemento %d\n", elemento );
   } /* fin de if */
   else {
      printf( "Valor no encontrado\n" );
   } /* fin de else */

   system("pause");
   return 0; /* indica terminación exitosa */

} /* fin de main */

/* compara la llave con cada elemento del arreglo hasta que localiza el elemento
   o hasta que alcanza el final del arreglo; devuelve el subíndice del elemento
   si lo encontró o -1 si no lo encontró */
int busquedaLineal( const int arreglo[], int llave, int tamanio )
{
   static int n = 0; /* contador */

   /* ciclo a través del arreglo */
   if (n < tamanio) {

      if ( arreglo[ n ] == llave ) {
         return n; /* devuelve la ubicación de la llave */
      } /* fin de if */
      else
      {
          printf("%d\n", n);
          n++;
          busquedaLineal( arreglo, llave, tamanio );
      }

   } /* fin de if */
   
   else
   {
   return -1; /* llave no encotrada */
   }

} /* fin de la función busquedaLineal */

Título: Re:comprobar si una palabra es un palíndromo
Publicado por: Ogramar en 10 de Junio 2014, 10:40
A mí el código que has puesto sí me funciona bien, me devuelve el índice del array donde se encuentra el elemento buscado, pero el diseño de la recursión con una variable estática dentro de la función recursiva no es un buen diseño por varios motivos. Para no hacer esto hay varias soluciones posibles, una de ellas introducir el parámetro de evolución dentro de la propia llamada recursiva (con lo cual no dependes de una variable estática), como en este código:

Código: [Seleccionar]
// Ejercicio 6.34: búsqueda lineal (recursivo) //

#include <stdio.h>
#define TAMANIO 100

/* prototipo de la función */
int busquedaLineal( const int arreglo[], int llave, int tamanio, int n );

/* la función main comienza la ejecución del programa */
int main() {
    int a[ TAMANIO ]; /* crea el arreglo a */
    int x; /* contador para inicializar los elementos de 0 a 99 del arreglo a */
    int llaveBusqueda; /* valor para localizar en el arreglo a */
    int elemento; /* variable para almacenar la ubicación de llaveBusqueda o -1 */

    /* crea los datos */
    for ( x = 0; x < TAMANIO; x++ ) {
        a[ x ] = 2 * x;
    } /* fin de for */

    printf( "Introduzca la llave de busqueda entera:\n" );
    scanf( "%d", &llaveBusqueda );

    /* intenta localizar llaveBusqueda en el arreglo a */
    elemento = busquedaLineal( a, llaveBusqueda, TAMANIO, 0);

    /* despliega los resultados */
    if ( elemento != -1 ) {
        printf( "Encontre el valor en el elemento %d\n", elemento );
    } /* fin de if */
    else {
        printf( "Valor no encontrado\n" );
    } /* fin de else */

    system("pause");
    return 0; /* indica terminación exitosa */

} /* fin de main */

/* compara la llave con cada elemento del arreglo hasta que localiza el elemento
   o hasta que alcanza el final del arreglo; devuelve el subíndice del elemento
   si lo encontró o -1 si no lo encontró */
int busquedaLineal( const int arreglo[], int llave, int tamanio, int n ) {

    /* ciclo a través del arreglo */
    if (n < tamanio) {

        if ( arreglo[ n ] == llave ) {
            return n; /* devuelve la ubicación de la llave */
        } /* fin de if */
        else {
            printf("%d\n", n);
            busquedaLineal( arreglo, llave, tamanio, n+1 );
        }

    } /* fin de if */

    else {
        return -1; /* llave no encotrada */
    }

} /* fin de la función busquedaLineal */

Aquí puedes ver algunas referencias:

Rather than using a static variable for index, it would be better to pass it in as an argument to recursive; otherwise, the function is non-reentrant.

http://stackoverflow.com/questions/1697777/recursion-using-c-language

Which has the benefit of not requiring the caller to supply an argument to foo() and also you don't need a static variable (which I always feel is a bad idea).

http://stackoverflow.com/questions/1316809/recursive-function-with-static-variable
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: rackdon en 12 de Junio 2014, 12:39
buenos dias.
He modificado el código pero sigue sin funcionar, me da valores raros.
El código es este:
Código: [Seleccionar]
// Ejercicio 6.34: búsqueda lineal (recursivo) //

#include <stdio.h>
#define TAMANIO 100

/* prototipo de la función */
int busquedaLineal( const int arreglo[], int llave, int tamanio, int n );

/* la función main comienza la ejecución del programa */
int main()
{   
   int a[ TAMANIO ]; /* crea el arreglo a */
   int x; /* contador para inicializar los elementos de 0 a 99 del arreglo a */
   int llaveBusqueda; /* valor para localizar en el arreglo a */
   int elemento; /* variable para almacenar la ubicación de llaveBusqueda o -1 */

   /* crea los datos */
   for ( x = 0; x < TAMANIO; x++ ) {
      a[ x ] = 2 * x;
   } /* fin de for */

   printf( "Introduzca la llave de busqueda entera:\n" );
   scanf( "%d", &llaveBusqueda );

   /* intenta localizar llaveBusqueda en el arreglo a */
   elemento = busquedaLineal( a, llaveBusqueda, TAMANIO, 0 );
printf( "elemento = %d\n", elemento );
   /* despliega los resultados */
   if ( elemento != -1 ) {
      printf( "Encontre el valor en el elemento %d\n", elemento );
   } /* fin de if */
   else {
      printf( "Valor no encontrado\n" );
   } /* fin de else */

   system("pause");
   return 0; /* indica terminación exitosa */

} /* fin de main */

/* compara la llave con cada elemento del arreglo hasta que localiza el elemento
   o hasta que alcanza el final del arreglo; devuelve el subíndice del elemento
   si lo encontró o -1 si no lo encontró */
int busquedaLineal( const int arreglo[], int llave, int tamanio, int n )
{
    printf("llave=%d  tamanio = %d  n = %d\n",llave,tamanio, n);
   

      if ( arreglo[ n ] == llave || n == -1 ) {
           printf( "n = %d\n", n );
         return n; /* devuelve la ubicación de la llave */
      } /* fin de if */
      else
      {
          busquedaLineal( arreglo, llave, tamanio, n+1 );
      }

 
} /* fin de la función busquedaLineal */

Puse printf a la salida de la función para ver el valor de n, y tambien en main para ver el valor de la variable elemento.
En teoría elemento debería ser igual a 'n', sin embargo, da igual la cifra que se ponga, siempre tiene valor 2686324.
Sinceramente no entiendo que falla y me estoy volviendo un poco loco.
Agradecería cualquier ayuda
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: Ogramar en 12 de Junio 2014, 14:17
A mí el código que te puse en la respuesta anterior sí me funciona bien, o eso parece. Por ejemplo:

Introduzca la llave de búsqueda entera: 6
0
1
2
Encontre el valor en el elemento 3



Introduzca la llave de búsqueda entera: 5
0
1
2
...
hasta 99
Valor no encontrado


Introduzca la llave de búsqueda entera: 100
0
1
2
...
Encontre el valor en el elemento 50


Si tú no obtienes estos resultados puede estar relacionado con algún detalle de la configuración del ide o compilador que estés utilizando.
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: rackdon en 12 de Junio 2014, 16:06
Muchas gracias.

He probado tu código y me da el mismo resultado que en lo que yo modifiqué (2686324).
Asique supongo que será problema del compilador.

Uso dev-c++. Sabes alguna forma para que lo pudiera arreglar.

Muchas gracias
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: Ogramar en 12 de Junio 2014, 18:08
Habría que revisar con calma muchas cosas para poder determinar algo, el problema puede venir por distintos motivos.

Aparentemente dev-c++ es un proyecto abandonado, y la alternativa sería Orwell Dev-C++, http://sourceforge.net/projects/orwelldevcpp/

Pero desconozco si va bien o no.

Generalmente codeblocks suele ir bien, http://www.codeblocks.org/downloads/26

codeblocks-13.12mingw-setup.exe te instala el ide y el compilador mingw.

Si te decides por instalar otro entorno, posiblemente si sería aconsejable desinstalar previamente lo que tengas, de cualquier manera ten cuidado con las instalaciones y desinstalaciones porque podrías perder cosas si no haces copia de seguridad. También se presenta el problema de no tener garantías sobre el correcto funcionamiento de la nueva instalación, así que no tomaría la decisión demasiado rápido.

Título: Re:comprobar si una palabra es un palíndromo
Publicado por: rackdon en 12 de Junio 2014, 19:55
Buenas tardes.

Entonces, que entorno de desarrollo me recomendarias para windows? y para linux-ubuntu? Es mejor usar un entorno de desarrollo o compilarlo a traves de la consola?

Muchas gracias
Título: Re:comprobar si una palabra es un palíndromo
Publicado por: Ogramar en 12 de Junio 2014, 20:03
Codeblocks, lo tienes disponible tanto para windows como para linux y te permite trabajar tanto con c como con c++

La mayoría de la gente prefiere trabajar con un entorno de desarrollo porque ofrece más comodidades (yo mismo suelo trabajar así normalmente).

Título: Re:comprobar si una palabra es un palíndromo
Publicado por: rackdon en 12 de Junio 2014, 21:51
He estado mirando en entornos de desarrollo para ubuntu, y los que más me han convencido son codeblocks, eclipse y anjuta. Da lo mismo usar uno que otro? ventajas o desventajas de alguno de ellos?. Esque estoy empezando con la programación por mi cuenta y además me instale linux hace nada asique estoy perdido por partida doble ejejeje.
Muchas gracias por toda tu ayuda.
Un saludo