PROBLEMA INICIADO EN C

JoKeR

Buenas ! Quisiera exponeros un problema que tengo leyendo archivos en C:
Por parametro me pasan ./practica nombrefichero N

Tal que nombrefichero por ejemplo es practica.txt y N el numero de caracteres que ira cogiendo cada vez que leo.

Despues de comprobar que el numero de parametros es correcto, paso a llamar N=argv[2];

Ahora hago FILE*fich; fich=openfich(argv[1]); para abrir el fichero que nos pasan por parametro.

Llevo horas intentando sacar mirando webs como hacer ahora para ir leyendo del fichero pero no me entero:

quiero que, al ir leyuendo la cadena del fichero (por ejemplo el fichero puede llevar dentro: ola ola ola ola ola foreros de media vida), esta vaya quedando almacenada en un char del siguiente modo:
Si N=1, la cadena ira cogiendo de 1 en 1
si N=2, la cadena ira cogiendo de 2 en 2

Se que es una tonteria pero no me sale ... Muchas gracias foreros !

JoKeR

Esto fue lo que probe, pero no me va.

while ( fread(&car,N,N,fich)!=0){
printf("%d",car);}

si hago:

FILE *fich;
fich=openfich(argv[1]);
while(!feof(fich))
{
fread(&car,1,10,fich);
printf("%d",car);
}
}

me sale un 152 en el terminal del ubuntu, no se por que :(

JoKeR

Esto es lo que hago:

////////////////////////////////////////////Funciones////////////////////////////////////////////////////////////
FILE *openfich(char str[])
{
FILE *fichero=NULL;
if((fichero=fopen(str,"rb"))==NULL)
{
fprintf(stderr,"imposible abrir el fichero\n");
exit(1);
}
return fichero;
}

///////////////////////////////////////////función main//////////////////////////////////////////////////////////////////

int main(int argc,char *argv[])
{
int N,i;
unsigned char caracter[10];

if (argc!=3)
{
fprintf(stderr,"Parametros insuficientes\n");
exit(1);
}

//Veamos el valor del segundo parametro: N
N=argv[2];
printf(" El valor de N es: %s \n",N);

//abrimos fichero para la lectura del mismo
FILE *fich;
fich=openfich(argv[1]);
while(!feof(fich))
{
fread(&caracter,1,10,fich);
printf("%s",caracter);
}
}

Y esto lo que me sale por pantalla:

clarinetgcc -w -lm practica1.c -o practica1
clarinete:> ./practica1 fichero 2
El valor de N es: 2
�뚿��clarinete:>

gracias!

elkaoD

De lo poco que he podido entender del post, lo de N lo tienes mal. Sería:

N=atoi(argv[2]);

Aunque luego N no lo usas en ningún lado :s

¿No te interesaría quizá usar fgets?

JoKeR

es que estoy empezando. Estoy mirandome el libro de Como programar C/c++ y es lo que voy sacando

Mi intencion con este ejercicio no es mas que pillar un fichero e ir leyendo hasta acabarlo, desde el 1er caracter hasta el EOFile segun me indique N, e ir metiendolo en una cadena de caracteres para luego imprimirla (son las pruebas que estoy haciendo para aprender a usarlo)

es decir. Si en el fichero tengo " ESTOY PRACTICANDO C"
Si N=1: tengo que ir cogiendo primeor la E,la S,la T... y metiendola de una en una en el string.
Si N=2: Cojo ES , luego TO, luego Y' ', luego PR....
si N=3: Cojo EST,luego OY' ', luego PRA...

y las voy metiendo en la cadena y mientras lo va haciendo, me va sacando por pantalla la propia cadena.¿entiendes?

lo de N lo quiero usar aqui: fread(&car,1,10,fich); --> pero para ir leyendo de N en N, pero no entiendo bien lo que hace el fread(mas bien no entiendo lo que hacen los parametros). Querria leer y meter en CAR, desde 1 hasta el fin del fichero, los caracteres que vaya leyendo de N en N.

Gracias por contestar

elkaoD

http://pastebin.com/f3c8ace9

Párate a entender el código.

JoKeR

Bueno, he leido y he probado en mi ejemplo practico lo que tu me has dicho, pero me han surgido unos problemas.
Por ejemplo, si yo uso ATOI al hacer el argv[2], al compilar me da "Error de segmentacion". No se que es eso, pues en el EMACS de linux cuando programaba en PASCAL nunca me aparecio un error asi.De todos modos, si no uso ATOI, parece que me funciona el parametro, pue s si envio al ejecutar ./practica fichero 2, al sacar por pantalla el segundo argumento, es decir, el 2, me lo saca sin problemas.

El verdadero problema viene con el for. Expongo ahora las dos pruebas que hice, ambas con identico resultado.

1- Tengo un fichero.txt que sera el que uso para ejecutar, que dentro contiene un string que dice: HOLA ME LLAMO JORGE
2- aqui pongo mi programilla y como leo el fichero de las dos maneras que probe:


#include <unistd.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//Puntero a comprobacion fichero//

FILE *abrefichero(char nombre[])
{
FILE *fichero=NULL;
if ((fichero=fopen(nombre,"r"))==NULL)
{
fprintf(stderr,"Imposible abrir el fichero\n");
exit(1);
}
return fichero;
}

///////////////////////////////////////////función main/////////////////////////////////////////

int main(int argc,char *argv[])
{
FILE *fich;
int N,cont;
short cadena[256];

if (argc!=3)
{
fprintf(stderr,"Parametros insuficientes\n");
exit(1);
}


//Veamos el valor del segundo parametro: N //
N=(argv[2]);
printf("El valor del parametro N es:%s\n",N);


//Asignamos el valor del parametro 1 al fichero y procedemos a comprobar su existencia//


fich=abrefichero(argv[1]);
for(cont=0;cont<10;cont++)
{
fscanf(fich,"%s",&cadena);
printf("%s",cadena);
}

}

Ahora, el fichero, en vez de con un for, lo recorrere como en el ejemplo que me pasaste:

char * buffer;
//Asignamos el valor del parametro 1 al fichero y procedemos a comprobar su existencia//


fich=abrefichero(argv[1]);
while(!feof(fich))
{
fread(buffer,N,1,fich);
print("%s\n",buffer);
}

}

En ambos programas, lee el fichero.txt que le mande, pero al sacarlo por pantalla saldria:
HOLA,MELLAMOJORGEJORGEJORGEJORGEJORGEJORGE

Es decir, se come los espacios y me repite jorge 5 o 6 veces.¿Sabrias decirme por que?

Por cierto, el fread(buffer,N,1,fich); almacena el cotenido del fichero en buffer, vale. Pero,¿Que sifnican la N y el 1? de N en N a partir de la posicion 1?

Muchas gracias por tu ayuda, es mi segundo dia aprendiendo C y espero avanzar rapido. Yo creo que una vez entienda esto ya podre seguir solo. Resulta bastante intuitivo. Algo menos que pascal, pero no parece complicadisimo.

elkaoD

Lo de que te de error de segmentación con lo del atoi, no te lo da por el atoi sino porque luego haces un printf("El valor del parametro N es:%s\n",N); y al hacer el atoi, N es un entero y tú lo intentas imprimir como cadena (Tienes que cambiar el %s por un %d.) No es bueno guardar N como una cadena, es mejor guardarlo como entero para poder usarlo luego.

"Fallo de segmentación" es algo así como, "Wops, algo chungo ha pasado con la memoria". En ese caso al intentar leer un entero como si fuera una cadena, toma el valor del entero que ha sacado con atoi (Es decir, lo que valga N) y lo toma como un puntero. Si N vale 3, el puntero apunta a 0x00000003. Acceder a la dirección de memoria de 0x00000003, que el sistema operativa no te deja leer, por lo que da fallo de segmentación.

Por otro lado, de esos includes te sobran la mitad porque no los vas a usar.

"Por cierto, el fread(buffer,N,1,fich); almacena el cotenido del fichero en buffer, vale. Pero,¿Que sifnican la N y el 1? de N en N a partir de la posicion 1?"
No, significa de 1 en 1, con tamaño N. (Es decir, coge un elemento de tamaño N.)

A ver, ahora a lo del for, te comento los fallos de los dos códigos.

PRIMER CODIGO
En el del fscanf en primer el error que cometes es que defines cadena como short, cuando deberías definirlo como char. En segundo lugar el for está mal completamente.

for(cont=0;cont<10;cont++)

El código se va a ejecutar 10 veces.

fscanf(fich,"%s",&cadena);

Lee desde el fichero 'fich' hacia el string del puntero 'cadena', desde el fichero con un formato "%s", lo que nos devuelve la primera palabra del fichero, es decir, "HOLA,". Sigue el bucle y siguiente palabra "ME", siguiente palabra "LLAMO" y luego "JORGE". Obviamente todas ellas las imprime sin espacios. Hemos llegado al final del fichero pero sin embargo sigue ejecutandose el bucle así que lo único que hace es imprimir la última palabra que se guardó en el buffer.

Solución: No uses fscanf para esto

SEGUNDO CODIGO
Ahora, en el del fread, creo que tienes dos fallos.

En primer lugar, defines char * buffer, pero no reservas memoria para el buffer como yo hago con malloc(), por lo que no sé dónde te apuntará el puntero. En segundo lugar, según me has dicho antes no has guardado N como int sino como cadena (Al no hacer el atoi) así que el argumento de fread va a valer algo chungo. ¿Pascal no tiene tipos?

Espero haber sido de ayuda :)

JoKeR

ok,probare todas estas cosas. Pascal si tiene tipos, pero intuitivamente tiendo a identificar cosas dando por hecho que son similares en pascal y c, como por ejemplo el for, que en pascal haces for x:=1 to N, por eso cometia el error en el for de c. Muchas gracias por la ayuda

JoKeR

ya he solucionado lo de los espacios. Muchas gracias, ahora me queda mas claro. un saludo !

elkaoD

#10, cómo lo has solucionado?

Había varias formas, por ejemplo una era cambiando el printf ("%s", cadena) por printf ("%s ", cadena). La otra usar alguna función que lea byte a byte y la otra el método que usé yo.

JoKeR

He hecho lo siguiente:
buffer=(char*) malloc(N+1);
fich=abrefichero(argv[1]);
while(!feof(fich))
{
fread(buffer,N,1,fich);
print("%s",buffer)
}

y al ejecutar me ha salido :P

Ahora estoy probando a ver los caracteres, pero no con buffer.

defini un puntero: introduce();

int cont;
char car;
cont=0;
y estoy probando algo un poco mas dificil(poquito a poco :P) con ese bucle while que me pasaste en el ejemplo del link.

while (!feof(fich))
{
fread(&car,1,1,fich); ---> me obliga a poner ; no se pq pero lo ire averiguando
{
cont=cont+1;
}
printf("%d",cont);
}

y parece que va funcionando salvo que me pone siempre dos caracteres de mas. Es decir, si escribo: hola, contador me devuelve un 6, como si empezase a contar antes de leer i contase una despues o algo asi.

elkaoD

¿Y no has puesto el caracter de fin de linea?

¿Qué compilador usas?

Y no se te olvide hacer el "free".

JoKeR

Uso un compilador que me instalo mi compañero de piso para el ubuntu, no se cual es por que me dejo mi novia el portatil y se lo instalo a ella y no le pregunte. Tampoco se mirarlo. Yo abro con el emacs "emacs proyecto.c &" y ya luego compilo desde el terminal.
No se que es eso de hacer el free xD es mi segundo dia programando en c aun !

PD: el mensaje anterior lo he editado

elkaoD

Hay que poner al final free (buffer); para liberar la memoria del buffer.

Por cierto, para poner código mejor pon [ code ]código[ /code ] (Sin espacios) porque si no se ve como el culo.

No entiendo qué quieres hacer con esto:

while (!feof(fich))
{
 fread(&car,1,1,fich); // Te obliga a poner ; porque se pone al final de todas las instrucciones
 { // Para qué es este "{" ?
  cont=cont+1;
 }
 printf("%d",cont);
}

¿Quieres contar cuántos caracteres tiene esto? Sería así:

while (!feof(fich))
{
 fread(&car,1,1,fich); // Te obliga a poner ; porque se pone al final de todas las instrucciones
 cont++; // O cont += 1; o como tenías tú puesto cont = cont+1;
 printf("%d\n",cont);
}

Como usas Linux seguramente uses gcc.

JoKeR

Claro, abri un begin solo para una instruccion(algo poco eficiente), no me habia dado cuenta :D
Por eso me lo preguntaba, por que estaba pensando en un bucle dentro del read :)

lo de cont++ no lo habia probado, ahora mismo iba a probar si se podia hacer inc(cont); pero ya veo como se hace, con cont++

muchas thanks :)

De todos modos, donde debo poner el free? Sabes por que me cuenta dos numeros de mas?

elkaoD

"Claro, abri un begin solo para una instruccion(algo poco eficiente), no me habia dado cuenta
Por eso me lo preguntaba, por que estaba pensando en un bucle dentro del read"

Eso en C no se puede hacer, simplemente xD

"De todos modos, donde debo poner el free?"
Al final del todo, antes del return (O el exit, según lo que uses)

"Sabes por que me cuenta dos numeros de mas?"
Sube el código entero a Pastebin y te lo miro, porque poniendo lo que yo he puesto exactamente, debería contar bien. De todas formas puede ser que cuente mal porque esté leyéndote también algún caracter de fin de linea o algo de eso, ya que lo has puesto el fichero de abrir como binario.

JoKeR

http://pastebin.com/m3e64055c

Esta aqui, yo pongo un fichero que se llama fichero.txt por ejemplo y que contenga la palabra: HOLA.
al hacer ./ejemplo fichero.txt 2(este es el numero de parametros que probare mas adelante para guardar de 2 en 2 letras i escribir de 2 en 2 letras) y me devuelve un 6 el contador en vez de un 4. ,muchas thanks

elkaoD

El free ponlo sólo si has hecho malloc como free(buffer); (O la que sea la variable para la que has reservado memoria.) Vamos, que en el código ese no hace falta. De hecho, que raro que te compile.

Solucionado:

  fich=abrefichero(argv[1]);
  fread(&car,1,1,fich);
  
while(!feof(fich)) { cont=cont+1; printf ("%c\n", car); fread(&car,1,1,fich); }

Hay que hacer esto para que el feof se active cuando toca. Si llegas al ultimo caracter, no salta el feof hasta que llegas al caracter que está despues del último caracter (Es decir, que no existe.)

JoKeR

ok, luego lo miro q tengo q ir a la uni q tengo clase. muchas thanks

Usuarios habituales

  • JoKeR
  • elkaoD