调用gnuplot绘制C程序中的文件

时间:2016-05-23 10:42:01

标签: c gnuplot

我编写了一个程序,其输出被写入一个文件(名为greater.dat),在同一个程序中我试图调用gnuplot并绘制存储在greater.dat文件中的那些数据。 但是在运行之后,代码出现错误

line 0: warning: Skipping data file with no valid points

gnuplot> plot'bigger.dat'
                     ^
     line 0: x range is invalid

我该如何删除此错误。

这是我的完整代码

#include <stdio.h>
#include <stdlib.h>

int main(void){

FILE *f;//pointer to a file 
int i;
f = fopen("bigger.dat","w");// creating a file in the write mode

/*check whether it is opened or not*/

if (f == NULL)
{
printf("unable to open file");
return 0;
}

/* if the file is  opened now then  we write the results of following     program to tht file*/

for (i=1;i<10;i++)

{

fprintf(f,"%d %d\n",i,i*i);


}


/* following code opens gnuplot and read data points from big.dat file*/
FILE *fp = fopen ("myfile","wt");
fprintf(f,"set xrange[0:10]\n");
fprintf(f, "set yrange [0:100]\n ");
fprintf(f, "set zeroaxis\n");
fprintf(fp,"plot'%s'\n","bigger.dat");
fclose(fp);
system("gnuplot -p  <myfile");


return 0;
}//main

3 个答案:

答案 0 :(得分:2)

通常,gnuplot需要绘图文件来描述要绘制的数据(列)并设置各种绘图选项(标题,轴标签,网格,线等)。 How to pass command line argument to gnuplot?。如果您希望在C程序中进行绘图,您将需要拥有一个现有的绘图文件,或者在代码中动态创建一个。

此外,虽然您可以pipe通过解决方案,但您可以更好地将绘图分配给单独的流程,使用所需参数构建命令行并从中调用gnuplot execvp等。 (提供shell路径名搜索等)使用fork您可以将绘图卸载到进程,从那里调用execvp,让您的程序可以继续而无需等待在gnuplot

以下示例使用该方法。所有辅助函数都只是错误检查函数或简单的实用函数来分割路径名,并且与forkexecvpgnuplot示例没有密切关系。 (他们只是保持main()整洁,这样你就可以专注于逻辑而不需要涉及所有的验证。(总有额外的验证可以添加)。

代码会将简单函数f(x) = x^3 - x2生成的值写入作为命令行提供的第一个参数给出的文件名(如果没有提供参数,则写入gnuplot.dat)。该程序将动态创建一个适当的绘图文件,写入gnuplot.plt(默认情况下)或以filename.plt格式提供的文件名(其中plt }替换原来的扩展名)

该计划创建的情节如下:

enter image description here

以下是简短示例代码:

#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;
}

查看代码,使用forkexecvp的方法,如果您有任何其他问题,请与我们联系。

答案 1 :(得分:0)

这是代码

#include <stdio.h>
#include <stdlib.h>

int main(void)
{

FILE *f;//pointer to a file 
int i;
f = fopen("BoosterData.dat","w");// creating a file in the write mode

/*check whether it is opened or not*/

if (f == NULL)
{
printf("unable to open file");
return 0;
}

/* if the file is  opened now then  we write the results of   following     program to tht file*/

for (i=1;i<10000;i++)

{

fprintf(f,"%d %d\n",i,i*i);


}

fclose(f);




  FILE *pipe_gp = popen("gnuplot -p", "w");

 // fputs("set terminal pn\n", pipe_gp);
  fputs("set xlabel date\n",pipe_gp);
  fputs("plot  'BoosterData.dat' u 1:2 title 'data1'\n", pipe_gp);
  pclose(pipe_gp);
  return 0;
}

答案 2 :(得分:-1)

根据我的理解,您希望阅读从bigger.datmyfile的内容,然后将myfile发送到gnuplot

在这种情况下,您必须以与撰写它们相同的方式使用它,即您必须从bigger.dat读取到myfile,然后将myfile发送到gnuplot }:

int main(void)
{

    FILE *f;//pointer to a file 
    int i;
    f = fopen("bigger.dat","w");// creating a file in the write mode

    /*check whether it is opened or not*/

    if (f == NULL)
    {
    printf("unable to open file");
    return 0;
    }

    /* if the file is  opened now then  we write the results of following     program to tht file*/

    for (i=1;i<10;i++)

    {

    fprintf(f,"%d %d\n",i,i*i);


    }

    fclose(f);



    FILE *fp = fopen("myfile", "w"); // I'm guesssiog you want to read it?
    f = fopen("bigger.dat", "r"); // you have to open it again for reading
    int a,b;

    for (i=1; i<10; i++)
    {
        fscanf(f, "%d %d\n", &a,&b);
        fprintf(fp, "plot %d %d\n", a,b);
    }

    fclose(f);
    fclose(fp);

    system("gnuplot -p  <myfile");

    return 0;
}

当然,这仍然无法正常工作,我的建议是编写一个bash脚本来阅读myfile line by line,或者(如果你不知道bash脚本) out this answer,即构建要发送到system()的命令:

#include <stdio.h>                                                             
#include <stdlib.h>                                                            

int main()                                                                     
{                                                                              
    int a;                                                                     
    char buf[BUFSIZ];                                                          

    printf("Please enter a number:\n");                                        
    scanf("%d",&a);                                                            
    printf("Your number is: %d\n",a);                                          
    snprintf(buf, sizeof(buf), "echo %d",a);                                   
    system(buf);                                                               
}  

在你的情况下(只是最后一部分):

    ...
    f = fopen("bigger.dat", "r"); // open it again for reading
    int a,b;
    char command[30];

    for (i=1; i<10; i++)
    {
        fscanf(f, "%d %d\n", &a,&b);
        snprintf(buf, sizeof(buf), "gnuplot plot %d %d", a,b %d",a);                                   
        system(command);
        command = ""; // reset the command variable
    }

    fclose(f);

    return 0;
}