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++)
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
);
// Process
text2paragraphs(text,txtLns,paragraphs,&txtPgrphs,pgrphLns);
// Output
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.