Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: ronbay en 17 Junio 2021, 02:06 am



Título: Frustracion
Publicado por: ronbay en 17 Junio 2021, 02:06 am
BUENAS GENTE.
AYUDA CON RECURSIVIDAD POR FAVOR.
tengo un ejercicio que tiene que contar cuantas palabras hay en una cadena.
lo he tratado de hacer de muchas maneras y no puedo resolverlo.
LES PASO LO QUE HICE PARA QUE ME PUEDAN GUIAR EN DONDE ESTOY MAL.

Código:
Byte CanPalabras(AnsiString x)
{Byte c;
  if (x == "") {//Caso Base
c = 0;
 }else{//Caso General

AnsiString letra = x[x.Length()];
x.Delete(x.Length(),1);
c = CanPalabras(x);

if (letra == " ") {
c++;
}
 }
 return c;

}

LES AGRADEZCO DE ANTEMANO


Título: Re: Frustracion
Publicado por: Xyzed en 17 Junio 2021, 03:13 am
Hola.

Ya habías abierto un post (https://foro.elhacker.net/programacion_cc/nesecito_ayuda_con_recusividad_por_favor_no_entiendo-t510360.0.html;msg2242848#msg2242848) con la misma pregunta. Tendrías que haber comentado en el mismo posteo la consulta, no está permitido abrir dos temas distintos sobre lo mismo.

Saludos.


Título: Re: Frustracion
Publicado por: Eternal Idol en 17 Junio 2021, 16:54 pm
AnsiString no es standard, usa std::string y depura tu codigo.


Título: Re: Frustracion
Publicado por: ronbay en 17 Junio 2021, 20:01 pm
ya lo resolvi..NO BUSCABA QUE LO HAGAN SOLO QUE ME DEN SU PUNTO DE VISTA, POR AHI ESTOY IGNORANDO ALGO
Código:
Byte CanPalabras(AnsiString x)
{Byte contador;

  if (x.Length()< 2) {//Caso Base
contador= x.Length();
 }else{//Caso General

char letra = x[x.Length()];
x.Delete(x.Length(),1);
char penul = x[x.Length()];
contador = CanPalabras(x);
if (letra != ' ' && penul == ' ') {
contador++;
}
}
 return contador;

MUCHAS GRACIAS DE TODOS MODOS.


Título: Re: Frustracion
Publicado por: Serapis en 17 Junio 2021, 23:48 pm
La cualidad que distingue una palabra de otra, es que medie un separador entre las palabras, cuando son más de una.

A su vez esto exige definir palabra y separador:
letra = 0|1|2|3...8|9|A|B|C...Y|Z|a|b|c|d...y|z| ...etc, si se precisan más
separador: espacio|tabulador|,|.|:|;|"| ...etc... si se precisan más
separadores = separador+   //uno o más separadores
palabra = letra+ // una o más letras
palabras = palabra [separador palabra]*

Una vez claro que letras pueden (son admitidas para) formar palabras y qué caracteres son un separador, se crean un array de 256 bytes indicando para cada uno, si es letra, separador (o no se admite = 0). Ese valor se toma de una enumeración y el array se crea al iniciar la aplicación.

Código:

array bytes Letras(256)

enumeracion ValorPalabra
    CARACTER_NO_APROBADO =0
    CARACTER_ES_LETRA = 1
    CARACTER_ES_SEPARADOR = 2
fin enumeracion

funcion inicializar
     ...
     Letras(09) =  CARACTER_ES_SEPARADOR  // el tabulador horizontal
     Letras(32) =  CARACTER_ES_SEPARADOR  // el espacio
     ...
     Letras(34) =  CARACTER_ES_LETRA   // comillas dobles
     ...
     Letras(48) =  CARACTER_ES_LETRA   // el dígito 0...
     ...
     Letras(65) =  CARACTER_ES_LETRA   // la letra A...
     ...
     Letras(97) =  CARACTER_ES_LETRA   // la letra a...
     ...
Fin funcion
La función se puede simplificar si se mete cada caracter aceptado como letra en un string y cada caracter admitido como separador en otro, y luego en sendos bucles, simplemente se toma cada carácter de dicho string y se le asigna el valor que toca.
El resto de caracteres tendrá el valor 0, señalando que o bien es un error o bien que se ignorará... (al gusto).

Finalmente puedes crear tu función, que sí, que puede ser recursiva, aunque es el tipo de casos que claramente no lo requiere, pero que para prácticas es adecuado.
En cuyo caso, convendría

Código:
entero BuscarPalabra(string Texto, entero Inicio, entero NumChars)
    entero j = inicio

    si (inicio = numchars) devolver 0 // impide buscar más allá del tamaño del texto.

    Hacer mientras  (texto(inicio) <> CARACTER_ES_SEPARADOR)  //caracteres no aprobados entre letras los ignora como si fueran letras.
        inicio +=1
        si (inicio = numchars) devolver 1
    repetir
    
    Hacer mientras  (texto(inicio) <> CARACTER_ES_LETRA)  // caracteres no aprobados entre separadores los ignora como separadores.
        inicio +=1
        si (inicio = numchars) devolver 1
    repetir
    
    si (inicio > j)   // caracteres no aprobados, pueden falsear esto.
        devolver  BuscarPalabra(texto, inicio, numChars) +1
    sino
        devolver  BuscarPalabra(texto, inicio, numChars)
    fin si
fin funcion

La función se invocaría tal que así:
Código:
texto = "Hola, esto es "..." 0001 ejemplo de pru3ba."
numPalabras = BuscarPalabra(texto, 0, texto.length)
mostrarMensaje "El texto: " + saltodelinea + texto + saltodelinea + "contiene: " + numpalabras + " palabras."
Cada llamada a la funcion BuscarPalabra, reconoce una palabra (o ninguna cuando se alcance el final).

Es del todo importante decidir qué caracteres pertencen a cada uno de los 3 grupos. Idealmente el grupo 'CARACTER_NO_APROBADO' no debería existir. Pero como nada es perfecto, ahi están. Se pueden ignorar o marcar como error, en el pseudocódigo se ignoran, pero su aparición puede arrojar error bajo determinadas condiciones, no se contempla evitar dicho errror, so pena de un código más complejo que luego interferirá con la comprensión.

Por supuesto, no necesitas construir el array ni tirar de la enumeración, sino del propio lenguaje, pero igualmente es preciso ilustrar dichos conceptos, sea que luego se construya o no. Para comprender el asunto, es preferible recrearlo y ver lo sencillo que es resolverlo.

El pseudocodigo está escrito al vuelo, pudiera hacerle falta un repaso, que queda a tu esfuerzo... lo mismo que entenderlo, y convertirlo a código.

...y no, no es necesario eliminar letras... imagina un texto de 100 millones de palabras, si con cada letra tienes que reconstruir otra cadena donde sea idéntica excepto en que ahora no tiene el que antes era el carácter primero/o ultimo (lo mismo me da, que me da lo mismo)... se haría eterno... simplemente avanza el puntero de lectura del char sobre el texto.


Título: Re: Frustracion
Publicado por: dijsktra en 25 Junio 2021, 21:21 pm
Aqui te va una propuesta de conteo de palabras con recursion...

(No es pa tanta frustración... Más se perdio en Cuba, que decía mi abuelo... ::) :D     )

Decir que es imprescindible llevar control de la primera posición de la linea - si queremos admitir lineas vacias - y del resultado provisional.

 

Código
  1.  
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6.  
  7. // Immersion:
  8. // ac = #i : 0 <= i < n : V[i]='nb' and (i>0 -> V[i-1]='b')
  9. // (s act as index n, in C-ish style)
  10. // 0 <= n <= len(p)
  11. int num_wordG(const char *p,const char *s, int ac)
  12. {
  13.  if (*s)
  14.    if (isspace(*s)) return num_wordG(p,++s,ac); // Rec.
  15.    else return num_wordG(p,s+1,ac+(p==s || isspace(*(s-1)))); // Rec.
  16.  return ac; // Basis case.
  17. }
  18.  
  19.  
  20. int main(int argc, char *args[])
  21. {
  22.  char *line = NULL;
  23.  size_t len = 0 ;
  24.  ssize_t nread;
  25.  for ( ; (nread = getline(&line, &len, stdin)) != -1; )
  26.    {
  27.      line[nread-1]=0; // chop the \n
  28.      printf("%s -> %i\n",line,num_wordG(line,line,0));
  29.    }
  30.  free(line);
  31.  return 0;
  32. }
  33.  
  34.  
  35.  
  36.  

Algunos casos de prueba...

Código:
En un lugar de la Mancha
En un lugar de la Mancha -> 6
son 3 palabras
son 3 palabras -> 3
una
una -> 1

 -> 0



Título: Re: Frustracion
Publicado por: ronbay en 29 Junio 2021, 16:57 pm
Gracias bro..con eso lo voy a mejorar el programa.