Discussion:
Función para "homogeneizar" frases
(demasiado antiguo para responder)
Jorge S. de Lis
2006-03-04 15:48:50 UTC
Permalink
Buenas lista.

Estoy intentando hacer una función que "homogeinice" las frases para luego
comprobar si son palíndromas o no.

Tengo un problema, y es que a veces no funciona, y no sé por qué:

¿LIGARÁ GIL O NO LIGARÁ GIL? -> ligaragilonoligaragila
¿LIGARÁ GIL O NO LIGARÁ GIL -> ligaragilonoligaragil (bien)
ATRÁSALA, CÓRTESE SE TROCA LA SARTA; -> atrasalacortesesetrocalasartau
ATRÁSALA, CÓRTESE: SE TROCA LA SARTA -> atrasalacortesesetrocalasartau
ATRÁSALA, CÓRTESE. SE TROCA LA SARTA -> atrasalacortesesetrocalasarta (bien)

¿Alguien me puede echar un cable? Muchas gracias :-)


void homogeiniza(char *palabra){

int lonxitude,i,j;

for(i=0;i<lonxitude && palabra[i]!='\0';i++){
switch(palabra[i]){
case 'á':case 'ä':case 'à':
case 'Á':case 'Ä':case 'À':
palabra[i]='a';
break;
case 'é':case 'ë':case 'è':
case 'É':case 'Ë':case 'È':
palabra[i]='e';
break;
case 'í':case 'ï':case 'ì':
case 'Í':case 'Ï':case 'Ì':
palabra[i]='i';
break;
case 'ó':case 'ö':case 'ò':
case 'Ó':case 'Ö':case 'Ò':
palabra[i]='o';
break;
case 'ú':case 'ü':case 'ù':
case 'Ú':case 'Ü':case 'Ù':
palabra[i]='u';
}

if(palabra[i]>64 && palabra[i]<91)
palabra[i]=palabra[i]+32;
else{
if(palabra[i]<97 || palabra[i]>122){
for(j=i;palabra[j]!='\0' && j<lonxitude;j++){
palabra[j]=palabra[j+1];
}
i--;
}
}
}
return;

}
Jorge S. de Lis
2006-03-04 15:54:03 UTC
Permalink
Post by Jorge S. de Lis
void homogeiniza(char *palabra){
int lonxitude,i,j;
lonxitude=strlen(palabra);
Post by Jorge S. de Lis
for(i=0;i<lonxitude && palabra[i]!='\0';i++){
...
Post by Jorge S. de Lis
if(palabra[i]<97 || palabra[i]>122){
for(j=i;palabra[j]!='\0' && j<lonxitude;j++){
palabra[j]=palabra[j+1];
}
lonxitude--;
Post by Jorge S. de Lis
i--;
}
Qué fallos más tontos :)
Pero sigue funcionando igual :-( lo de lonxitude no sirve para nada
realmente.
Lokutus
2006-03-04 21:40:06 UTC
Permalink
Post by Jorge S. de Lis
Qué fallos más tontos :)
Pero sigue funcionando igual :-( lo de lonxitude no sirve para nada
realmente.
ischar()
isalpha()

etc.

- --
Lokutus, Asimilando la red.
Llave Pública en hkp://wwwkeys.eu.pgp.net
Lokutus
2006-03-04 21:48:39 UTC
Permalink
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Post by Jorge S. de Lis
Qué fallos más tontos :)
Pero sigue funcionando igual :-( lo de lonxitude no sirve para nada
realmente.
ischar()
isalpha()
etc.
y strtok()


- --
Lokutus, Asimilando la red.
Llave Pública en hkp://wwwkeys.eu.pgp.net
Jorge S. de Lis
2006-03-06 12:33:10 UTC
Permalink
Post by Lokutus
Post by Lokutus
ischar()
isalpha()
etc.
y strtok()
Gracias, no conocía estas funciones. Me fueron de bastante utilidad, y
seguro que lo son en el futuro. No resolví el problema, pero leyendo tu
envío se me vinieron ideas a la cabeza. A ver qué sale... :-)
Bartomeu
2006-03-06 00:01:22 UTC
Permalink
[...]
Los problemas creo que mas que en homogenizar palabras estará en otro sitio,
(Por cierto, ya que intentas utilizar todos los acentos de las vocales, te
has olvidado del acento circunflejo y las consonantes 'ñ' de año y 'ç' del
Barça).

Haz una función que diga directamente si una frase es palíndroma sin
separarla por palabras.

Primero una funciones preliminares triviales y optimizables:

bool es_una_a(char c) {
return ('a'==c) || ('A'==c) ||
('á'==c)||('à'==c)||('ä'==c)||('â'==c)||('Á'==c)||('À'==c)||('Ä'==c)||('Â'==c);
}

bool es_letra(char c) {
if (isalpha(c)) return true;
// testea si 'isalpha' detecta las vocales acentuadas la eñe y las
letras que quieras
// si no las detecta añade las siguientes lineas
if (es_una_a(c) return true;
// ... haz lineas equivalentes para la e, i, o, u, ñ y ç
return false;
}

bool son_equivalentes(char c1, char c2) {
if (toupper(c1)==toupper(c2)) return true;
if (es_una_a(c1)==es_una_a(c2)) return true;
// ... haz lineas equivalentes para la e, i, o, u, ñ y ç
return false;
}

Ahora la función que dada una frase te dice si es palíndroma:

bool es_palindroma(const char *frase) {
int izq = -1; // antes del primer carácter
int der = strlen(frase); // después del último carácter
while (izq<der) {
do { // busco una letra por la izquierda
izq++;
} while (!es_letra(frase[izq])&&(izq<der))
do { // busco una letra por la derecha
der--;
} while (!es_letra(frase[der])&&(izq<der))
if (izq<der) // si no nos hemos pasao
if (!son_equivalentes(frase[izq],frase[der]))
return false; // no es palíndroma, falla un par de
letras
}
// se han cruzado izq y der, es palíndroma
return true;
}

Era un problema interesante, y no me he podido resistir a intentar
solucionarlo. No lo he compilado pero creo que es una posible solución.
Acábalo y ya me dirás si funciona.

Si entiendes la función anterior, mírate la siguiente. Es equivalente, pero
ya para nota ;-)

bool es_palindroma(const char *frase) {
int izq = -1;
int der = strlen(frase);
while (izq<der) {
while (!es_letra(frase[++izq])&&(izq<der)); // Hay un punto y coma
final
while (!es_letra(frase[--der])&&(izq<der)); // Hay un punto y coma
final
if (izq<der)
if (!son_equivalentes(frase[izq],frase[der]))
return false;
}
return true;
}
Jorge S. de Lis
2006-03-06 12:41:49 UTC
Permalink
Post by Bartomeu
Los problemas creo que mas que en homogenizar palabras estará en otro
sitio, (Por cierto, ya que intentas utilizar todos los acentos de las
vocales, te has olvidado del acento circunflejo y las consonantes 'ñ' de
año y 'ç' del Barça).
Haz una función que diga directamente si una frase es palíndroma sin
separarla por palabras.
Eso ya es de muy máquina :-) realmente es un ejercicio chorras de juguete
para clase, no creo que haga falta matarse tanto.
Post by Bartomeu
[...]
Qué bonito :-) No voy a usar esta opción porque me parece que es pasarse,
pero cuando tenga un rato intentaré hacerlo así, que es muy interesante. De
todas formas te he robado algunas ideas ^_^.

He cambiado el problema de lugar y me he valido de alguna función auxiliar
más. Finalmente, el ejercicio ha quedado así:


/*
* 4.10 - Palíndromos
* Decir si una palabra es palíndroma o no
*/

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/*
* Devuelve la vocal sin acentuar. Si se le pasa una no vocal
* devuelve el mismo caracter.
*/

char vocal_sin_tilde(char c) {
if (('a'==c)||('A'==c)||('á'==c)||('à'==c)||('ä'==c)||
('â'==c)||('Á'==c)||('À'==c)||('Ä'==c)||('Â'==c)) return 'a';
if (('e'==c)||('E'==c)||('é'==c)||('è'==c)||('ë'==c)||
('ê'==c)||('É'==c)||('È'==c)||('Ë'==c)||('Ê'==c)) return 'e';
if (('i'==c)||('I'==c)||('í'==c)||('ì'==c)||('ï'==c)||
('î'==c)||('Í'==c)||('Ì'==c)||('Ï'==c)||('Î'==c)) return 'i';
if (('o'==c)||('O'==c)||('ó'==c)||('ò'==c)||('ö'==c)||
('ô'==c)||('Ó'==c)||('Ò'==c)||('Ö'==c)||('Ô'==c)) return 'o';
if (('u'==c)||('U'==c)||('ú'==c)||('ù'==c)||('ü'==c)||
('û'==c)||('Ú'==c)||('Ù'==c)||('Ü'==c)||('Û'==c)) return 'u';
return c;
}



/*
* Lee una cadena. Devuelve un puntero a la nueva cadena.
*/
char *lepalabra(void){

int i;
char auxchar;
char *palabra=NULL;

for(i=0;auxchar!='\012';i++){
auxchar=fgetc(stdin);
if(isupper(auxchar))
auxchar+=32;
if(!isblank(auxchar)&&!ispunct(auxchar)&&auxchar!='\012'){
auxchar=vocal_sin_tilde(auxchar);
palabra=(char*)realloc(palabra,sizeof(char)*(i));
palabra[i]=auxchar;
}
else
i--;
}
palabra=(char*)realloc(palabra,sizeof(char)*(i));
palabra[i]='\0';
return palabra;
}

/*
* Devuelve 0 si la palabra es palíndroma. Devuelve 0 si no lo es.
*/
int epalindroma(char *palabra){

int lonxitude,i,f;
lonxitude=strlen((char*)palabra);

for(i=0,f=(lonxitude-1);i<lonxitude/2;i++,f--){
// printf("%c - %c\n",palabra[i],palabra[f]);
if(palabra[i]!=palabra[f]) return 1;
}

return 0;

}


int main(void){
char *palabra=NULL, auxchar='\0';
int i;

printf("Introduce unha palabra ou frase: ");

if((palabra=lepalabra())[0]!='\0'){
// printf("%s\n",palabra);
printf((epalindroma(palabra)==0)?"É palíndroma\n":
"Non é palíndroma\n");
}
return 0;
}



Muchas gracias, así da gusto oye. :-**

Por cierto, que el fallo estaba en otro sitio ^_^U. Siempre he usado esa
función para leer la palabra, antes sin tantas condiciones (hacía la
"limpieza" de la palabra en la función que mandé primero).

El caso es que cuando probé "ANITA, LA GORDA LAGARTONA, NO TRAGA LA DROGA
LATINA" y vi que parecía que lo hacía bien, pero me decía que NO era
palíndroma, me empecé a mosquear.

Entonces vi con gdb que la cadena era
"anitalagordanotragaladrogalatina\017". Una mala condición de salida en la
función de leer la cadena era la causante después de todo esto ^_^U...

Saludos.
Bartomeu
2006-03-06 13:31:16 UTC
Permalink
Post by Jorge S. de Lis
[...]
Qué bonito :-) No voy a usar esta opción porque me parece que es pasarse,
pero cuando tenga un rato intentaré hacerlo así, que es muy interesante. De
todas formas te he robado algunas ideas ^_^.
Ya te pasaré una factura por el uso de mis ideas en 'vocal_sin_tilde'. Pero
como me gusta más tu función que las varias que habia que crear con mi
sitema, te lo perdonaré ;-)
Post by Jorge S. de Lis
[...]
"Non é palíndroma\n");
[...]
Por curiosidad, ¿el programa para que idioma está preparado? Gallego,
portugués... ¿Realmente necesitas todas las vocales con todos los acentos, o
simplemente quieres ser sistemático?

ROC
2006-03-04 23:53:51 UTC
Permalink
Hola:
Es posible que, según que entornos utilices (por ejemplo el C de
MSVisualStudio 6 bajo windows XP), el compilador no entienda las constantes
de caracteres acentuados y especiales ('á'...'ñ'...) prueba de substituirlos
por su valor numérico ascii o una secuencia de escape en hexadecimal u octal
(te adjunto una tabla en hexadecimal) en las sentencias "case:".
Ya dirás qué tal.
(El código que usas parece correcto)
Saludos
ROC



á \x0A0 é \x082 í \x0A1 ó \x0A2 ú \x0A3
Á \x0B5 É \x090 Í \x0D6 Ó \x0E0 Ú \x0E9
à \x085 è \x08A ï \x08B ò \x095 ü \x081
À \x0B7 È \x0D4 Ï \x0D8 Ò \x0E3 Ü \x09A
ç \x087 Ç \x080 ñ \x0A4 Ñ \x0A5 ¿ \x0A8
¡ \x0AD
Post by Jorge S. de Lis
Buenas lista.
Estoy intentando hacer una función que "homogeinice" las frases para luego
comprobar si son palíndromas o no.
¿LIGARÁ GIL O NO LIGARÁ GIL? -> ligaragilonoligaragila
¿LIGARÁ GIL O NO LIGARÁ GIL -> ligaragilonoligaragil (bien)
ATRÁSALA, CÓRTESE SE TROCA LA SARTA; -> atrasalacortesesetrocalasartau
ATRÁSALA, CÓRTESE: SE TROCA LA SARTA -> atrasalacortesesetrocalasartau
ATRÁSALA, CÓRTESE. SE TROCA LA SARTA -> atrasalacortesesetrocalasarta (bien)
¿Alguien me puede echar un cable? Muchas gracias :-)
void homogeiniza(char *palabra){
int lonxitude,i,j;
for(i=0;i<lonxitude && palabra[i]!='\0';i++){
switch(palabra[i]){
palabra[i]='a';
break;
palabra[i]='e';
break;
palabra[i]='i';
break;
palabra[i]='o';
break;
palabra[i]='u';
}
if(palabra[i]>64 && palabra[i]<91)
palabra[i]=palabra[i]+32;
else{
if(palabra[i]<97 || palabra[i]>122){
for(j=i;palabra[j]!='\0' &&
j<lonxitude;j++){
palabra[j]=palabra[j+1];
}
i--;
}
}
}
return;
}
Jorge S. de Lis
2006-03-06 12:43:51 UTC
Permalink
Post by ROC
Es posible que, según que entornos utilices (por ejemplo el C de
MSVisualStudio 6 bajo windows XP), el compilador no entienda las
constantes de caracteres acentuados y especiales ('á'...'ñ'...) prueba de
substituirlos por su valor numérico ascii o una secuencia de escape en
hexadecimal u octal (te adjunto una tabla en hexadecimal) en las
sentencias "case:". Ya dirás qué tal.
(El código que usas parece correcto)
Saludos
ROC
á \x0A0 é \x082 í \x0A1 ó \x0A2 ú \x0A3
Á \x0B5 É \x090 Í \x0D6 Ó \x0E0 Ú \x0E9
à \x085 è \x08A ï \x08B ò \x095 ü \x081
À \x0B7 È \x0D4 Ï \x0D8 Ò \x0E3 Ü \x09A
ç \x087 Ç \x080 ñ \x0A4 Ñ \x0A5 ¿ \x0A8
¡ \x0AD
Muchas gracias, además hasta me has puesto una tabla de equivalencias :-)
Lo hice nada más leer tu envío, y me empecé a rallar que a lo mejor era
culpa del signo, y nada... lo mismo. Como contesté a Bartomeu, al final
estaba en otro sitio.

Muchas gracias por cotestarme.
Zara
2006-03-06 07:16:10 UTC
Permalink
On Sat, 04 Mar 2006 16:48:50 +0100, "Jorge S. de Lis"
Post by Jorge S. de Lis
Buenas lista.
Estoy intentando hacer una función que "homogeinice" las frases para luego
comprobar si son palíndromas o no.
¿LIGARÁ GIL O NO LIGARÁ GIL? -> ligaragilonoligaragila
¿LIGARÁ GIL O NO LIGARÁ GIL -> ligaragilonoligaragil (bien)
ATRÁSALA, CÓRTESE SE TROCA LA SARTA; -> atrasalacortesesetrocalasartau
ATRÁSALA, CÓRTESE: SE TROCA LA SARTA -> atrasalacortesesetrocalasartau
ATRÁSALA, CÓRTESE. SE TROCA LA SARTA -> atrasalacortesesetrocalasarta (bien)
¿Alguien me puede echar un cable? Muchas gracias :-)
void homogeiniza(char *palabra){
int lonxitude,i,j;
for(i=0;i<lonxitude && palabra[i]!='\0';i++){
switch(palabra[i]){
palabra[i]='a';
break;
palabra[i]='e';
break;
palabra[i]='i';
break;
palabra[i]='o';
break;
palabra[i]='u';
}
if(palabra[i]>64 && palabra[i]<91)
palabra[i]=palabra[i]+32;
else{
if(palabra[i]<97 || palabra[i]>122){
for(j=i;palabra[j]!='\0' && j<lonxitude;j++){
for(j=i;j<=lonxitude;j++){
Necesitas copiar también el caracter cero terminal, para que realmente
se eleimine el carácter que te sobra.
Post by Jorge S. de Lis
palabra[j]=palabra[j+1];
}
i--;
}
}
}
return;
}
Saludos,

Zara
Jorge S. de Lis
2006-03-06 12:47:27 UTC
Permalink
Post by Zara
for(j=i;j<=lonxitude;j++){
Necesitas copiar también el caracter cero terminal, para que realmente
se eleimine el carácter que te sobra.
Gracias por contestar, Zara, pero si te fijas copio el i+1 caracter encima
del i, por lo que si voy hasta i, el anterior de '\0', ya copio el '\0' que
está en i+1 encima del que estaba en i.

Gracias de todas formas, estas cosas me pasan a veces (a más gente imagino
que también, claro).

Saludos.
Loading...