Duda con contador de palabras en C para principiantes

Iniciado por al2000, 22 Octubre 2018, 09:57 AM

0 Miembros y 1 Visitante están viendo este tema.

al2000

Hola! Soy nuevo en programación en C y hay un ejercicio que me pide que cuente las palabras de una frase acabada en '.', además de tener en cuenta los espacios en medio y sin utilizar strings ni vectores.

Mi problema es que he visto muchos tipos de códigos que lo resolvían con strings y eso aún no sé como aplicarlos.

Quizás deberia de cambiarlo por un while? O un do-while?
El codigo que de momento tengo es:


#include <stdio.h>

int main()
{
   int cont;
   char frase;

   printf("Introduzca una frase acabada en punto: ");
   scanf("%c", &frase);

     
   if(frase != ' ' && frase != '.' )
   {
       cont++;
   }
   
   
   printf("\nNumero de palabras: %d\n", cont);

}

Dresden

#include <stdio.h>
#include <ctype.h>  // isalpha()

int main(void) {
    int nPalabras = 0;
    int existeLetra = 0;
    char caracter = '\0';

    while (caracter != '.') {
        scanf("%c", &caracter);

        if (!existeLetra) {
            existeLetra = isalpha(caracter);
        }

        if (existeLetra) {
            if (caracter == ' ') {
                ++nPalabras;
                existeLetra = 0;
            }

            if (caracter == '.') {
                ++nPalabras;
            }
        }
    }

    printf("Total palabras: %i\n", nPalabras);

    return 0;
}
PROGRAMMER
noun. [pro-gram-mer]
Someone who solves a problem
you didn't know you had, in a way
that you don't understand.

See also wizard, magician.

dijsktra

#2
La solución anterior es incorrecta: en el momento en que haya más de un espacio entre palabras, o mismamente cuando no haya palabras, el cálculo es errónea.

Propongo esta.

No tengo un compilador a mano para probarlo...
Pero si metes una frase, sin punto al final, no hace falta, debe funcionar.... No metas más que 'a', 'z' y ' '

Código (cpp) [Seleccionar]



/*


 P : V[0..N) , N>= 0  
 Q : (c = # i, j: 0 <= i < j <= N : word(V, i, j))

     where
word(V,n,m) : allesnb(n, m) and (n>0 - > V[n-1]=' ') and  (m<N- > V[m]=' ')


Snapshot invariant:
-------------------






  I : Q[N/n]
      and 0 <= n <= N
     

  B : n<N


  C(n) = N - n  >= 0

  Init:
  -----
    n,c = 0,0

  Step:
  ------
    n= n + 1 (Clearly, quota decreases)


  Restore:
  --------
     c = c +\chi (V[n]! =' ' && (n=0 ||   V[n-1]==' '))


  Pseudo-code:
  ------------

  n,c= 0,0
  while  n < N
      c = c +\chi (V[n]! =' ' && (n=0 ||   V[n-1]==' '))
     n= n +1
  end
  return c

 
O(N) since while;s body is in O(1) and f_iter in O(N)
     
*/

#include <iostream>
#include <algorithm> // max,min
#include <string> // to string, to use


using namespace std;
#define MAX 100000


/* See full development and derivation above*/
int solve(const char V[], const int N)
{
 int c,n;
 for(n=c=0;n<N;n++)
      c +=(V[n]!=' ' && (!n ||   V[n-1]==' '));
 return c;
}


int main(int argc, char *arg[])
{
 int n,N;
 string V;
 for(;getline(cin, V) ;)
     cout << solve(V. c_str() ,V.length() ) << endl;
 return 0;
}

Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)

Dresden

Cita de: al2000 en 22 Octubre 2018, 09:57 AM...un ejercicio que me pide que cuente las palabras de una frase acabada en '.'...

El título del tema nos dice que se trata de un ejercicio para principiantes, por esto, al leer la parte de la pregunta que cité anteriormente, deduje que la entrada del programa siempre sería una frase terminada con un punto (utilizado para señalar el final de la entrada). Lo que es habitual en este tipo de ejercicios, donde se suelen asumir entradas ideales.

Estos son algunos de los casos de prueba que utilicé, y las salidas que obtuve con mi código:

Código (cpp) [Seleccionar]
.
0

       .
0

,;.
0

,  ;    .
0

Hola.
1

Hola      .
1

        Hola   .
1

En un lugar de la Mancha, de cuyo nombre no quiero acordarme...
12

En    lugar             , de cuyo nombre no quiero          .
7

En un lugar.
3


Como se puede ver, cuando no existen palabras o cuando hay más de un espacio entre las palabras el cálculo es correcto.

No tomé en cuenta, intencionalmente, el conteo de números dentro de la frase, porque al2000 no lo planteó como parte del problema:

Código (cpp) [Seleccionar]
Ahora vienen 7 espacios:       , con estos otros suman 12:     .
7


En todo caso, no me parece que sea una solución incorrecta para un ejercicio de nivel básico.
PROGRAMMER
noun. [pro-gram-mer]
Someone who solves a problem
you didn't know you had, in a way
that you don't understand.

See also wizard, magician.

dijsktra

#4
Hola dresden, gracias por responder. Así aprenderé algo también.

Mi razonamiento al estudiar tu código, sin ejecutarlo, fue el siguiente :


  • creo (no estoy seguro), que scanf no procesa el espacio ' ' como carácter, por lo que nunca evaluará espacios en la cadena.. Suponiendo que si, entonces
  • o  bien isalpha(' ') es true, en cuyo caso existeLetra es true, y es evaluado por la parte positiva del primer condicional... En ese caso, la traza '    .' (5 espacios y un punto) da al menos 5 palabras, pues incrementa nPalabras 5 veces. Es esto correcto?
  • o bien isalpha(' ') es false,en cuyo caso  nunca es evaluado por la condición del if, nPalabras no se incrementa. 'hola'  daría 0 palabras.
  • ocurre que efectivamente, 'hola.' se incrementará en 1. Esto implica  que isalpha('.') es true.
Y según el manual

Citar


isalpha()
checks for an alphabetic character; in the standard "C" locale, it is equivalent to (isupper(c) || islower(c)). In some locales, there may be additional characters for which isalpha() is true-letters which are neither upper case nor lower case.

Es decir, que en el estándar C locale, sería false. Debe ser que tu computador esté configurado a sp (Spanish) y acierta arbitrariamente, marcando isalpha(' ') false y isalpha('.') true  , pero con otra configuración, no está garantizado





Cita de: Dresden en 24 Octubre 2018, 06:57 AM
... Lo que es habitual en este tipo de ejercicios, donde se suelen asumir entradas ideales.
En mi opinión, las frases "ideales" deben acabar en C,  en un carácter nulo, y no deben incluir símbolos como Comas, acentos y "puntos y Comas". La única razón es ajustarse a la esencia del Problema, que deja de ser portable en otros "locales".... Pero esto es opinable...

En lo que respecta a los casos que mandas, el segundo me llama la atención, puesto que según lo anterior '    .' (5 espacios y un blanco) debería dar 1, y te da 0, que es lo correcto.

Es realmente la salida de tu código?
No Le veo la explicación, pero puede que esté equivocado.
Debería verse




Total palabras: 0


Un saludo, amigo... A ver si me sacas de dudas...
Estoy solo con un móvil y no puedo probar tus códigos.
Cita de: Dresden en 24 Octubre 2018, 06:57 AM

Estos son algunos de los casos de prueba que utilicé, y las salidas que obtuve con mi código:



Código (cpp) [Seleccionar]
.
0

      .
0

,;.
0

,  ;    .
0

Hola.
1

Hola      .
1

       Hola   .
1

En un lugar de la Mancha, de cuyo nombre no quiero acordarme...
12

En    lugar             , de cuyo nombre no quiero          .
7

En un lugar.
3


Como se puede ver, cuando no existen palabras o cuando hay más de un espacio entre las palabras el cálculo es correcto.

No tomé en cuenta, intencionalmente, el conteo de números dentro de la frase, porque al2000 no lo planteó como parte del problema:

Código (cpp) [Seleccionar]
Ahora vienen 7 espacios:       , con estos otros suman 12:     .
7


En todo caso, no me parece que sea una solución incorrecta para un ejercicio de nivel básico.
Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)

dijsktra

Cita de: Dresden en 24 Octubre 2018, 06:57 AM
Estos son algunos de los casos de prueba que utilicé, y las salidas que obtuve con mi código:


....

En todo caso, no me parece que sea una solución incorrecta para un ejercicio de nivel básico.

Mis excusas. He probado ya tus códigos y son como dices. Aunque la estrategia de "existeLetra" como flag de comienzo no la entendía.
Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)