C-Code automatisch einen Graphen zeichnen lassen

Lesezeit: 6 Minuten

Benutzer-Avatar
JMzance

Ich habe ein Programm geschrieben, das eine Liste von Daten in eine ‘.dat’-Datei schreibt, mit der Absicht, sie dann separat mit gnuplot zu plotten. Gibt es eine Möglichkeit, meinen Code automatisch zu plotten? Meine Ausgabe hat die Form:

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

Wenn ich den Code ausführe, würde das Diagramm im Idealfall auch mit einem x-Etikett, einem y-Etikett und einem Titel gedruckt werden (der von meinem C-Code geändert werden könnte). Danke vielmals.

  • Vielleicht mal nachsehen system Funktion.

    – sje397

    19. August 2010 um 11:23 Uhr

Benutzer-Avatar
BenB

Ich bin darauf gestoßen, als ich nach etwas anderem in Bezug auf Gnuplot gesucht habe. Obwohl es sich um eine alte Frage handelt, dachte ich, ich würde einen Beispielcode beitragen. Ich benutze das für ein Programm von mir, und ich denke, es macht einen ziemlich ordentlichen Job. AFAIK, dieses PIPEing funktioniert nur auf Unix-Systemen (siehe die Bearbeitung 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;
}

BEARBEITEN

In meiner Anwendung bin ich auch auf das Problem gestoßen, dass der Plot erst erscheint, wenn das aufrufende Programm geschlossen wird. Um dies zu umgehen, fügen Sie a hinzu fflush(gnuplotPipe) nachdem Sie verwendet haben fprintf um ihm deinen letzten Befehl zu senden.

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

BEARBEITEN 2

Man kann vermeiden, in eine Datei schreiben zu müssen, indem man gnuplot die sendet plot '-' Befehl gefolgt von Datenpunkten gefolgt vom Buchstaben “e”.

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");

  • Ich weiß, dass es sehr lange her ist, seit diese Antwort veröffentlicht wurde, aber ich habe den Code aus Ihrer zweiten Bearbeitung plus die for-Schleife mit der verwendet commandsForGnuplot darin, um Befehle hinzuzufügen, und es zeichnet, aber es fügt keinen der Befehle (Titel, xlabel oder ylabel) hinzu. Wie kann ich sie hinzufügen, wenn nicht so? Bitte.

    – MO

    22. September 2017 um 19:34 Uhr

  • Wenn jemand auf dem Diagramm auf ein „-“ und einen zusätzlichen Punkt stößt, handelt es sich nicht wirklich um geplottete Punkte. Sie sind Teil der Legende. Tun fprintf(gnuplotPipe, "plot '-' notitle\n"); und sie würden verschwinden.

    – Tommy Wolfsherz

    21. März um 10:36 Uhr


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

Der portabelste und wahrscheinlich einfachste Weg wäre jedoch immer noch der Aufruf von gnuplot, um ein Skript zu plotten. Wie in sje397 erwähnt, überprüfen Sie Ihre Dokumentation auf den system()-Aufruf in stdlib.h.

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

  • Ich bin nicht fantastisch darin, all diese Dokumentationen zu verstehen, aber ich habe die Deklaration für system() gefunden: int system(const char *command); Geht es dann nur darum, so etwas hinzuzufügen?: system(gnuplot plot “data_set.dat” with 1:2 using lines);

    – JMzance

    19. August 2010 um 11:54 Uhr


  • Am Ende habe ich mich für so etwas entschieden:

    – JMzance

    23. September 2010 um 11:56 Uhr

  • #include “gnuplot_i.h” int main(void) { DATEI outFile; outFile = fopen(“Flight_Path.dat”, “w”); / Iterative Schleife, die in die Ausgabedatei druckt: example.dat */ fclose(outFile); gnuplot_ctrl *k; k = gnuplot_init(); gnuplot_set_xlabel(k, “x”); gnuplot_set_ylabel(k, “y”); gnuplot_cmd(k,input_x); gnuplot_cmd(k,input_y); gnuplot_cmd(k, “Titel setzen \”Flugbahn mit Ziehen\””); gnuplot_cmd(k, “plot \”Flight_Path.dat\” unter Verwendung des 1:2-Titels \”Flight Path\” mit Linien, \ sleep(7); gnuplot_close(k); return 0; }

    – JMzance

    23. September 2010 um 12:00 Uhr

  • Ich bin mir sicher, dass Ihnen einige Teile dieses Codes fehlen, dh Sie öffnen und schließen die Datei unmittelbar danach. Außerdem ist die Formatierung in Kommentaren einfach scheiße. Bitte bearbeiten Sie Ihren ursprünglichen Beitrag und fügen Sie Code hinzu – ich würde das selbst tun, aber wie gesagt, ich glaube, Ihrem Code fehlt etwas.

    – Jim Brissom

    23. September 2010 um 21:50 Uhr

Benutzer-Avatar
Nidish Narayanaa

Obwohl ich viele Möglichkeiten gesehen habe, dies zu tun, wäre die einfachste Möglichkeit, die Funktion system() (aus stdlib.h) in C zu verwenden. Erstellen Sie zuerst ein gnuplot-Skript und speichern Sie es als “name. gp” (weder der Name noch die Erweiterung sind wichtig).
Ein einfaches Skript wäre,

plot 'Output.dat' with lines

Fügen Sie nach dem Speichern dieser Skriptdatei einfach hinzu
system("gnuplot -p name.gp");

am Ende Ihres Codes.
So einfach ist das.

Stellen Sie sicher, dass Sie den gnuplot-Pfad zu den Windows-Systempfadvariablen hinzufügen.

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

Prost,
Andreas

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");
}

Ich weiß, es ist zu spät, aber ich antworte, ob es jemandem helfen kann. fputs macht wirklich den Job, den Sie wollen. Zuerst müssen Sie die Daten, die Sie plotten möchten, in eine temporäre Datei data.temp drucken.

FILE *pipe_gp = popen("gnuplot -p", "w");
fputs("set terminal png \n",pipe_gp);
fputs("set output 'abc.png' \n",pipe_gp);
fputs("set xlabel 'f' \n",pipe_gp);
fputs("set xrange [0:100] \n",pipe_gp);
fputs("set yrange [0:100] \n",pipe_gp);
fputs("plot 'data.temp' u 1:2 w circles lc rgb 'pink' notitle \n",pipe_gp);
pclose(pipe_gp);

1143220cookie-checkC-Code automatisch einen Graphen zeichnen lassen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy