Problema con un programa en C (string.h y funciones)

Iniciado por loriik, 11 Marzo 2014, 01:00 AM

0 Miembros y 2 Visitantes están viendo este tema.

loriik

Hola, estoy aprendiendo a estudiar C, y estoy encallado en un ejercicio, mañana tengo el examen y pff.. espero que me podáis ayudar:

El ejercicio me pide que cree un programa que reconozca palindromos (frases o palabras que se leen tanto de derecha a izquierda, como de izquierda a derecha)

ej: Abusón, acá no suba (evidentemente en el programa no pondremos acentos ni comas)

yo he escrito de momento esto:

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

void invertida (char text[]);

int main ()
{
    char text[100], text2[100];
    int j, i;
    printf("\n Introduce un texto ");
    gets(text);
    strcpy(text2, text);
    invertida(text);
    j=strcmp(text, text2);
    if(j==0)
        printf("\n Es un palindromo ");
    else
        printf("\n No es un palindromo ");
   
printf("\n FIN DEL PROGRAMA \n ");
system("pause");
}

void invertida (char text[])
{
    int i, longitud;
    longitud=strlen(text);
    for(i=longitud-1; i>=0; i--)
    {
       
    }
   
}


Para saber si es un palíndromo, copio el texto con strcpy en otra char, luego invierto el texto original, y por último los comparo con strcmp, y lo igualo a j para poder hacer el if mas tarde. En teoría, si coinciden todos los caracteres, retorna un 0, y por eso pongo if (j==0)

El error creo que está en la función, en el bucle del for, y/o en la llamada a la función "invertida(text);" y me temo que será una tontería... pero bueno.. me tiene loco ya xD

Espero que me podais ayudar! Gracias!

PD: Perdón por si he hecho una estupidez con el programa... llevo poco estudiando C xD

engel lex

void invertida (char text[])
{
    int i, longitud;
    longitud=strlen(text);
    for(i=longitud-1; i>=0; i--)
    {
       
    }
   
}


hiciste un for... pero no hiciste nada en el D:
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

loriik

claro! ahí está el problema, no sé que poner dentro de ese for XD

leosansan

#3
El problema nace con la copia de text, cuando lo que deberías hacer es que text2 sea la copia invertida de text, lo que consigues con la función,. Y ya luego comparar:

Código (cpp) [Seleccionar]

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

void invertida (char text[],char invertida[]);

int main ()
{
   char text[100], text2[100]={""};
   int j, i;
   printf("\n Introduce un texto ");
   gets(text);
   invertida(text,text2);
   j=strcmp(text2, text);
   if(j==0)
       printf("\n Es un palindromo ");
   else
       printf("\n No es un palindromo ");

printf("\n FIN DEL PROGRAMA \n ");
system("pause");
}

void invertida (char text[],char text2[])
{
   int i, longitud;
   longitud=strlen(text);
   for(i=longitud-1; i>=0; i--)
   {
       text2[i]=text[longitud-1-i];/* AQUI LA COPIAS AL REVES*/
   }
   text2[i]='\0';

}



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








Yoel Alejandro

#4
Exactamente como dice leosasan, faltaba la parte donde realmente inviertes la palabra (?!). Y aparte yo recomendaría optimizar la parte donde haces la comparación, sin necesidad de usar la variable intermedia j (entre menos variables uses, el código será más ligero):
Código (cpp) [Seleccionar]

if( strcmp(text2, text) != 0 )
    printf("\n Es un palindromo ");
else
    printf("\n No es un palindromo ");
}


o más elegantemente, reemplazado strcmp(text2, text) != 0 por  !strcmp(text2, text) :
Código (cpp) [Seleccionar]

if( !strcmp(text2, text) )
    printf("\n Es un palindromo ");
else
    printf("\n No es un palindromo ");
}


=====================================================
(EDICIÓN)

Estaba pensando mejor el asunto, y no es necesario invertir toda la palabra para saber si es un palindromo. Es decir, basta que un carácter no coincida con su "complementario" en la otra mitad de la palabra. O sea si la palabra tiene una longitud N entonces basta que
Código (cpp) [Seleccionar]

text[i] != text[N - i - 1]

para saber que no es palíndromo, y en este punto el ciclo debería detenerse. Por la misma razón, es suficiente con escanear la primera mitad de la palabra, o sea desde i=0 y mientras i sea menor a N/2 caracteres (saca la cuenta, funciona con N par e impar).

Con todo esto, el código se puede depurar a:
Código (cpp) [Seleccionar]

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

int palindromo (char text[]);

int main ()
{

   char text[100];

   printf("\n Introduce un texto: ");
   gets(text);
   
   if ( palindromo(text) )
     printf("\n Es un palindromo ");
   else
     printf("\n No es un palindromo ");

   printf("\n FIN DEL PROGRAMA \n ");
   getchar( );
   
   return 0;
}

int palindromo (char text[])
{
   int i, N;

   N = strlen(text);
   for (i = 0; i < (float)N/2; i++)
   {
      if ( text[i] != text[N - i - 1] )
         return 0;
   }
   return 1;
}


Claro, entre más sofisticado se vuelva el código puede que este se ejecute más rápido pero aumenta la complejidad de algunos detalles del mismo (espero no abrumarte). Observa que el tipo de retorno de la función auxiliar palindromo se cambió a int, precisamente para que devuelva un valor numérico indicando si la palabra es palindromo o no.

Si no lo es, observa que la ejecución del for/ se detiene en algún momento cuando la condición dentro del if sea verdadera, y retorna 0. De lo contrario, continúa hasta el final y retorna 1.

Por último un detalle sutil. Cuando la longitud N de la palabra sea impar, el cociente N/2 será decimal, pero los tipos de las variables i, N son enteros, por eso la comparación i < N/2 no será válida. Es necesario convertir N a float para que admita los decimales y por eso ponemos i < (float)N / 2.

Por ejemplo, si N=5 entonces el programa debe ejecutarse con las primeras 3 letras de la palabra, y siendo N/2 = 2.5 ocurrirá justo así, se ejecutará para i=0, i=1, i=2. Por eso, funciona bien cuando N es impar.
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

engel lex

pongo mi granito de arena optimizando un poco más el código

int main (){
    char text[100];
    int j, i;
    printf("\n Introduce un texto ");
    gets(text);
    j=strlen(text);
    for(i=0;i<j;i++){
        if(text[i]!=text[j-i-1]){
            break;
        }
    }
    if(i==j)
        printf("\n Es un palindromo ");
    else
        printf("\n No es un palindromo ");

printf("\n FIN DEL PROGRAMA \n ");
system("pause");
}
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Yoel Alejandro

Uy, engelx se me adelantó, justo con la idea de interrupir el ciclo cuando ya se sepa que no es palíndromo. Lo que faltaría es recorrer sólo la primera mitad de la palabra, yeah!!
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

leosansan

#7
Cita de: yoel_alejandro en 11 Marzo 2014, 04:54 AM
Uy, engelx se me adelantó, justo con la idea de interrupir el ciclo cuando ya se sepa que no es palíndromo. Lo que faltaría es recorrer sólo la primera mitad de la palabra, yeah!!

Pues estrujando un poco más:

Código (cpp) [Seleccionar]

int main (){
   char text[100];
   int  i;
   printf("\n Introduce un texto:\n ");
   gets(text);
   for(i=0;text[i]==text[strlen(text)-i-1] && i<strlen(text)/2;i++);
   printf (i==strlen(text)/2 ? "\n Es un palindromo ": "\n No es un palindromo ");
   return 0;
}


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



engel lex

#8
int main (){
   char text[100];
   int i=0;
   printf("\n Introduce un texto:\n ");
   gets(text);
   while(text[i]==text[strlen(text)-i-1] && strlen(text)/2>i++);
   printf (i>strlen(text)/2 ? "\n Es un palindromo ": "\n No es un palindromo ");
   return 0;
}


solo por el bien de la competencia otra manera ligeeeeeeeeeramente más corta XD basado en leosansan (sin contar la j, que se te pasó, está es 5 caracteres más corta XD (creo))  aunque realmente no aporto nada XD solo lo hago por while en lugar de for
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Yoel Alejandro

Totalmente de acuerdo engelx, pero también hay considerar a veces que no sólo el código fuente sea más breve, sino que realmente se ejecute más rápido.

Por ejemplo, usas tres veces el strlen(text) es decir una sobrecarga por llamadas a función. Sería mejor definir una constante y asignarle el valor N = strlen(text), luego usas N. Esto quizá lleve más líneas de código fuente pero se ejecutará más rápido.
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)