Pues la idea que se me ocurrió en el otro post resultó ser más sencilla de lo que me imaginé, y ahora sà la función recursiva se ve mucho mejor, ya es mucho más que un ciclo disfrazado.
Comenté extensivamente el código, asà que aquà está:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| #include<string.h>
#include<iostream>
using namespace std;
int len, n=0;
string chk4palindrosity(string thestr)
{
if(thestr[0] == thestr[thestr.length() - 1]) // comparar primer caracter con ultimo
{
n++;
if(n == len / 2) // si el numero de veces que la comparación ha sido cierta es...
return "Si es palindromo!"; // igual a la mitad de los caracters, es palindromo
thestr.erase(0, 1); // borramos primer caracter
thestr.erase(thestr.length() - 1, 1); // borramos ultimo
return chk4palindrosity(thestr); // llamamos a la función con el string recortado
}
else // si una de las comparaciones no es cierta, no es palÃndromo
return "No es palindromo";
}
int main()
{
char inputf[50]={0}, input[50], *parte;
cout<<"Introduce un palindromo: "; cin.getline(input, '\n');
parte = strtok(input, " "); //
strcat(inputf, parte); //
while((parte = strtok(NULL, " ")) != NULL) //
strcat(inputf, parte); // quitar espacios del array
string thestr(inputf); // convertir array en string para facilitar operaciones
len = thestr.length(); // obtener longuitud del string
if(len == 1)
cout << "Si es palindromo!";
else
cout << chk4palindrosity(thestr); // llamar a la funcion e imprimir lo que retorne
cin.get();
} |
Lo que hace la función recursiva es comparar el primer caracter con el último, si son iguales recortarlos y llamarse; si no, no es palÃndromo. Cualquier duda ya saben que los comentarios están abiertos.
Hace unos dÃas me pidieron por correo un programa que nos dijera si un string es palÃndromo o no, pero usando una función recursiva. Me pareció interesante aunque raro que pidieran hacerlo de forma recursiva.
Tal vez recuerden que ya habÃa publicado aquà una forma de saber si un string es palÃndromo o no, el cual he descubierto (ahora que hice este otro) que no es muy eficiente.
Bueno pues el código es este:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| #include<string.h>
#include<iostream>
using namespace std;
char cadenaf[50]={0}; int len, n=0;
string chk4palindrosity(int c)
{
if(cadenaf[c] == cadenaf[len-1-c])
{
n++;
if(n == len/2)
return "Si es palindromo!";
return chk4palindrosity(c+1);
}
else
return "No es palindromo";
}
int main()
{
char cadena[50],*parte;
cout<<"Introduce un palindromo: "; cin.getline(cadena,50,'\n');
parte = strtok(cadena," "); //
strcat(cadenaf,parte); //
while((parte = strtok(NULL," ")) != NULL) //
strcat(cadenaf,parte); // quitar espacios del string
len = strlen(cadenaf);
cout << chk4palindrosity(0);
cin.get();
} |
La verdad es que es la función es recursiva de puro milagro. Lo que hice fue transformar el ciclo que checaba que los caracteres fueran iguales en una función en la que se aumenta una variable cada vez que se llama a sà misma.
El código ahora es más eficiente por dos simples razones:
- Se detiene y da el resultado a la primera comparación de caracteres que no sean iguales. Si el primer y el último caracter no son iguales, no es palÃndromo y ya no sigue analizando los demás.
- Sólo checa la mitad de los caracteres. Si la mitad de los caracteres corresponden a la configuración de un palÃndromo, ya no hay porqué seguir analizando la otra mitad.
Tal vez una mejor manera de hacerlo serÃa con una función que recibiera el string a analizar, comparar el primer y último caracter: si no, no es; si si, eliminar el primer y último caracter y volver a llamar a la función. Esto hasta que el numero de comparaciones ciertas sea igual a la mitad de la longitud inicial del string. ¿Alguien se anima a hacerlo?
No sé, es algo que se me ocurrió y que es muy fácil de hacer. Lo único que tenemos que hacer es ver a un string no como una frase, sino como un conjunto de caracteres; y además ver a los caracteres no como letras, sino números del código ASCII.
Teniendo esto claro, es muy fácil generar un números aleatorios (que representas letras) para llenar cada elemento del arreglo que es nuestro string. Veamos:
#include<stdlib.h>
#include<time.h>
#include<iostream>
using namespace std;
int main()
{
char strrnd[10];
srand(time(NULL));
for(int i=0; i <= 9; i++)
strrnd[i] = 33 + rand() % (126 - 33);
cout << strrnd;
cin.get();
}
- Primero declaramos un string de nombre strrnd.
- Luego inicializamos nuestro random.
- Con un ciclo recorremos cada elemento del string.
- Y cada elemento lo llenamos con un número aleatorio entre 33 y 126, que en el código ASCII representan todos las sÃmbolos letras y números normales.
- Y listo, ya hemos creado un string aleatorio en c++.
Si tienen duda con los números aleatorios pueden checar este post: Obtener número aleatorios en c++. Aquà pueden ver el código ASCII.
Si quieren que muestre, por ejemplo, solo letras minúsculas, tendrÃan que modificar la fórmula del random para que generara números entre el 97 y 122.
Bueno, siguiendo con la lÃnea de los posts sobre la librerÃa string.h les traigo esta función que no está en esa librerÃa pero que es muy útil al trabajar con strings. Ya dijimos que un/una string es una variable que puede contener 0, uno o más caracteres.
Ya vimos en nuestra introducción a string.h cómo declarar un string, hacerle algunas modificaciones y cómo mostrarlo. Ahora veremos como pedir un string (que el usuario la introduzca por medio del teclado).
Esto es muy sencillo si usamos la función cin.getline(); Esta función necesita tres datos o parámetros:
- Nombre. El nombre de la variable que va a contener el string
- Longitud. La cantidad de caracteres que queremos que se puedan introducir (nunca mayor que la longitud del string).
- Caracter de fin. El caracter que el usuario va usar como final de la cadena. Por lo general es el ‘enter‘ que se representa como ‘\n’ (diagonal n).
Por ejemplo, supongamos que tenemos un arreglo char de 500 elementos llamado str (nuestra string) y queremos pedirle al usuario que la “llene”, la función cin.getline quedarÃa asÃ:
cin.getline(str, 500, '\n');
Como ven, los parámetros van separados por comas (,), y el caracter de fin está entre comillas simples (‘). Pero bueno, dejemos de suponer y empecemos a programar.
#include<iostream>
using namespace std;
int main()
{
char str[500];
cout << "Introduce una frase: ";
cin.getline(str, 500, '\n');
cout << "Tu frase es: " << str;
cin.get();
}
Mas sencillo no podrÃa ser.
string.h es una librerÃa de c++ que contiene funciones que nos facilitan la vida al trabajar con cadenas o strings. Una cadena es un conjunto de caracteres almacenados en una variable.
DeberÃamos saber que char es un tipo de dato que almacena un caracter, por lo tanto un arreglo lineal de caracteres es una cadena:
char str[100];
Ahora podemos llenar nuestra cadena..
str ="Soy una cadena";
…y mostrarla
cout << str;
Pero recuerden que no podemos hacer nada de esto si no tenemos incluida la librerÃa string.h. Vamos a ver un programa de ejemplo:
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
char esunacadena[100] = "Soy una cadena", esunacopia[100];
strcpy(esunacopia, esunacadena);
strcat(esunacopia, " - copia");
cout << esunacadena << endl << esunacopia;
cin.get();
return 0;
}
- Primero declaramos dos cadenas (‘esunacadena’ y ‘esunacopia’) que pueden tener hasta 100 caracteres, ‘esunacadena’ la llenamos con el texto “Soy una cadena“.
- Luego con la función strcpy copiamos el contenido de ‘esunacadena’ a ‘esunacopia’. Ahora las dos cadenas tienen el mismo texto.
- Ahora con la función strcat agregamos el texto ” - copia” al final de’esunacopia’.
- Al final solo mostramos las dos cadenas.
Bastante fácil ¿no? En los próximos dÃas voy a postear otros programas muy sencillos para seguir checando las funciones mas comunes para trabajar con cadenas.
Pues si, en este post vamos a hacer un programa en c++ que lee una frase y luego la muestra centrada en la pantalla, todo eso ¡sin usar gotoxy! wow.
Bueno, usando gotoxy serÃa mas fácil, pero este blog promueve el no uso de la librerÃa conio.h (Cómo dejar de usar conio.h) asà que lo vamos a hacer como les dije.
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
char str[100];
cout << "Una frase: "; cin.getline(str, 100, '\n');
int numofch = strlen(str);
for(int i=1; i<(40-(numofch/2)); i++)
cout << " ";
cout << str;
cin.get();
return 0;
}
A la consola le caben 80 caracteres a lo largo, su mitad son 40; enseguida tenemos que averiguar el numero de caracteres que tiene la frase que se acaba de introducir y dividirlo entre dos. Supongamos que la frase es “hola”:
- ‘Hola’ tiene 4 caracteres.
- La mitad de la consola es 40.
- Si a los 40 le restamos la mitad de los caracteres de la frase, obtenemos el punto en donde debe comenzar la frase para quedar centrada. 40 – (4/2) = 38
- Ahora con un ciclo damos 38 espacios y luego imprimimos la frase.
Si quieren utilizar gotoxy, el proceso es el mismo hasta el último paso, donde guardarÃan el valor obtenido en una variable y luego lo pondrÃan en el lugar adecuado de la función.
La función strlen está en la librerÃa string.h y nos devuelve el número de caracteres que tiene una cadena, viene de string length.
A propósito me he dado cuenta que no he hablado casi nada de la librerÃa string.h, voy a ver si hago unos cuantos posts sobre ella.
Lo primero que tendrÃamos que hacer serÃa quitar los espacios de nuestra cadena. Luego ir comparando, el primer caracter con el último, el segundo con el penúltimo, etc. Si todos los caracteres coinciden, es palÃndromo, si no, pues no.
#include<string.h>
#include<iostream>
using namespace std;
int main()
{
char cadena[50],cadenaf[50]={0},*parte;
int c,len,pal=0;
cout<<"Introduce un palÃndromo: "; cin.getline(cadena,50,'\n');
parte=strtok(cadena," ");Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â //
strcat(cadenaf,parte);Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â // quita los espacios de 'cadena' y
while((parte=strtok(NULL," ")) != NULL)Â // guarda el resultado en 'cadenaf'
strcat(cadenaf,parte);Â Â Â Â Â Â Â Â Â Â Â Â Â //
len=strlen(cadenaf);
for(c=0;c<=len-1;c++)
{
if(cadenaf[len-1-c]==cadenaf[c]) // comparación del primer caracter con el
pal++; // último, el segundo con el penúltimo, etc
}
if(pal==len) // si todos las caracteres coinciden, sà es palÃndromo
cout<<"SÃ es palÃndromo!";
else
cout<<"No es palÃndromo";
cin.get();
}
/*Creado por THEbatzuk*/
Este programa lee una frase por medio de cin.getline y con la función strtrok le quita los espacios. Cada vez que corta la cadena, un contador se aumenta. Al final se obtiene la longitud de la cadena sin espacios con la función strlen.
/*Programa para contabilizar el número de letras y de espacios
que tiene una frase */
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
char frase[100], *parte, frasef[100]={0};
int lng,spc=0;
cout<<"Introduce una frase: "; cin.getline(frase, 100, '\n');
parte=strtok(frase," ");
strcat(frasef,parte);
while((parte=strtok(NULL," ")) != NULL)
{
strcat(frasef,parte);
spc++;
}
lng=strlen(frasef);
cout<<"Tu frase tiene "<<lng<<" letras y "<<spc<<" espacios";
cin.get();cin.get();
return 0;
}
/*Creado por THEbatzuk*/