perror
). Solamente usad llamadas
al sistema (no usar printf
ni fopen
)
en la parte principal de la práctica.
#define _HPUX_SOURCE #include <stdio.h> #include <unistd.h> #include <fcntl.h> int main(int argc, char *argv[]) { int fd,tam,i; char buffer[1024]; if(argc!=2) { fprintf(stderr,"Uso:%sFijaros sobre todo cuáles son los parámetros del\n", argv[0]); return 1; } fd=open(argv[1],O_RDWR); /* Bastaría con especificar O_RDONLY */ if(fd==-1) { perror("susti.c:open"); return 1; } /*Algoritmo de sustitucion*/ do { tam=read(fd,buffer,1024); if(tam==-1) { perror("susti.c:read"); return 1; } for (i=0;i<tam;i++) if(buffer[i]=='a') buffer[i]='o'; write(1,buffer,tam); /* Falta comprobar los errores del write */ } while(tam!=0); close(fd); return 0; }
read
y
del write
. Así sabréis también
cómo se sabe cuándo se ha alcanzado el final del fichero...
read
y el write
.
#define _HPUX_SOURCE #include <stdio.h> #include <unistd.h> #include <fcntl.h> int main(int argc,char *argv[]) { int fd; char caracter; if(argc != 2) { fprintf(stderr,"\n\nUso: %s <fichero>\n\n",argv[0]); return 1; } fd=open(argv[1],O_RDONLY); if(fd==-1) { perror("pract2-1: open"); return 2; } while(read(fd,&caracter,sizeof(char))!=0) { if(caracter=='a') write(1,"o",sizeof(char)); else write(1,&caracter,sizeof(char)); } close(fd); return 0; }Observad cómo en el primer
write
la o va entre
comillas dobles y no entre comillas simples. Esto es porque
write
espera un puntero en ese parámetro y
una cadena de caracteres es un puntero a caracteres.
read
para saber el final del fichero (0.1 puntos):
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
int tamano, fd, lectura, escritura;
char c;
char etiqueta[80];
if(argc!=2) {
fprintf(stderr,"\nHint: %s + path.\n",argv[0]);
return 1; }
fd=open(argv[1],O_RDONLY);
if(fd==-1) {
sprintf(etiqueta,"\nopen:%s",argv[1]);
perror(etiqueta);
return 1; }
/* Manera para saber la longitud de un fichero con lseek */
tamano=lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
while(tamano!=lseek(fd,0,SEEK_CUR)) {
lectura=read(fd,&c,1);
if(lectura==-1){
sprintf(etiqueta,"\nread:%s:error",argv[1]);
perror(etiqueta);
return 1; }
if(c=='a') c='o';
escritura=write(1,&c,1);
if(escritura==-1){
sprintf(etiqueta,"\nwrite:stdout:error");
perror(etiqueta);
return 1; }
}
if(close(fd)==-1){
sprintf(etiqueta,"\nclose:error");
perror(etiqueta);
return 1; }
return 0;
}
else
innecesario:
x=open(argv[1], O_RDONLY); if(read(x, buffer, 256)==-1) {perror(error); return 1;} else {for(i=0;i<256;i++) if(buffer[i]=='a') buffer[i]='o'; if(write(1, buffer, 256)==-1) [...]Lo corregimos y queda:
x=open(argv[1], O_RDONLY);
if(read(x, buffer, 256)==-1)
{perror(error);
return 1;}
for(i=0;i<256;i++)
if(buffer[i]=='a') buffer[i]='o';
if(write(1, buffer, 256)==-1)
[...]
Incluso corrigiéndolo, hay un error peor. Aparece en rojo. Es
el 256 que está como tercer parámetro del write
.
El valor devuelto de read
no se debe desperdiciar.
En él se nos va a indicar cuántos caracteres se han
leído realmente
el el búffer del total que hemos solicitado
como tercer parámetro.
Si estamos al final del fichero y quedan menos de 256 caracteres,
evidentemente se van a leer menos. Al leerse menos, se tendrán
que escribir justo los que se han leído.
Además, read
devuelve cero cuando no quedan más caracteres que leer del fichero.
Así es como detectamos el fin de fichero.
do { /* Lectura de una "trama" de fichero */ if ((n_bytes_r=read(desc_fich, buffer, TAM-1)) == -1) { /* Tratamiento del error. */ } buffer[n_bytes_r] = '\0'; /* Cambio de aes por oes */ [...] /* Presentación por pantalla de los cambios */ if ((n_bytes_w=write(1, buffer, strlen(buffer))) == -1) [...]Lo que hace este fragmento es leer en el búfer un trozo de fichero, añadir un
'\0'
al final y saber
lo que tenemos que escribir gracias a la función de biblioteca
strlen
. Esta función nos dice la longitud de
una cadena de caracteres que le pasamos como parámetro.
La longitud la obtiene contando caracteres hasta que encuentra
el carácter de fin de cadena ('\0'
). Pero,
¿qué ocurre si dentro del fichero ya hay un
carácter de fin de cadena?
if ((desc_fich=open(argv[1], O_RDONLY)) == -1) { /* Tratamiento de errores */ } /* CÁLCULO DE LA LONGITUD DEL FICHERO Y RESERVA DE MEMORIA */ if ((n_bytes=lseek(desc_fich, 0, SEEK_END)) == -1) { /* Tratamiento de errores */ } if ((buffer=(char *)calloc(n_bytes, sizeof(char))) == NULL) { /* Tratamiento de errores */ } /* LECTURA Y TRATAMIENTO DEL FICHERO */ if (lseek(desc_fich, 0, SEEK_SET) == -1) { /* Tratamiento de errores */ } if ((n_bytes_r=read(desc_fich, buffer, n_bytes)) == -1) { /* Tratamiento de errores */ } /* Cambio de aes por oes */ [...] /* Presentación por pantalla de los cambios */ if ((n_bytes_w=write(1, buffer, n_bytes_r)) == -1) { /* Tratamiento de errores */ }En este ejemplo, se reserva con memoria dinámica un búfer lo suficientemente grande para dar cabida a todo el fichero. Se trata el búfer, y se escribe su contenido. El problema de este esquema es que se están desperdiciando recursos (memoria virtual). Además, al reservar memoria para todo el fichero puede que, si el fichero es muy grande no haya memoria suficiente. No podremos tratar el fichero en ese caso. Al solo querer hacer acceso secuencial, nos basta tratar la información por partes con un búfer más pequeño.