2010-08-19 14 views
16

Ich habe ein Programm geschrieben, das eine Liste von Daten in eine '.dat'-Datei schreibt mit der Absicht, sie dann mit gnuplot separat zu plotten. Gibt es eine Möglichkeit, meinen Code automatisch plotten zu lassen? Meine Ausgabe ist von der Form:C-Code automatisch einen Graph erstellen

x-coord analytic approximation 
x-coord analytic approximation 
x-coord analytic approximation 
x-coord analytic approximation 
x-coord analytic approximation 
.... 

Idealfall, wenn ich den Code der Graph laufe auch mit einem x-label, y-Label und Titel gedruckt werden würde (was von meinem C-Code geändert werden könnte). Danke vielmals.

+1

Vielleicht die 'system' Funktion überprüfen. – sje397

Antwort

32

Ich stieß auf diese während der Suche nach etwas anderes in Bezug auf gnuplot. Obwohl es eine alte Frage ist, dachte ich, ich würde etwas Beispielcode beisteuern. Ich benutze das für ein Programm von mir, und ich denke, es macht einen ziemlich sauberen Job. AFAIK funktioniert dieses PIPEing nur auf Unix-Systemen (siehe unten für Windows-Benutzer). Meine Gnuplot-Installation ist die Standardinstallation aus dem Ubuntu-Repository.

#include <stdlib.h> 
#include <stdio.h> 
#define NUM_POINTS 5 
#define NUM_COMMANDS 2 

int main() 
{ 
    char * commandsForGnuplot[] = {"set title \"TITLEEEEE\"", "plot 'data.temp'"}; 
    double xvals[NUM_POINTS] = {1.0, 2.0, 3.0, 4.0, 5.0}; 
    double yvals[NUM_POINTS] = {5.0 ,3.0, 1.0, 3.0, 5.0}; 
    FILE * temp = fopen("data.temp", "w"); 
    /*Opens an interface that one can use to send commands as if they were typing into the 
    *  gnuplot command line. "The -persistent" keeps the plot open even after your 
    *  C program terminates. 
    */ 
    FILE * gnuplotPipe = popen ("gnuplot -persistent", "w"); 
    int i; 
    for (i=0; i < NUM_POINTS; i++) 
    { 
    fprintf(temp, "%lf %lf \n", xvals[i], yvals[i]); //Write the data to a temporary file 
    } 

    for (i=0; i < NUM_COMMANDS; i++) 
    { 
    fprintf(gnuplotPipe, "%s \n", commandsForGnuplot[i]); //Send commands to gnuplot one by one. 
    } 
    return 0; 
} 

EDIT

In meiner Anwendung, lief ich auch in das Problem, dass die Handlung nicht, bis das rufende Programm geschlossen wird, erscheint. Um dies zu umgehen, fügen Sie eine fflush(gnuplotPipe) hinzu, nachdem Sie fprintf verwendet haben, um es Ihren letzten Befehl zu senden.

Ich habe auch gesehen, dass Windows-Benutzer _popen anstelle von popen verwenden können - aber ich kann das nicht bestätigen, da ich Windows nicht installiert habe.

EDIT 2

Man kann vermeiden, durch die Buchstaben „e“, gefolgt von Datenpunkten, gefolgt von Senden gnuplot den plot '-' Befehl in eine Datei zu schreiben.

z.B.

fprintf(gnuplotPipe, "plot '-' \n"); 
int i; 

for (int i = 0; i < NUM_POINTS; i++) 
{ 
    fprintf(gnuplotPipe, "%lf %lf\n", xvals[i], yvals[i]); 
} 

fprintf(gnuplotPipe, "e"); 
+0

Ich weiß, es ist eine wirklich lange Zeit seit dieser Antwort veröffentlicht wurde, aber ich habe den Code von Ihrem zweiten Edit plus die for-Schleife mit dem 'commandsForGnuplot' darin verwendet, Befehle hinzuzufügen , und es stellt dar, aber es fügt keine der Befehle (Titel, Xlabel oder Ylabel) hinzu. Wie kann ich sie hinzufügen, wenn nicht so? Bitte. –

5

Sie können entweder ein gnuplot-Skript erstellen und einen Prozess generieren, der gnuplot ausführt, um dieses Skript über die Befehlszeile zu zeichnen, oder Sie verwenden eine der bereitgestellten Schnittstellen. Für C gibt es eine POSIX ist-Rohr-basierte Schnittstelle von Nicolas Devillard hier: http://ndevilla.free.fr/gnuplot/ ... und eine iostream-basierten C++ Version wird über git verfügbar (siehe: http://www.stahlke.org/dan/gnuplot-iostream/)

Die meist tragbaren und wahrscheinlich die einfachste Way würde trotzdem gnuplot aufrufen, um ein Skript zu erstellen. Wie bereits erwähnt, überprüfen Sie Ihre Dokumentation für den Aufruf system() in stdlib.h.

Nebenbei gibt es auch GNU plotutils, die libplot, eine Bibliothek zum Plotten von Datensätzen, die Sie in Ihrer Anwendung verwenden können, bietet. Siehe: http://www.gnu.org/software/plotutils/

+1

Ich bin nicht fantastisch zu verstehen, all diese Dokumentation Sachen, aber ich habe die Deklaration für system() gefunden: int system (const char * -Befehl); Ist es dann nur ein Fall von so etwas wie diese ?: System (gnuplot plot "data_set.dat" mit 1: 2 mit Linien) hinzuzufügen; – JMzance

+1

Am Ende ging ich für etwas wie folgt: – JMzance

+1

#include "gnuplot_i.h" Int Haupt (void) { FILE * outFile; outFile = fopen ("Flight_Path.dat", "w"); /* Iterative Schleife, die zur Ausgabe der Datei druckt: example.dat */ fclose (outFile); gnuplot_ctrl * k; k = gnuplot_init(); gnuplot_set_xlabel (k, "x"); gnuplot_set_ylabel (k, "y"); gnuplot_cmd (k, eingabe_x); gnuplot_cmd (k, input_y); gnuplot_cmd (k, "Titel setzen \" Trajektorie mit Drag \ ""); gnuplot_cmd (k, "plot \" Flight_Path.dat \“unter Verwendung von 1: 2 Dokument \ "Flight Path \" mit Linien, \ Schlaf (7); gnuplot_close (k); return 0; } – JMzance

2

Obwohl ich viele Möglichkeiten, dies zu tun gesehen habe, die einfachste Art und Weise, dies zu tun, indem Sie das System wäre() (aus stdlib.h) Funktion in C. zunächst eine gnuplot machen Skript und speichern Sie es als "name.gp" (weder der Name noch die Erweiterung wichtig).
A würde einfaches Skript, seine

plot 'Output.dat' with lines 

Nachdem diese Skript-Datei zu speichern, nur
system("gnuplot -p 'name.gp'");
am Ende des Codes hinzufügen.
Es ist so einfach.

0

Ich habe die akzeptierte Antwort angepasst, um ein Float-Array zu zeichnen und gleichzeitig die Verwendung einer temporären Datei zu vermeiden. Darin ist float* data_ das Array und size_t size_ seine Größe. Hoffentlich ist es hilfreich für jemanden!

Cheers,
Andres

void plot(const char* name="FloatSignal"){ 
    // open persistent gnuplot window 
    FILE* gnuplot_pipe = popen ("gnuplot -persistent", "w"); 
    // basic settings 
    fprintf(gnuplot_pipe, "set title '%s'\n", name); 
    // fill it with data 
    fprintf(gnuplot_pipe, "plot '-'\n"); 
    for(size_t i=0; i<size_; ++i){ 
    fprintf(gnuplot_pipe, "%zu %f\n", i, data_[i]); 
    } 
    fprintf(gnuplot_pipe, "e\n"); 
    // refresh can probably be omitted 
    fprintf(gnuplot_pipe, "refresh\n"); 
}