Hi,
gibt es in C eine effizientere Möglichkeit, die Ausgabe eines Programms nach stdout einzulesen als per "./programm >output" und danach das File output zu parsen? So ala cin oder so..
Joe
Hi,
gibt es in C eine effizientere Möglichkeit, die Ausgabe eines Programms nach stdout einzulesen als per "./programm >output" und danach das File output zu parsen? So ala cin oder so..
Joe
Z.b mit popen !
Aus der Man-Page:
main()
{
char *cmd = "/usr/bin/ls *.c";
char buf[BUFSIZ];
FILE *ptr;
if ((ptr = popen(cmd, "r")) != NULL)
while (fgets(buf, BUFSIZ, ptr) != NULL)
(void) printf("%s", buf);
(void) pclose(ptr);
return 0;
}
Müsste sich in dem von dir genanntem Beispiel die while-Schleife nicht so auswirken, das nach und nach die BUFSIZ Bytes der Ausgabe eingelesen werden? Bei mir ist es so, das ich in einer Endlosschleife hängen bleibe... Die Ausgabe ist eine Zeile lang und ich lese nur einen Bruchteil an Zeichen ein. Jedesmal spuckt er mir die selben aus.
Joe
Ups, sorry mein Fehler. Dennoch wie schaffe ich es, das er mir nach und nach die Ausgabe einliest. Beispiel:
Ausgabe wäre: "Das ist eine lange Ausgabe und man muss Sie in mehreren Schritten einlesen!"
Nun möchte ich davon (da mir die Länge a priori nicht bekannt ist) immer x Zeichen nach und nach einlesen. Geht das?
Joe
Tust Du doch bereits, eine Zeile pro Schleifendurchlauf, wobei Zeilen die länger als BUFSIZ sind aufgespalten werden.
Wenn Du unter GNU programmierst, empfehle ich die getline-Funktion, die allokiert Dir immer genau genug für eine ganze Zeile, egal wie lang diese ist.
#define _GNU_SOURCE // only necessary prior to GCC 3.2
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = popen("/bin/ls /etc", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
if (line)
free(line);
return EXIT_SUCCESS;
}
Alles anzeigen
Hmm, da muss ich widersprechen. Im Moment liest er mir immer die ersten BUFSIZ Zeichen ein. Und wenn es mal <BUFSIZ Zeichen sind, dann lese ich im "undefinierten" Bereich dahinter. Das ist ungünstig.
Joe
Sorry, aber - nö
fgets liest maximal size Zeichen in buffer ein. Der buffer wird nullterminiert. Lesen stoppt bei einem Zeilenvorschub, bei EOF oder wenn size Zeichen gelesen wurden, was auch immer zuerst eintritt.
EDIT: Beachte auch meine Ergänzung oben
fgets liest immernoch nur die ersten BUFSIZ Zeichen, also hab ich deinen Vorschlag mal probiert:
int state;
ssize_t pSize;
size_t len;
char* buffer;
FILE * pFile;
[...]
while (state<2) {
if ((pFile = popen("/usr/sbin/postqueue -p","r"))!=NULL) {
if (pSize=getline(&buffer, &len, pFile) != -1) {
printf("Length=%zu\n",pSize);
printf("->%s<-\n",buffer);
} // if getline
pclose(pFile);
} // if pFile != NULL
if (state<2)
sleep(5); // wait 2 seconds
if (buffer)
free(buffer);
} // while state <2
Alles anzeigen
Da die Mail-Queue meist leer ist sollte rauskommen
tatsächlich erhalte ich
Der Zeilensprung ist tatsächlich in der Ausgabe enthalten! Irgendeine Idee was das soll? Im übrigen erhalte ich beim zweiten Schleifendurchlauf (da state nie >1 wird) einen Speicherzugriffsfehler. Warum?
Joe
Getline verstaut den gelesenen Zeilenwechsel in den Puffer - wenn Du ihn nicht haben willst musst Du das letzte Zeichen löschen.
Und du _musst_ buffer und len anfangs mit 0 initialisieren, wie im Beispiel gezeigt, weil sonst getline u.U. versucht, nicht vorhandenen Speicher freizugeben. Um genau zu sein allokiert getline einen neuen Puffer, wenn der bestehende nicht ausreicht um die Zeile zu fassen (oder noch keiner vorhanden ist -> 0), und packt dessen Adresse in buffer und die Länge in len. Beim nächsten Mal versucht er den buffer in der Länge wiederzuverwenden, reicht das nicht gibt er ihn frei und schreibt die Adresse eines neuen Puffers samt Länge in buffer und len. Deshalb musst Du ganz zum Schluss diesen auch mit free abräumen.
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!