Discussion:
identificar líneas en blanco dentro de un fichero
(demasiado antiguo para responder)
newsf
2004-04-27 09:33:20 UTC
Permalink
Buenas grupo,
estoy leyendo un fichero, y quiero que salte las líneas que estan en
blanco. He hecho un programa, pero no doy con el caracter necesario:

#include <stdio.h>
#include <string.h>
main ()
{
FILE *f_in;
char *leido;
if ((f_in = fopen ("borrar.txt", "r")) == NULL)
{
printf ("Error de apertura del fichero entrada.txt\n");
exit (1);
}
if((leido = (char *)malloc(10 * sizeof(char))) == NULL)
{
printf ("No hay mas memoria en el Heap");
exit(1);
}
do
{
fgets(leido,10,f_in);
if (leido != "\n") printf ("%s", leido);
}while (feof(f_in) == 0);
}

En el fichero borrar.txt está el siguiente contenido:
aa

bb
Quiere que la salida sea:
aa
bb
y me da la salida:
aa

bb

¿Alguién me puede decir como identificar es línea en blanco?. Si la línea en
blando fuese la última del fichero, ¿se identificará de la misma forma?.

Gracias,
Fernando
Antoine Leca
2004-04-27 10:50:07 UTC
Permalink
Post by newsf
do
{
fgets(leido,10,f_in);
if (leido != "\n") printf ("%s", leido);
La comparación de cadenas se hace con strcmp, no con == o !=
Post by newsf
}while (feof(f_in) == 0);
Tu has aprendido con Pascal, ¿verdad?

Bién, en C, las cosas son diferente. No tienes que controlar si un flujo
está acabado ó no, con una llamada a feof(). Más bién, tienes que controlar
que la operación de lectura, aquí el fgets(), no te devuelva NULL (ó 0,
según la función). Entonces, hay que escribir:

for(;;) /* manera C de escribir una bucla continua */ {
if( fgets(/*...*/) == NULL ) /* también se puede encontrar if( !
fgets(... */
break; /* no queda nada, salimos de la bucla */
if( /*...*/ ) printf(leido);
}


Antoine
Mikel Irazabal
2004-04-28 07:46:51 UTC
Permalink
Post by newsf
if (leido != "\n") printf ("%s", leido);
Con esto no buscas el caracter en la cadena leido.
Necesitas usar strstr()
Post by newsf
¿Alguién me puede decir como identificar es línea en blanco?. Si la línea en
blando fuese la última del fichero, ¿se identificará de la misma forma?.
Para buscar una línea en blanco necesitas buscar dos finales de línea
seguidos y eliminar el uno de ellos.

Los finales de línea en DOS/Windows son \r\n (ó \n\r no me acuerdo) y en
UNIX sólo \n.

¿Como quitarlos?

Chapuceramente y rápido: reemplaza el primer final de línea por espacio
(se alargará la línea anterior cada línea que elimines)

Más elegante y lento: desplazando todo lo que tienes por detrás hacia la
izquierda para quitar el final de línea.

Hasta otra,

Mikel
J.A. Gutierrez
2004-04-28 07:53:28 UTC
Permalink
newsf <***@grupalia.com> wrote:

: fgets(leido,10,f_in);
: if (leido != "\n") printf ("%s", leido);

if ( *leido != '\n' ) ...

: ¿Alguién me puede decir como identificar es línea en blanco?. Si la línea en

(eso vale para unix, en DOS/Windows, se deja como ejercicio.

: blando fuese la última del fichero, ¿se identificará de la misma forma?.

si
--
finger ***@shiva.cps.unizar.es for PGP /
.mailcap tip of the day: / La vida es una carcel
application/ms-tnef; cat '%s' > /dev/null / con las puertas abiertas
text/x-vcard; cat '%s' > /dev/null / (A. Calamaro)
Antoine Leca
2004-04-28 14:14:48 UTC
Permalink
En el texto borrado, habia
if ((f_in = fopen ("borrar.txt", "r")) == NULL)
Post by J.A. Gutierrez
: fgets(leido,10,f_in);
if ( *leido != '\n' ) ...
(eso vale para unix, en DOS/Windows, se deja como ejercicio.
Vale también para DOS, UNIX, MacOS (donde las fines de lineas son
fisicamente el carácter '\r'), AS/400 (donde las fines de lineas son
"indicadas" con la descripción del archivo, que dice cual es le tamaño de
las lineas), etc.

Es el proposito de las funciones de <stdio.h> de ocultar estas diferencias.
Si realmente quieres saber lo que hay en el archivo fisico, hay que obrir
con fopen(..., "rb"). Y sobre todo hacerlo también con *nix, así queda muy
claro la intención, y también seguirá funcionando con otra máquina.

Ya he acabado el ejercicio ;-).


Antoine
J.A. Gutierrez
2004-04-29 07:33:00 UTC
Permalink
Antoine Leca <***@localhost.gov> wrote:
: En c6nnto$cr1$***@news-4.escomposlinux.org, J.A. Gutierrez va escriure:
:> newsf <***@grupalia.com> wrote:

: En el texto borrado, habia
: if ((f_in = fopen ("borrar.txt", "r")) == NULL)

:> if ( *leido != '\n' ) ...
:>
:> (eso vale para unix, en DOS/Windows, se deja como ejercicio.

: Vale también para DOS, UNIX, MacOS (donde las fines de lineas son
: fisicamente el carácter '\r'), AS/400 (donde las fines de lineas son
: "indicadas" con la descripción del archivo, que dice cual es le tamaño de
: las lineas), etc.

hmmm
Pues no lo tengo yo tan claro. En algunos casos, puede que
por defecto sea asi, pero nadie te lo garantiza.

: Es el proposito de las funciones de <stdio.h> de ocultar estas diferencias.
: Si realmente quieres saber lo que hay en el archivo fisico, hay que obrir
: con fopen(..., "rb"). Y sobre todo hacerlo también con *nix, así queda muy
: claro la intención, y también seguirá funcionando con otra máquina.

Ejemplo: en gcc/cygwin sobre windows 2003 no funciona, hay
que abrir el fichero explicitamente en modo texto, usando
fopen (fname, "rt").

: Ya he acabado el ejercicio ;-).

insert coin and try again :-)
--
finger ***@shiva.cps.unizar.es for PGP /
.mailcap tip of the day: / La vida es una carcel
application/ms-tnef; cat '%s' > /dev/null / con las puertas abiertas
text/x-vcard; cat '%s' > /dev/null / (A. Calamaro)
Antoine Leca
2004-04-29 13:41:35 UTC
Permalink
Post by J.A. Gutierrez
Post by Antoine Leca
En el texto borrado, habia
if ((f_in = fopen ("borrar.txt", "r")) == NULL)
Post by J.A. Gutierrez
if ( *leido != '\n' ) ...
(eso vale para unix, en DOS/Windows, se deja como ejercicio.
Vale también para DOS, UNIX, MacOS [...]
hmmm
Pues no lo tengo yo tan claro. En algunos casos, puede que
por defecto sea asi, pero nadie te lo garantiza.
Con perdón: te lo garantiza la norma del lenguaje.

Ahora bién, siempre puedes escribir o utilizar compiladores que no complen
con la norma, o en modos que no complen.
Incluso hay algunos que tienen muy buenas razones para no complir (en modo
per defecto).
Post by J.A. Gutierrez
Ejemplo: en gcc/cygwin sobre windows 2003 no funciona, hay
que abrir el fichero explicitamente en modo texto, usando
fopen (fname, "rt").
Raro. Muy raro, de verdad.
He mirado a la FAQ de Cygwin, y la ultima versión en linea
(http://cygwin.com/faq/faq_4.html#SEC75) está claramente diciendo lo mismo
que yo.

Supongo que has probado con un volumen no montado "binary", tampoco con un
tubo o similar, pero con un archivo real de Windows. Tampoco tindrás
_fmode=O_BINARY en tu código. (Todas estas son posibilidades de olvidarse de
la transformación, por qué hay casos que lo necesitan.)
J.A. Gutierrez
2004-04-30 07:51:01 UTC
Permalink
Antoine Leca <***@localhost.gov> wrote:

:> Ejemplo: en gcc/cygwin sobre windows 2003 no funciona, hay
:> que abrir el fichero explicitamente en modo texto, usando
:> fopen (fname, "rt").

: Raro. Muy raro, de verdad.
: He mirado a la FAQ de Cygwin, y la ultima versión en linea
: (http://cygwin.com/faq/faq_4.html#SEC75) está claramente diciendo lo mismo
: que yo.

si, parece que el modo "texto" seria el de por defecto...

: Supongo que has probado con un volumen no montado "binary", tampoco con un
: tubo o similar, pero con un archivo real de Windows. Tampoco tindrás

de hecho, si que estan montados en modo binmode; pero
creo recordar que era el modo por defecto (esto es, no
recuerdo haber seleccionado nada al respecto cuando lo
instale hace tiempo...)

: _fmode=O_BINARY en tu código.

no
--
finger ***@shiva.cps.unizar.es for PGP /
.mailcap tip of the day: / La vida es una carcel
application/ms-tnef; cat '%s' > /dev/null / con las puertas abiertas
text/x-vcard; cat '%s' > /dev/null / (A. Calamaro)
Antoine Leca
2004-04-30 14:24:35 UTC
Permalink
Post by J.A. Gutierrez
Post by J.A. Gutierrez
Ejemplo: en gcc/cygwin sobre windows 2003 no funciona, hay
que abrir el fichero explicitamente en modo texto, usando
fopen (fname, "rt").
de hecho, si que estan montados en modo binmode; pero
creo recordar que era el modo por defecto (esto es, no
recuerdo haber seleccionado nada al respecto cuando lo
instale hace tiempo...)
He instalado el Cygwin. En una pantalla de instalación, te pregunta sobre el
modo de los fichero (es una de las escasas preguntas que hace).

Y el modo binario es la valor por defecto. Lo cual explique todo.

Supongo que antes, no era asi, y que Earnie Boyd ha instalado sus Cygwin sin
está opción. Lo que explica la FAQ (y el hecho que las explicaciones como la
sua, o la mía, no admiten muchas criticas frontales, por que "es así que les
cosas suelen hacerse").

Pero como los usuarios de Cygwin prefieren hacer "como si está Unix de
verdad" (lo cual está muy ybién, solo digo que hay otras utilizaciones de
Cygwin), y como del otro lado los programas de Unix son lo sufisamiente mal
programados para no tener "rb" cuando toca (lo cual esta vez está mal), pués
resulta que es más sencillo echar la culpa a Microsoft de tener "malas
convenciones", y circonverlo cambiando la opción per defecto de instalación,
así menos denuncias, más tranquilos. :-(.

Lo peor, es que no he encontrado lo que se tiene que hacer (menos
reinstalar, que no es una opción) para cambiar tu configuración para poner
pasar de binario a texto per defecto (menos lo de "rt" o de _fmode, que no
son soluciones, sino arreglos malos para no decir chapucerias).


Antoine

Alberto Giménez
2004-04-27 18:38:48 UTC
Permalink
Post by newsf
if((leido = (char *)malloc(10 * sizeof(char))) == NULL)
^^
No es muy aconsejable utilizar "magic numbers". mejor defínete una
constante y utilízala homogéneamente.
Post by newsf
fgets(leido,10,f_in);
if (leido != "\n") printf ("%s", leido);
Confundes un par de cosas del lenguaje C. La variable leido es un
puntero a carácter, o sea, una dirección de memoria. "\n" es una cadena
que consta de 2 carácteres: retorno de línea y el carácter 0. '\n' es el
carácter retorno de línea.

leido puedes "verlo" como un array de 10 carácteres (9 + \0 de cerrar el
string), por lo que comparar la dirección "leido" con el string "\n" no
tiene sentido. Deberías utilizar leido[0] != '\n', aunque esto no
funcionaría si la línea contiene espacios en blanco antes del retorno.
Mejor definirte una función "isblankline (char *line)" o algo así.
Post by newsf
}while (feof(f_in) == 0);
En C los ficheros puedes imaginarte que al final tienen un carácter
especial, que indica fin de fichero. Por lo que tienes que leer SIEMPRE,
no como en Pascal o Ada, y si esa lectura es errónea, mirar a ver si es
por un error en sí, o que has llegado ya a ese "carácter especial" (en
realidad es una especie de bandera indicadora). Saludos


- --
Alberto Giménez, SimManiac en el IRC
http://www.almorranasozial.es.vg
GnuPG ID: 0x3BAABDE1
Don't compare Linux with Windows. There's no colour (except blue).
Loading...