Detectar linea en blanco en C

Iniciado por Dani001, 5 Marzo 2017, 16:57 PM

0 Miembros y 1 Visitante están viendo este tema.

Dani001

Hola, Que funcion en C o de que manera puedo tetectar un espacio en blanco?
Por ejemplo, esta seria mi entrada que le mando desde la linea de comandos:

programa < entrada.in

AABCATFS
TTRTACAS

TRESSSAA
ASRTSOOA


Deberia leer solo las dos primeras y al detectar la linea en blanco cambiar a otra matriz para almacenar las otras dos restantes.
Gracias.

MAFUS

Busca una línea que únicamente contenga '\n'

Dani001

Comprendo lo de '\n' pero  de que manera la puedo buscar?  estoy inciando en esto.
Gracias

MAFUS

Vale, entiendo. Algo que te va a gustar poco: C es un lenguaje de nivel medio y a diferencia de Java, C#, PHP, etc. debes aprender más de como funcionan los ordenadores por dentro, solo entonces sacarás todo el partido al lenguaje. Debes pensar que C fue creado para escribir el sistema operativo  UNIX y eso es trabajar con el hardware.

Dicho esto cuando en la línea de comandos haces COMANDO < ARCHIVO lo que haces es ejecutar el comando o programa y pasar el contenido del archivo al buffer de entrada estándar del comando. Desde tu punto de vista es como si alguien, una vez ejecutado el programa, hubiera escrito todo el contenido del archivo desde el teclado y debieras sacarlo.

En ce existe la función fgets que sirve para sacar una cadena de texto de un archivo, en tu caso el buffer de entrada (que es stdin).

Un posible inicio:

#include <stdio.h>

int main() {
    char str[80] = {0};
   
    fgets(str, 80, stdin);
    while(!feof(stdin)) {
        /* Cambia la siguiente línea por tu detector
         * de líneas vacías.
         **/
        printf("%s", str);
       
        fgets(str, 80, stdin);
    }
}

integeroverflow

tambien podrias leer caracter por caracter desde el archivo con la funcion fgetc(), y ir metiendo los caracteres uno por uno en un buffer llevando un contador, hasta encontrar el caracter '\n'.
cuando encuentres \n asumis que termino una linea, entonces copias el contenido del buffer (la linea) a donde la tengas que copiar, limpias el buffer, reinicias el contador y seguis leyendo caracteres.

el truco esta en que si encontrase el caracter \n, y el contador esta en 0 (es el primer caracter de la linea) asumis que la linea esta vacia y reinicias el buffer y el contador sin copiar nada, para seguir leyendo caracteres y repitiendo el proceso hasta EOF.

Dani001

Excelente! Gracias por su ayuda ya quedo.

Alberto n

Cita de: Dani001 en  5 Marzo 2017, 16:57 PM
Hola, Que funcion en C o de que manera puedo tetectar un espacio en blanco?
Por ejemplo, esta seria mi entrada que le mando desde la linea de comandos:

programa < entrada.in

AABCATFS
TTRTACAS

TRESSSAA
ASRTSOOA


Deberia leer solo las dos primeras y al detectar la linea en blanco cambiar a otra matriz para almacenar las otras dos restantes.
Gracias.

Como lo solucionaste, tengo un problema parecido...

dijsktra

#7
Cita de: Alberto n en  5 Marzo 2019, 03:09 AM
Como lo solucionaste, tengo un problema parecido...

Todavia no lo ha resuelto.

Lo que dice MAFUS respecto a la redireccion de la entrada estandar en shell/UNIX (tambien en COMMAND/Microsoft) es cierto, pero va a ser dificil si no elevas la abstracción, de "caracter \n" a "linea vacia". Para eso te ayuda la función

#include <stdio.h>

ssize_t getline(char **lineptr, size_t *n, FILE *stream);


Aquí va una propuesta, con una "durisima" formalización, de la que no estoy seguro al 100%.
IMPORTANTE: Segun mi criterio, el ultimo parrafo acaba en EOF, no en EOL.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // strlen


#define LINES_PER_FILE 1000
#define LINES_PER_PARAGRAPH 100
#define PARAGRAPH 100
#define LENGTH_LINE 250

/*
 Formal spec hard. Use line (not char) as main abstraction

 P : text[0..txtLns) of char[LENGTH_LINE];
 Q : \forall i,j : 0 <= i <= j <= N and paragraph(V,i,j,N) :
          let
            M = emptyLines(V,0,i)
          in
            isCopy(Pgrphs,M,i,j) and PgrphLns[M]=(j-i)
     txtPgrphs = min(1,N) + emptyLines(text,0,txtLns)

 where

    emptyLines(text,0,txtLns) = #i : 0 <=i <txtLns :empty(text[i])
    paragraph(V,i,j,N) =
                 i = max k : 0 <= k <=j and (k > 0 -> empty(text[k-1]) : k
                 j = min k : i <= k <= N and (k < N -> empty(text[k]) : k
    isCopy(Pgrphs,M,n,m) = \forall i : 0 <= i < m-n : Pgrphs[M][i]=text[n+i]

*/
void  text2paragraphs(const char text[][LENGTH_LINE],
     const int txtLns,
                     char pgrphs[PARAGRAPH][LINES_PER_PARAGRAPH][LENGTH_LINE],
     int *txtPgrphs,
     int pgrphLns[])
{
 int n;
 for(*txtPgrphs=(txtLns>0), n=pgrphLns[0]=0;  n<txtLns;n++)  
   if (strlen(text[n])>1)
     strncpy(pgrphs[*txtPgrphs-1][pgrphLns[(*txtPgrphs-1)]++],text[n],LENGTH_LINE);
   else
     (*txtPgrphs)++;
 return;
}

int main(int argc, char *args[])
{
 char text[LINES_PER_FILE][LENGTH_LINE];
 int txtLns,txtPgrphs;
 char paragraphs[PARAGRAPH][LINES_PER_PARAGRAPH][LENGTH_LINE];
 int pgrphLns[PARAGRAPH];
 
 char *line=NULL;
 ssize_t read;
 size_t len;

 // Input
 txtLns = 0 ;
 while ((read=getline(&line,&len,stdin))!=-1)
     strncpy(text[txtLns++],line,LENGTH_LINE);
 free(line);

 // Process
 text2paragraphs(text,txtLns,paragraphs,&txtPgrphs,pgrphLns);

 // Output
 printf("%d\n",txtPgrphs);
 for (int i=0; i< txtPgrphs ; i++)
   {
     printf("(%d,%d)\n",i,pgrphLns[i]);
     for (int j=0; j< pgrphLns[i] ; j++)
printf("%d.%d\t%s",i,j,paragraphs[i][j]);
   }
}

Ahora comprobamos con el siguiente soneto en castellano del insigne Garcilaso de la Vega (quitando acentos y usando algunas formas del siglo XVI). Fichero poema.txt


bash-2.04$ cat poema.txt
A Dafne ya los brazos le crecian
y en luengos ramos vueltos se mostraban;
en verdes hojas vi que se tornaban
los cabellos qu'el oro escurecian;

de aspera corteza se cubrian
los tiernos miembros que aun bullendo 'staban;
los blancos pies en tierra se hincaban
y en torcidas raices se volvian.

Aquel que fue la causa de tal danio,
a fuerza de llorar, crecer hacia
este arbol, que con lagrimas regaba.

Oh miserable estado, oh mal tamanio,
que con llorarla crezca cada dia
la causa y la razon por que lloraba!



Veamos la salida en shell/UNIX. La primera linea marca el  número de parrafos. Despues, por cada párrafo se da el número de orden , el total de líneas por parrafo, y cada línea enumerada dentro de su párrafo.


bash-2.04$ ./main < poema.txt
4
(1,4)
1.1 A Dafne ya los brazos le crecian
1.2 y en luengos ramos vueltos se mostraban;
1.3 en verdes hojas vi que se tornaban
1.4 los cabellos qu'el oro escurecian;
(2,4)
2.1 de aspera corteza se cubrian
2.2 los tiernos miembros que aun bullendo 'staban;
2.3 los blancos pies en tierra se hincaban
2.4 y en torcidas raices se volvian.
(3,3)
3.1 Aquel que fue la causa de tal danio,
3.2 a fuerza de llorar, crecer hacia
3.3 este arbol, que con lagrimas regaba.
(4,3)
4.1 Oh miserable estado, oh mal tamanio,
4.2 que con llorarla crezca cada dia
4.3 la causa y la razon por que lloraba!



Hmm...  :-\ Demasiada formalidad para un poema tan humano. ;) ;)
Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)