3

I have written a program whose output is written int a file (named as bigger.dat) and in the same program I am trying to invoke gnuplot and plot those data which are stored in bigger.dat file. But after runnung the code following error comes

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

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

How should I remove this error.

Here is my complete code

#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
vivek
  • 47
  • 1
  • 4
  • Looks to me like you're actually trying to get the output you get when you use gnuplot like so: `set xrange [0:10]` then `set yrange [0:50]`, add `set zeroaxis`, and then finally the function itself: `plot x**2` – Elias Van Ootegem May 23 '16 at 11:07
  • @I have modified mycode but still the same error – vivek May 23 '16 at 11:42

3 Answers3

4

Generally, gnuplot requires a plot file describing the data (columns) to be plotted and setting the various plot options (title, axis labels, grid, lines, etc.) See How to pass command line argument to gnuplot?. If you wish to plot from within a C program, you will either have to have an existing plot file, or create one on the fly from within your code.

Further, while you may be able to pipe your way to a solution, you are better served forking the plot to a separate process, building a command line with the required parameters and calling gnuplot from execvp or the like. (which provides shell pathname searching, etc.) Using fork you can offload the plotting to the child process, calling execvp from there, leaving your program free to continue without waiting on gnuplot.

The following example uses that approach. All of the helper functions are simply error checking functions or simply utility functions to split pathnames and are not germane to the fork, execvp, gnuplot example. (they just keep main() uncluttered so you can focus on the logic without wading through all the validations. (there are always additional validations you can add).

The code will write the values resulting from the simple function f(x) = x^3 - x2 to the filename given as the first argument provided on the command line (or to gnuplot.dat if no argument is provided). The program will create an appropriate plot file on-the-fly written to gnuplot.plt (by default) or to the filename provided in the format filename.plt (where plt replaces the original extension)

The plot created by the program is the following:

enter image description here

Here is the short example code:

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

Look over the code, the approach with fork and execvp and let me know if you have any further questions.

Community
  • 1
  • 1
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

Here is the code

#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;
}
vivek
  • 47
  • 1
  • 4
-1

From what I understand, you want to read the content's from bigger.dat to myfile and then send myfile to gnuplot?

In that case you have to to it the same way you wrote them down, that is you have to read from bigger.dat to myfile and then send myfile to 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;
}

Of course this still won't work properly, my suggestion is to write a bash script to read myfile line by line, or (if you don't know bash scripting) check out this answer, that is build the command that you want to send to 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);                                                               
}  

In your case that would be (just the last part):

    ...
    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;
}
smrdo_prdo
  • 234
  • 2
  • 12
  • I have tried your code but it throws following err [write3.c: In function ‘main’: write3.c:38:14: error: redeclaration of ‘i’ with no linkage for (int i=1; i<10; i++) ^ write3.c:8:9: note: previous declaration of ‘i’ was here int i; ^ write3.c:38:5: error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode for (int i=1; i<10; i++) ^ write3.c:38:5: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code ] – vivek May 23 '16 at 12:16
  • Actually my program tries to do the following two thing in the same program 1:make bigger.dat file which should contain the result of x**2 And 2: gnuplot should read bigger.dat file to plot it. – vivek May 23 '16 at 12:19
  • @vivek Oh yes, sorry, I edited the answer, should be working now. – smrdo_prdo May 23 '16 at 12:46
  • @vivek Please check the answer now. – smrdo_prdo May 23 '16 at 12:59
  • Thanks, Surely I will try it. Yesterday I did piping with gnuplot and thats work fine. I am posting my code in reply section So it may help someone – vivek May 24 '16 at 04:22