简体   繁体   中英

Run a C program from within a C program

The question pretty much explains itself I have three different C programs and to try and compare their efficiency I tried to test their runtime by making them run several times varying their parameter (which is proportional to time taken) and write how long it takes each program to run for certain parameter (so later i can plot the results).

The following is my code

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

   int main(void){

    int i;
    struct timeval bni, bmi, bfi, bnf, bmf, bff;
    FILE *in;
    char filename1[30] = "shuff.dat";
    int a1,a2,b1,b2,c1,c2;
    char command[100];

    in = fopen(filename1, "w");
    //for(i = 0; i<=100000; i +=100){
    for(i = 0; i<=10; i +=1){

        if (snprintf(command, sizeof(command), "./barajas_n.x %d", i) < sizeof(command)){
        a1 = gettimeofday(&bni , NULL);
        system(command);
        a2 = gettimeofday(&bnf , NULL);
        }

        if (snprintf(command, sizeof(command), "./barajas_m.x %d", i) < sizeof(command)){
        b1 = gettimeofday(&bmi , NULL);
        system(command);
        b2 = gettimeofday(&bmf , NULL);
        }

        if (snprintf(command, sizeof(command), "./barajas_fy.x %d", i) < sizeof(command)){
        c1 = gettimeofday(&bfi , NULL);
        system(command);
        c2 = gettimeofday(&bff , NULL);
        }
        fprintf(in, "%d %d %d %d \n", i, (a2-a1),(b2-b1),(c2-c1));
    }
    fclose(in);
}

I get the following message on the terminal window:

错误信息

Which means this program is running all of its steps, only not correctly executing the programs I want to time.

I've tested all three programs individually in the terminal like this

./barajas_*.x i
  1. Can someone please tell me why system() is taking it's input as a directory and,
  2. how to tell system() it to stop taking it as a directory and execute it?

EDIT: After a long discusion in a chat room the problem was as said by Jonathan Leffler: " a mismatch between the actual command name that existed and the command name that the program was attempting to run."

The actual question is answered by iharob's contribution, for anyone interested the snippet he provided should work if the command name matches the command name being run by the program.

The system() function takes only one argument of type const char * , if you need to build the command try with snprintf() , like this

char command[100];

if (snprintf(command, sizeof(command), "barajas_n.x %d", i) < sizeof(command))
{
    a1 = gettimeofday(&bni , NULL);
    system(command);
    a2 = gettimeofday(&bfi , NULL);
}

also, the return value of gettimeofday() is not useful for calculating the time difference. It's just to check errors, you can get the elapse time using this function

float elapsed_time(struct timeval *end, struct timeval *start)
{    
    struct timeval result;
    if (end->tv_usec - start->tv_usec > 1.0E6)
    {
        double adjust;

        adjust          = (end->tv_usec - start->tv_usec) / 1.0E6;
        start->tv_usec += 1.0E6 * adjust;
        start->tv_sec  -= adjust;
    }
    result.tv_sec  = end->tv_sec  - start->tv_sec;
    result.tv_usec = end->tv_usec - start->tv_usec;

    return result.tv_sec + result.tv_usec / 1.0E6;
}

and then to print the elapsed time

printf("Elapsed time: %f\n", elapsed_time(&bni, &bfi);

As the other answer mentioned you need to add a slash to execute the programs, ./programname instead of .programname , but this is another solution:

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

#include <sys/time.h>
#include <time.h>

/* This function, just calculates the difference in seconds, between end and start */
float elapsed_time(struct timeval *end, struct timeval *start)
{
    struct timeval result;
    if (end->tv_usec - start->tv_usec > 1.0E6)
    {
        float adjust;

        adjust          = (end->tv_usec - start->tv_usec) / 1.0E6;
        start->tv_usec += 1.0E6 * adjust;
        start->tv_sec  -= adjust;
    }
    result.tv_sec  = end->tv_sec  - start->tv_sec;
    result.tv_usec = end->tv_usec - start->tv_usec;

    return result.tv_sec + result.tv_usec / 1.0E6;
}

/* this function will execute the command and wrap the system call
 * with 'gettimeofday()' so you can return the elapsed time while
 * the called program was running.
 *
 * It also builds the command string with the right parameter. 
 */
float run_command_and_return_time(const char *const program, int parameter)
{
    char           command[100];
    struct timeval start;
    struct timeval end;
    int            result;
    /* check that sprintf didn't need more characters */
    result = snprintf(command, sizeof(command), "%s %d", program, parameter);
    if ((result >= sizeof(command)) || (result < 0))
        return -1.0;
    gettimeofday(&start, NULL);
    system(command);
    gettimeofday(&end, NULL);

    return elapsed_time(&end, &start);
}

int
main(int argc, char **argv)
{
    char        cwd[PATH_MAX];
    const char *filename;
    FILE       *output;

    filename = "shuff.dat";
    output   = fopen(filename, "w");
    if (output == NULL)
        return -1;
    /* get the current working directory */
    getcwd(cwd, sizeof(cwd));
    /* add the cwd to the PATH variable, so your barajas_*.x programs are found,
     * this way you don't need the ./bara... anymore, just bara... will do it.
     */
    setenv("PATH", cwd, 1);
    /* from here it's pretty evident what the program does */
    for (int i = 0 ; i < 10 ; ++i)
    {
        float a, b, c;

        a = run_command_and_return_time("barajas_n.x", i);
        b = run_command_and_return_time("barajas_m.x", i);
        c = run_command_and_return_time("barajas_fy.x", i);

        fprintf(output, "%d %f %f %f \n", i, a, b, c);
    }
    /* don't forget to close the output file */
    fclose(output);

    return 0;
}

I note that your code currently reads:

if (snprintf(command, sizeof(command), ".barajas_n.x %d", i) < sizeof(command)){

It looks to me like you're missing a slash in that:

if (snprintf(command, sizeof(command), "./barajas_n.x %d", i) < sizeof(command)){

If that's just a typo, then one remaining problem is that gettimeofday() always returns 0:

The gettimeofday() function shall return 0 and no value shall be reserved to indicate an error.

Any elapsed time is found by computation on the struct timeval structures, more or less as shown in the answer by iharob .

Post-chat synopsis

I invited Carlos to chat with me.

After a bit of discussion in chat and seeing the actual results of running the program, we discovered that the problem was a typo — a mismatch between the actual command name that existed and the command name that the program was attempting to run.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM