Dudilla con programa simple que lee ficheros (En C )

Hola, a ver si podeis hecharme una mano con un programita que me viene comiendo el tarro toda la tarde por que no consigo que funcione.

/*Escribe una funcion que reciba dos nombres de fichero, uno para entrada de datos y otro para salida. El
fichero de entrada tiene el formato: numero palabras palabra palabra . . . palabra, suponiendo que hay un
solo espacio entre palabras y que no hay espacios extra al final de la linea. Por ejemplo:

5 hola mundo de la gente
3 con inquietudes manifiestas
2 y alianzas
5 mas alla de la virtud

La funcion debera comprobar si el numero de palabras indicado al inicio de la linea coincide con el numero
real de palabras. Si es asi, en el fichero de salida escribiria \OK" para dicha linea y en caso contrario
\ERROR".*/

#include  <stdio.h>
#include <string.h>
int fich(char *rin, char *rout){
int n=0,a=0,b=1;
char s,g,r;
FILE *in,*out;
in=fopen(rin,"r");
if(in==NULL)
return (-1);
out=fopen(rout,"w");
if(out==NULL)
return (-1);

while(fscanf(in,"%s",&g)!= EOF){
   while (fscanf(in,"%s",&s) !='\0'){
      if (fscanf(in,"%c",&r)==' '){
      n++;}}
   fscanf(in,"%d",&a);
   
   if (n==a)
      fprintf(out,"Linia %d Ok\n",b);
   else
      fprintf(out,"Linia %d Error\n",b);
      b++;
   }   
   fclose(in);
   fclose(out);
   }

int main(){
int e=0;
char rin[256],rout[265];
gets(rin);
gets(rout);

e=fich(rin,rout);
if(e==-1)
printf("las cagao\n");
return 0;
}

Compila bien, dando solo 1 aviso chorra, decir que lo ejecuto en la misma carpeta en la que tengo unos archivos "in.txt" y "out.txt" que indico con el gets nada mas iniciar la funcion main y el programa no muestra nada y no se termina, supongo que se queda en un bucle infinito en el while, pero como aun no tengo mucha practica trabajando con ficheros y cadenas aun no se por que, a ver si alguien me puede orientar.
Muchas gracias por adelantado =)
Que yo recuerde, fscanf no devuelve el carácter leído sino el número de datos asignados.
while(fscanf(in,"%s",&g)!= EOF)


fscanf no devuelve el caracter leido, sino los bytes leidos. Otro error es lo que lees. %s indica la lectura de una cadena, pero luego pasas &g. Si lees un caracter, haz %c.

Si quieres que te devuelva el caracter, usa fgetc.

Salu2!
He cambiado ese fscanf por getc (no me sale como fgetc en los apuntes, pero sigue sin acabar el bucle.)

/*Escribe una funcion que reciba dos nombres de fichero, uno para entrada de datos y otro para salida. El
fichero de entrada tiene el formato: numero palabras palabra palabra . . . palabra, suponiendo que hay un
solo espacio entre palabras y que no hay espacios extra al final de la linea. Por ejemplo:

5 hola mundo de la gente
3 con inquietudes manifiestas
2 y alianzas
5 mas alla de la virtud

La funcion debera comprobar si el numero de palabras indicado al inicio de la linea coincide con el numero
real de palabras. Si es asi, en el fichero de salida escribiria \OK" para dicha linea y en caso contrario
\ERROR".*/

#include  <stdio.h>
#include <string.h>
int fich(char *rin, char *rout){
int n=0,a=0,b=1;
char s[50],g,r;
FILE *in,*out;
in=fopen(rin,"r");
if(in==NULL)
return (-1);
out=fopen(rout,"w");
if(out==NULL)
return (-1);

while (getc(in)!= EOF){
   while (getc(in) !='\0'){
      if (getc(in)==' '){
      n++;}}
   fscanf(in,"%d",&a);
   
   if (n==a)
      fprintf(out,"Linia %d Ok\n",b);
   else
      fprintf(out,"Linia %d Error\n",b);
      b++;
   }   
   fclose(in);
   fclose(out);
   return 0;
   }

int main(){
int e=0;
char rin[256],rout[265];
gets(rin);
gets(rout);

e=fich(rin,rout);
if(e==-1)
printf("las cagao\n");
return 0;
}





Observo que si elimino este bucle
while (getc(in) !='\0'){
      if (getc(in)==' '){
      n++;}}

el programa si que acaba asi que ahi se encuentra el error.
\-\adEs escribió:
while(fscanf(in,"%s",&g)!= EOF)


fscanf no devuelve el caracter leido, sino los bytes leidos. Otro error es lo que lees. %s indica la lectura de una cadena, pero luego pasas &g. Si lees un caracter, haz %c.

Si quieres que te devuelva el caracter, usa fgetc.

Salu2!


WTF Pero tu que haces escribiendo en EOL? xD
Me estoy volviendo loco, xD alguien me ayuda?
El salto de linia es '\0' no?
El_Harto escribió:Me estoy volviendo loco, xD alguien me ayuda?
El salto de linia es '\0' no?


No, seria '\n'
codestation escribió:
El_Harto escribió:Me estoy volviendo loco, xD alguien me ayuda?
El salto de linia es '\0' no?


No, seria '\n'

bueno quiero decir como final de una linia, creo que es asi, almenos asi lo pone en los apuntes. (He probado con \n y tampoco)
Fin de línea es '\n'
'\0' es el carácter que indica fin de cadena.
amuchamu escribió:Fin de línea es '\n'
'\0' es el carácter que indica fin de cadena.

Pero cuando estas leyendo un fichero si quiero que deje de hacer algo al final de la linia tengo que hacer ese while no?
while(getc(in)!='\0')

Leyendo el enunciado nadie podria decirme como es exactamente el bucle que tengo que poner?
Esto no son deberes ni nada obligatorio, lo hago por que quiero aprender y me interesa saber en que estoy fallando.
No, \0 es fin de cadena, salto de linea es \n
Korso10 escribió:No, \0 es fin de cadena, salto de linea es \n

Bueno igualmente, he puesto '\n' en el lugar del '\0' y sigue sin rular...
Nada incluso aunque ponga
while (getc(in) !=' '){
      if (getc(in)==' '){
         n++;}
      }

no acaba nunca, joder que pasa con ese bucle >< si lo quito el bucle del EOF funciona y sale algo en out.txt y todo, esta ahi el fallo, tiene que ser una chorrada, pero no la veo.


EDIT: Manda cojones solo con este cambio
while (getc(in) !='\n'){
      if (getc(in)==' ')
         n++;
      }

Ya funciona, bueno me devuelve
Linia 1 Ok
Linia 2 Error
Linia 3 Error
Linia 4 Error

que es erroneo, pero almenos devuelve algo.
como dijo amuchamu, en este caso debes usar \n ya que buscas el fin de la linea. Además el problema no es el bucle en si, sino la implementación del codigo. No estas tomando el valor que hay al principio de cada linea para hacer la comprobacion, de la forma que estas usando los getc estas perdiendo la comprobacion de muchos caracteres, no estas reinicializando el contador de palabras "n" cuando vas a una nueva linea, etc, etc.

Toma un depurardor y ve ejecutando el codigo linea a linea, te daras cuenta facilmente donde esta fallando tu codigo.
Bueno por ahora el codigo me queda asi
/*Escribe una funcion que reciba dos nombres de fichero, uno para entrada de datos y otro para salida. El
fichero de entrada tiene el formato: numero palabras palabra palabra . . . palabra, suponiendo que hay un
solo espacio entre palabras y que no hay espacios extra al final de la linea. Por ejemplo:

5 hola mundo de la gente
3 con inquietudes manifiestas
2 y alianzas
5 mas alla de la virtud

La funcion debera comprobar si el numero de palabras indicado al inicio de la linea coincide con el numero
real de palabras. Si es asi, en el fichero de salida escribiria \OK" para dicha linea y en caso contrario
\ERROR".*/

#include  <stdio.h>
#include <string.h>
int fich(char *rin, char *rout){
int n=0,a=0,b=1;
FILE *in,*out;
in=fopen(rin,"r");
if(in==NULL)
return (-1);
out=fopen(rout,"w");
if(out==NULL)
return (-1);
while (getc(in)!= EOF){
   n=0;
   while (getc(in) !='\n'){
      if (getc(in)==' ')
         n++;
      }
      a=0;
   fscanf(in,"%d",&a);
   
   if (n==a)
      fprintf(out,"Linia %d Ok\n",b);
   else
      fprintf(out,"Linia %d Error\n",b);
      b++;
   }   
   fclose(in);
   fclose(out);
   return 0;
   }

int main(){
int e=0;
char rin[256],rout[265];
gets(rin);
gets(rout);

e=fich(rin,rout);
if(e==-1)
printf("las cagao\n");
return 0;
}




Y me devuelve que las 2 primeras linias son correctas y las otras falsas (en realidad son todas correctas)
Ahora cenare y luego seguire mirando.
Podrias decirme por que me estoy perdiendo la comprobacionde muchos caracteres?
Y habia pensado usar el depurador, pero no lo tengo muy visto y no se como sera con ficheros, ahora despues le hecho un ojo.

Muchas gracias por vuestra paciencia y consejos =D.
El_Harto escribió:No, seria '\n'

bueno quiero decir como final de una linia, creo que es asi, almenos asi lo pone en los apuntes. (He probado con \n y tampoco)[/quote]

No te lies. Una cosa es salto de linea (\n) y otro final de cadena (\0). Solo el salto de linea es imprimible.

El_Harto escribió:EDIT: Manda cojones solo con este cambio
while (getc(in) !='\n'){
      if (getc(in)==' ')
         n++;
      }



Dudo que con eso te funcione. Si te funciona, es pura casualidad por que solo comprueba uno de cada dos caracteres. Para que eso funcionase tendria que ser algo como:

char aux = 'a'; /* El establecer la variable a "algo" es para no arriesgarnos a que pueda valer alguna vez EOF */
while(aux != EOF){
aux = getc(in);
if(aux == '\n')
n++;
}

El fallo que tienes esque, por cada comprobacion, desplazas el cabezal del fichero dos posiciones (llamas 2 veces por bucle a getc, en el propio while y en el if).

Pokemon escribió:WTF Pero tu que haces escribiendo en EOL? xD


Spammear un rato, que no me apetece ponerme con lo de Ingenieria del Software xD

Salu2!
La función fscanf retorna el número de datos de entrada asignados, que puede ser menor que ofrecido, incluso cero, en el caso de un error de asignación. Si un error de entrada ocurre antes de cualquier conversión, la función fscanf retorna el valor de la macro EOF.

Creo recordar, es que ahora mismo no tengo compilador, que fscanf lee cadenas de caracteres hasta un espacio. Por lo tanto si hicieras algo asi:

fscnaf(in,%c,&c); en c tendrias el primer valor de la linea usease el numero que te dice cuantas palabras tiene que tener la linea.
Después solo tendrías que hacer un while para contar el número de palabras.
Muchas gracias por todo, el programa va mal (el out devuelve 1 entrada por cada caracter en lugar de por cada linia y no termina de ser correcto), seguire dandole yo a ver que sale.
Gracias otra vez por la ayuda =D
16 respuestas