Hola buenas, quiero saber la posición del cur de un archivo de texto a medida que leo caracteres con la función fscanf. Entonces, implemente lo siguiente ,en términos generales:
char c;
while(!feof(fichero)){
fscanf(fichero," %c",&c);
printf("%c",c);
printf("(%ld) ", ftell(fichero));
}
En el archivo contiene los siguiente:
---------------------------------------------------------------------
supholasadkjholasad
adholadsa
---------------------------------------------------------------------
En el terminal se imprime:
---------------------------------------------------------------------
s(1) u(2) p(3) h(4) o(5) l(6) a(7) s(8) a(9) d(10) k(11) j(12) h(13) o(14) l(15) a(16) s(17) a(18) d(19) a(21) d(22) h(23) o(24) l(25) a(26) d(27) s(28) a(29) a(29)
---------------------------------------------------------------------
Mis preguntas son:
¿Por qué el carácter '\n' no lo imprime cuando lo lee?
El número 20 se lo salta al terminar de leer la primera línea, ¿Por qué?
fscanf lee '\n' ? '\n' es un char, cierto?
Espero sus respuestas :D
Antes de nada quiero que sepas que mi teoría esta basada en mi mis conocimientos y puede ser erronea la explicación que te voy a dar.
He estado mirando en la documentación y no he encontrado respuesta, solo puedo comentarte que si quieres trabajar mejor con el fichero crees un puntero a los datos y no los vayas leyendo poco a poco. Puede que las funciones que estás usando para leer el archivo caracter a caracter supriman los saltos de línea.
Por otra parte quiero que sepas que '\n' no es un solo caracter... No te lo explico, te lo muestro :P
#include <stdio.h>
int main()
{
char JmpLine[2] = {0};
JmpLine[0] = 10;
JmpLine[1] = 13;
JmpLine[2] = 0;
printf("Una linea %s Otra linea",JmpLine);
return 0;
}
saludos y espero resolver tu duda.
saludos.
Cita de: Apazche en 27 Diciembre 2017, 00:39 AM
Mis preguntas son:
¿Por qué el carácter '\n' no lo imprime cuando lo lee?
El número 20 se lo salta al terminar de leer la primera línea, ¿Por qué?
fscanf lee '\n' ? '\n' es un char, cierto?
Espero sus respuestas :D
Como dices, "\n" es un carácter, pero la directiva de matching "%c", según el manual, salta todos los caracteres "white-space", (entendiendo estos como el spacio, el tablador, el fin de línea... todos los que responden a
isspace(int c) ).
Si te fijas en la salida , salta del 19 al 21...
Otra aspecto tiene que ver con
printf. Propimaente hablando, el caracter '\n' no es carácter imprimible, segun (
isprint(c)) , sino de control
iscntrl(c). En el caso de "\n" dicen que "debe" hacer un
scrolling de 1 y empezar en la primera columna, no que imprima propiamente un caracter...
Una solución pasa por dejar usar las rutinas "high-level IO", los streams, a las de "low-level IO", los "file descriptors".
El incoveniente es que perdemos la funcionalidad de la rutina
long ftell(FILE *stream)
pero que podemos simular con
pos=lseek(fd,0,SEEK_CUR)
Por supuesto, para dar una salida formateada, debo volver a las rutinas "high-level" IO, como
printf... Pero es un problema aparte de el de lectura
readHay otro error, que ya muestro corregido, relatio a la función
feof()... Esta función sólo tiene valores coherentes
después de haber invocado la correspondiente
fscanf, es decir, no puede anticipar si la cabeza lectora ha llegafo a fin de fichero..
Ahí va mi propuesta.
#include <stdlib.h> // exit()...
#include <assert.h> // assert
#include <unistd.h> // open,read,close (Low-level IO),
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> // open,O_RDONLY...
#include <stdio.h> //p printf
#include <ctype.h> // isprint
int main()
{
char c;
int n;
int fd;
const char *pattern="%d\t%c\t%d\n";
char row[80];
if (!(fd=open("texto.txt",O_RDONLY)))
{
perror("open");
exit(EXIT_FAILURE);
}
printf("ASCII\tPrint\tPos\n");
while((n=read(fd,&c,sizeof(char)))> 0)
{
assert(isascii(c));
if ((n=sprintf(row,pattern,c,isprint(c)?c:' ',lseek(fd,0,SEEK_CUR)))<0)
{
perror("sprintf");
exit(EXIT_FAILURE);
}
printf(row);
}
if (n==-1)
{
perror("read");
exit(EXIT_FAILURE);
}
close(fd);
exit(EXIT_SUCCESS);
}
Pasándole el fichero de texto propuesto
supholasadkjholasad
adholadsa
El programa arroja la salida siguiente: Cuando es imprimible, imprime su símbolo, cuando es de control, en su lugar, un espacio. (Los números que salen al principio los pone el codgo GeSHi del web, porque si no, perdía el formato de salida... un lío vamos)
ASCII Print Pos
115 s 1
117 u 2
112 p 3
104 h 4
111 o 5
108 l 6
97 a 7
115 s 8
97 a 9
100 d 10
107 k 11
106 j 12
104 h 13
111 o 14
108 l 15
97 a 16
115 s 17
97 a 18
100 d 19
10 20
97 a 21
100 d 22
104 h 23
111 o 24
108 l 25
97 a 26
100 d 27
115 s 28
97 a 29
10 30
Cita de: dijsktra en 23 Abril 2018, 01:14 AM
Una solución pasa por dejar usar las rutinas "high-level IO", los streams, a las de "low-level IO", los "file descriptors".
El incoveniente es que perdemos la funcionalidad de la rutina
long ftell(FILE *stream)
Esto no es así necesariamente. Me corrijo a mí mismo. En high-level contamos con
int fgetc(FILE *stream);
que, sin buscar patrones como
scanf, hace lo que queremos, conservando el
ftellEl erroes es que en vez de scanf , la rutina qie había que haber utilizado era
fgetcEl nuevo programa, más sencillo queda:
#include <stdlib.h> // exit()...
#include <assert.h> // assert
#include <stdio.h> //p printf
#include <ctype.h> // isprint
int main()
{
char c;
int n;
FILE* fs;
const char *pattern="%d\t%c\t%d\n";
char row[80];
if (!(fs=fopen("texto.txt","r")))
{
perror("fopen");
exit(EXIT_FAILURE);
}
printf("ASCII\tPrint\tPos\n");
while((c=fgetc(fs))!=EOF)
{
assert(isascii(c));
if ((n=sprintf(row,pattern,c,isprint(c)?c:' ',ftell(fs)))<0)
{
perror("sprintf");
exit(EXIT_FAILURE);
}
printf(row);
}
if (c!=EOF)
{
perror("fgetc");
exit(EXIT_FAILURE);
}
fclose(fs);
exit(EXIT_SUCCESS);
}
Y la salida, como en el caso anterior, leyendo "texto.txt", queda
ASCII Print Pos
115 s 1
117 u 2
112 p 3
104 h 4
111 o 5
108 l 6
97 a 7
115 s 8
97 a 9
100 d 10
107 k 11
106 j 12
104 h 13
111 o 14
108 l 15
97 a 16
115 s 17
97 a 18
100 d 19
10 20
97 a 21
100 d 22
104 h 23
111 o 24
108 l 25
97 a 26
100 d 27
115 s 28
97 a 29
10 30