Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Deux passes de stdin

14 réponses
Avatar
florian
Bonjour,

je vais surement me faire traiter de noob ;), mais je bloque un peu..

J'aimerai lire deux fois stdin, =E0 l'aide de fgets.

La premi=E8re passe se d=E9roule bien.

Pour revenir au d=E9but, j'ai tent=E9 un rewind(stdin).

Mais, lors de la seconde passe, feof est vrai, et fgets renvoie
NULL...

Surement un truc tout b=EAte mais..

a+

10 réponses

1 2
Avatar
Marc Boyer
Le 03-05-2007, florian a écrit :
je vais surement me faire traiter de noob ;), mais je bloque un peu..

J'aimerai lire deux fois stdin, à l'aide de fgets.


Tu ne peux pas.

La première passe se déroule bien.

Pour revenir au début, j'ai tenté un rewind(stdin).


Et tu as regardé son code de retour ? Il devrait te retourner
EBADF The stream specified is not a seekable stream.

Surement un truc tout bête mais..


Non, non, c'est simplement impossible.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)

Avatar
Laurent Deniau
florian wrote:
Bonjour,

je vais surement me faire traiter de noob ;), mais je bloque un peu..

J'aimerai lire deux fois stdin, à l'aide de fgets.

La première passe se déroule bien.

Pour revenir au début, j'ai tenté un rewind(stdin).

Mais, lors de la seconde passe, feof est vrai, et fgets renvoie
NULL...

Surement un truc tout bête mais..


C'est impossible, il faut bufferiser ce que tu lis durant la 1ere passe
qque part.

a+, ld.

Avatar
florian
On 3 mai, 18:33, Laurent Deniau wrote:

C'est impossible, il faut bufferiser ce que tu lis durant la 1ere passe
qque part.

a+, ld.


mh, c'est du 150Mo compressé (lu avec zcat fic | prog)..
Dommage..

Je vais chercher une autre solution
merci & a+

Avatar
Laurent Deniau
florian wrote:
On 3 mai, 18:33, Laurent Deniau wrote:
C'est impossible, il faut bufferiser ce que tu lis durant la 1ere passe
qque part.

a+, ld.


mh, c'est du 150Mo compressé (lu avec zcat fic | prog)..
Dommage..


Donc tu n'as pas besoin de lire 150Mo mais seulement la taille des blocs
compresses, en general <1Mo qui decompresses devrait faire <10Mo. Ce
qu'il faut que tu detectes/calcules, c'est quel est le plus gros rewind
que tu aurais a faire. Si tu ne le sais pas a l'avance, tu alloues les
150Mo sachant que le systeme te les fourniras au fur et a mesure que tu
y accedes (en tout cas sous Linux).

Perso mes parsers utilisent la technique du read+commit ou read+rollback
comme les DBs. C'est beaucoup plus simple: si le parsing reussi ->
commit, s'il echoue -> rollback et on essaie autre chose (sous forme de
combinateurs). C'est moins optimal que tu lex/yacc mais tellement plus
reposant, on ecrit directement en C qqchose qui ressemble a du BNF ;-).

a+, ld.


Avatar
florian
On 3 mai, 19:18, Harpo wrote:
Je vois 2 solutions :

1 - séparer ton programme en 2 :
zcat fic | prog1
zcat fic | prog2

2 - passer par un fichier temporaire :
zcat fic > tmp
et ouvrir tmp au lieu d'utiliser stdin.


Le problème avec la première solution est que le prog2 à besoin des de
ce qui est fait sur le prog1.

Pour la seconde solution, le but du pipe sur le zcat est de justement
ne pas avoir à décompresser.

Avatar
Jean-Marc Bourguet
florian writes:

On 3 mai, 18:33, Laurent Deniau wrote:

C'est impossible, il faut bufferiser ce que tu lis durant la 1ere passe
qque part.

a+, ld.


mh, c'est du 150Mo compressé (lu avec zcat fic | prog)..
Dommage..

Je vais chercher une autre solution


popen et ouvrir le fichier deux fois

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Eric Levenez
Le 3/05/07 18:51, dans
, « florian »
a écrit :

mh, c'est du 150Mo compressé (lu avec zcat fic | prog)..
Dommage..


Si tu utilisais la zlib, tu n'aurais pas besoin de zcat et ton programme
ferais directement des gz[d]open, gzread ou gzgets...

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.

Avatar
Stephane Chazelas
2007-05-3, 16:08(+00), Marc Boyer:
Le 03-05-2007, florian a écrit :
je vais surement me faire traiter de noob ;), mais je bloque un peu..

J'aimerai lire deux fois stdin, à l'aide de fgets.


Tu ne peux pas.

La première passe se déroule bien.

Pour revenir au début, j'ai tenté un rewind(stdin).


Et tu as regardé son code de retour ? Il devrait te retourner
EBADF The stream specified is not a seekable stream.


rewind n'a pas de code de retour. Utiliser fseek si on veut un code
de retour.


Surement un truc tout bête mais..


Non, non, c'est simplement impossible.


Non, seulement si stdin pointe sur un fichier qui ne permet pas de
lseek (comme un pipe ou un tty). Ca n'a rien a voir avec le fait
que ce soit stdin ou un autre FILE* (au moins chez les Unix).

~$ cat > a.c
#include <stdio.h>
int main() {
char buf[2048];
gets(buf);
puts(buf);
rewind(stdin);
gets(buf);
puts(buf);
return 0;
}
~$ make a
cc -c -o a.o a.c
cc a.o -o a
a.o: In function `main':
a.c:(.text+0x1e): warning: the `gets' function is dangerous and should not be used.
~$ seq 2 | ./a
1
2
~$ seq 2 > b
~$ ./a < b
1
1

Evidemment, on ne peut pas revenir en arriere sur un pipe ou un
tty, question de bon sens.

--
Stéphane


Avatar
Antoine Leca
En news:,
florian va escriure:
On 3 mai, 18:33, Laurent Deniau wrote:

C'est impossible, il faut bufferiser ce que tu lis durant la 1ere
passe qque part.


mh, c'est du 150Mo compressé (lu avec zcat fic | prog)..


Il n'y a pas de solution magique, ou bien tu mets toi-même en tampon ou en
fichier ou que-sais-je tes 150×n Mo décomprimés, ou bien tu exécutes deux
fois l'algorithme de décompression sur les 150 Mo comprimés.

Dans tous les cas, il faut le faire faire _explicitement_, les ordinateurs
(en C) ne sont pas encore suffisament intelligents pour savoir que tu veux
faire et stocker dans le doute le résultat de la décompression dans un «
petit » coin de la mémoire...

(Surtout que 150×n Mo décomprimés, cela doit représenter un bon bout de la
dite mémoire.)


Antoine


Avatar
Antoine Leca
En news:, Jean-Marc Bourguet va escriure:

popen et ouvrir le fichier deux fois


Si la première passe a besoin de lire le fichier complètement avant que ne
se lance la seconde passe, tu vas demander au système de stocker en mémoire
tampon la totalité des 150×n Mo décomprimés (en attente de lecture sur le
deuxième descripteur de fichier).

Et un certain nombre d'implémentation vont te faire un bras d'honneur très
vite (par exemple, Unix original ne permet de stocker les tubes que dans les
entrées directes des inodes, cela risque de ne pas suffir ici;-)); tandis
que d'autres vont essayer de faire de leur mieux, et risquent de swapper
férocement.

Sans parler des systèmes plus exotiques (Windows ? que dit Posix ?) qui vont
refuser tout court la seconde ouverture.


Antoine

1 2