Как правило, gnuplot
требует участка файл, описывающий данные (столбцы) для построения и настройки различных параметров сюжета (название, осевые метки, сетка, линии и т. д.) См. How to pass command line argument to gnuplot?. Если вы хотите сделать вывод из программы C, вам придется либо иметь существующий файл сюжета, либо создать его «на лету» из вашего кода.
Кроме того, в то время как вы можете быть в состоянии pipe
свой путь к решению, вы лучше служили разветвление сюжет для отдельного процесса, построение командной строки с требуемыми параметрами и вызова gnuplot
из execvp
или тому подобное. (который обеспечивает поиск пути в пул и т. д.). С помощью fork
вы можете разгрузить график до ребенка, вызывая execvp
оттуда, оставляя вашу программу свободной, не дожидаясь на gnuplot
.
В следующем примере используется этот подход. Все вспомогательные функции - это просто функции проверки ошибок или просто служебные функции для разделения путей и не связаны с примерами fork
, , gnuplot
. (Они просто держать main()
лаконичными, так что вы можете сосредоточиться на логике, не пробираясь через все валидации. (Всегда есть дополнительная валидация можно добавить).
Код записают значения, вытекающие из простой функции f(x) = x^3 - x2
к имени файла заданный как первый аргумент, предоставленный в командной строке (или до gnuplot.dat
, если аргумент не указан).Программа создаст соответствующий участок файл на лета, написанной gnuplot.plt
(по умолчанию) или имени файла, представленный в формате filename.plt
(где plt
заменяет исходное расширение)
сюжета, созданная программой является следующее:
Вот небольшой пример кода:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
enum { MAXL = 128, MAXC = 256};
FILE *xfopen (const char *fn, const char *mode);
int badmode (const char *s);
int xfclose (FILE *fp);
int xfexists (char *fn);
char *fnwoext (char *nm, char *fn);
int main (int argc, char **argv) {
int pid, status;
float f[MAXL] = {0.0};
char *fn = argc > 1 ? argv[1] : "gnuplot.dat";
char fnbase[MAXC] = "", fnplt[MAXC] = "";
size_t i;
FILE *fp = NULL;
for (i = 0; i < MAXL; i++) /* fill array of values */
f[i] = i * i * i - i * i; /* x^3 - x^2. no overflow */
fp = xfopen (fn, "w"); /* open output file */
for (i = 0; i < MAXL; i++) /* write values to file */
fprintf (fp, "%3zu %10.2f\n", i, f[i]);
xfclose (fp); /* close output file */
/* create 'plot' file 'fn.plt' */
strcpy (fnplt, fnwoext (fnbase, fn));
strcat (fnplt, ".plt");
if (!xfexists (fnplt)) {
xfopen (fnplt, "w");
fprintf (fp, "set xlabel 'x'\n"
"set ylabel 'f(x) = x^3 - x^2'\n"
"set title 'Function Plot of f(x) = x^3 - x^2'\n"
"set grid\n"
"set style data lines\n"
"plot \"%s\" using 1:2 lw 3 linecolor rgb \"blue\"\n"
"quit\n", fn);
xfclose (fp);
}
/* fill arguments array for execvp */
char *args[] = { "gnuplot", "-p", fnplt, NULL };
if ((pid = (fork())) < 0) { /* fork plot process */
fprintf (stderr, "fork() error: fork failed.\n");
return 1;
}
else if (pid == 0) { /* plot from child process */
if (execvp (*args, args) == -1) {
fprintf (stderr, "execvp() error: returned error.\n");
_exit (EXIT_FAILURE);
}
}
waitpid (pid, &status, 0); /* wait for plot completion (not req'd) */
return 0;
}
/** fopen with error checking - short version */
FILE *xfopen (const char *fn, const char *mode)
{
if (!fn || !mode || badmode (mode)) {
fprintf (stderr, "xfopen() error: invalid parameter.\n");
exit (EXIT_FAILURE);
}
FILE *fp = fopen (fn, mode);
if (!fp) {
fprintf (stderr, "xfopen() error: file open failed '%s'.\n", fn);
exit (EXIT_FAILURE);
}
return fp;
}
/** validate file mode 's' is "rwa+b" */
int badmode (const char *s)
{
const char *modes = "rwa+b";
for (; *s; s++) {
const char *m = modes;
int valid = 0;
while (*m) if (*s == *m++) { valid = 1; break; }
if (!valid) return *s;
}
return 0;
}
/** file close with error check */
int xfclose (FILE *fp)
{
if (fclose (fp)) {
fprintf (stderr, "xfclose() error: nonzero return on fclose.\n");
return 1;
}
return 0;
}
/** check if file 'fn' already exists */
int xfexists (char *fn)
{
/* if access return is not -1 file exists */
if (access (fn, F_OK) != -1)
return 1;
return 0;
}
/** isolate filename, without path or extension */
char *fnwoext (char *nm, char *fn)
{
char *p = NULL, *ep = NULL;
char fnm[MAXC] = "";
if (!fn) return NULL;
strcpy (fnm, fn);
if ((p = strrchr (fnm, '/')))
p++;
else
p = fnm;
if ((ep = strrchr (p, '.'))) {
*ep = 0;
strcpy (nm, p);
*ep = '.';
} else
strcpy (nm, p);
return nm;
}
Посмотрите на код, подход с fork
и execvp
и дайте мне знать, если у вас есть дополнительные вопросы.
Похоже, вы на самом деле пытаетесь получить вывод, который вы получаете, когда используете gnuplot так: 'set xrange [0:10]' then' set yrange [0:50] ', add' set zeroaxis' , а затем, наконец, сама функция: «plot x ** 2' –
@ У меня был измененный код, но по-прежнему та же ошибка – vivek