Programa en C

Iniciado por Leafar77, 24 Octubre 2014, 19:34 PM

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

Leafar77

Hola a todos!

soy estudiante de ingeniería y estoy tratando de resolver un ejercicio. Un programa que muestre un histograma de las longitudes de las palabras de un texto
de entrada (usando la entrada estándar). Mi codigo es este:

#include <stdio.h>
#define IN 1
#define OUT 0


main()
{
   int c,i;
   int state;
   int index[10];
   int n_char = 0;
   int n_words = 0;
   state = OUT;
   
   
   
   for( i = 0; i < 10; ++i)
   {
      index = 0;
   }
   
   
   
   while( c = getchar() != EOF )
   {   if (state == IN)
      {
         n_char = n_char + 1;
         printf("%d\n", n_char);
      }
      if( c = ' ' || c == '\n' || c == '\t' )
      {
         state = OUT;
         index[n_char] = index[n_char] + 1;
      }
      else if ( state == OUT )
      {
         state = IN;
         ++n_words;
      }
      
   }
   printf("%d\n", index[0]);
   printf("%d\n", index[1]);
   printf("%d\n", index[2]);
   printf("%d\n", index[3]);
   printf("%d\n", index[4]);
   printf("%d\n", index[5]);
   printf("%d\n", index[6]);
   printf("%d\n", index[7]);
   printf("%d\n", index[8]);
   printf("%d\n", index[9]);
   
}

Al ejecutarlo, en lugar de guardar el número de palabras de X número de caracteres en cada posición del array, introduce el numero total de caracteres del texto siempre en la misma posicion del array. Que estoy haciendo mal?
Gracias de antemano!

ivancea96

#1
No me fijé más, pero pusiste en el for: "index = 0;" en vez de "index[ i ]=0", que supongo que es lo que querrías poner.

reich

hace mucho que no toco C pero aquí me parece ver una incongruencia:

if( c = ' ' || c == '\n' || c == '\t' )

en [c = ' ' ] se realiza una asignación , no una comparación. Puede que eso este creando problemas.


rir3760

Cita de: Leafar77 en 24 Octubre 2014, 19:34 PMsoy estudiante de ingeniería y estoy tratando de resolver un ejercicio. Un programa que muestre un histograma de las longitudes de las palabras de un texto de entrada (usando la entrada estándar). Mi codigo es este [...]
Por partes.

El programa que presentas es uno de los ejemplos del primer capitulo del libro "The C Programming Language", una versión sencilla del comando wc (abreviación de word count). En el los autores enseñan como detectar la transición fuera-->dentro, cuando esta sucede se incrementa el contador de palabras en una unidad.

Paginas mas adelante uno de los ejercicios a resolver es el que comentas: imprimir las frecuencias de las palabras obtenidas de la entrada estándar. Para esto se debe detectar la transición opuesta (dentro-->fuera) y cuando esto suceda incrementar el contador de frecuencia correspondiente.

El primer error importante ya te lo indico reich: utilizar el operador de asignación "=" cuando deberías utilizar el de comparación "==". Otros son no colocar a cero el contador de longitud cuando se sale de una palabra y la falta de los paréntesis en la expresión que controla al bucle:
while (c = getchar() != EOF) ...
Hay que cambiarla a:
while ((c = getchar()) != EOF) ...

Otros mas son imprimir el primer elemento del array cuando este no se utiliza y no tomar previsiones en caso de una palabra de mas de diez caracteres (lo cual llevaría a utilizar un indice invalido al acceder al array).

Por ultimo no es necesario la bandera de estado, en su lugar se utiliza al contador de longitud para conocer este (cero es fuera de una palabra, mayor que cero es dentro). El bucle en pseudocódigo:
Asignar al contador de longitud el valor cero
Mientras se pueda leer un caracter
   Si el caracter NO es espacio blanco
      Incrementar el contador de longitud en una unidad
   Caso contrario: si el contador de longitud es mayor que cero
      Si el contador de longitud es mayor que el indice maximo del array
         Asignar al contador de longitud el indice maximo del array
     
      Incrementar el elemento del array de indice "contador de longitd" en una unidad
      Asignar al contador de longitud el valor cero


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Leafar77

Gracias por la explicación! Ha sido vital para resolver el problema!
Asi ha quedado finalmente:

#include <stdio.h>



main()
{
int c,i;
int index[20];
int n_char = 0;
int h,t;


/* Inicialización del array */

for( i = 0; i < 20; ++i)
{
index[i]=0;
}

/* Contador de longitud */

while ((c = getchar()) != EOF)
{ if ( c != ' ' && c != '\n' && c != '\t' )
{
++n_char;
}
else if ( n_char > 0 )
{
index[n_char]++;
n_char = 0;
}

}

/* Impresión del histograma */

for(t = 1; t < 20; ++t)
{
printf("%4d Caracteres: ", t);
for(h = 0; h < index[t]; ++h)
{
printf("=");
}
printf("\n");
}

}

rir3760

El programa funcionara correctamente siempre y cuando ninguna palabra tenga una longitud mayor a 19 caracteres pero, si existe una, el programa puede terminar reventando.

Para evitarlo dentro del bucle debes verificar el valor del contador "n_char", si este tiene un valor mayor al permitido le asignas el máximo, de esta forma:
while ((c = getchar()) != EOF)
   if (c != ' ' && c != '\n' && c != '\t')
      ++n_char;
   else if (n_char > 0){
      if (n_char > 19)
         n_char = 19;

      index[n_char]++;
      n_char = 0;
   }


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language