0

I want to rewrite a program starting with main(){} so that I can use it as a function. Normally the program expects an input file an output file and optionally up to 6 arguments. I pass them within the command line with:

programname --opt1 --op2 --op3 <input file> output file

The different arguments in the program are then read by getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *indexptr).

When I want to create a function out of this I have to swith the name main() to some other, lets say programname(), besides I have to directly pass the arguments, so out of

main(int argc, char **argv){}

it becomes e.g.:

main(int opt1, int opt2, int opt3, FILE *infile, FILE *outfile){}

My question is: how can I manage the optionality of the number of input arguments? With getopt_long I can manage this with using --opt1 instead of -opt1, but getopt_long can just be used within a main function, or? Can I somehow create a function that has no specified number of inputs?

Thanks for your help!

EDIT: Now I try to read argv from user with scanf()

A small example, you can try e.g: first input: --dd=2 second input: ok

#include <getopt.h>
void main(){

    char **options = (char**) malloc(6*sizeof(char*));
    int i;
    for(i=0;i<6;i++){
        options[i] = (char*) malloc(100*sizeof(char));
    }

    int argc=1;

    printf("%s\n", "insert your options. e.g.: [--ngf=20]");
    printf("%s\n", "if finished press [ok]");

    scanf("%s",options[argc]);
    while (strcmp(options[argc],"ok")!=0){
        argc++;
        scanf("%s",options[argc]);
    }

    char **argv = (char**) malloc(argc*sizeof(char*));

    for(i=0;i<argc;i++){
        argv[i] = (char*) malloc(100*sizeof(char));
    }
    for(i=0;i<argc;i++){
        argv[i] = options[i];
    }

    /* Process Arguments */
      optind = 1;
      double aa,bb,cc;
      int c, dd;
      int option_index = 0;
      static struct option long_options[] = {
             {"aa", 1, 0, 1},
             {"bb", 1, 0, 2},
             {"cc", 1, 0, 3},
             {"dd", 1, 0, 4},
             {0, 0, 0, 0}
      };
      while ((c = getopt_long(argc,argv,"hgt",
                              long_options, &option_index)) != -1) {
        switch (c) {
        case 1: if (sscanf(optarg,"%lg",&aa) != 1)
                           fun_Stop("incorrect format");
        break;
        case 2: if (sscanf(optarg,"%lg",&bb) != 1)
                           fun_Stop("incorrect format ");
        break;
        case 3: if (sscanf(optarg,"%lg",&cc) != 1)
                           fun_Stop("incorrect format");
        break;
        case 4: if (sscanf(optarg,"%i",&dd) != 1)
                           fun_Stop("incorrect format");
        break;
        default  :
          break;
        }
      }
}
aciams
  • 35
  • 1
  • 7

3 Answers3

1

There are several possibilities:

1) you leave the interface intact. That means you have to build the argc argv thing yourself when you call the code. Like this:

void myfunction(int argc, char **argv);

...

char *arguments[5]={"whatever","--opt1","--opt2","blabla","blablabla"};
myfunction(5,arguments);

you can use getopt_long as before. Note that the first argument argv[0] is the name of the program (doesn't matter in this case) and not your first argument, which is in argv[1].

or

2) if your options are simply binary on/off affairs you can define your options as constants that can be combined in a bitfield. Like this:

typedef enum {opt1=1, opt2=2, opt3=4, opt4=8} Opts;

void myfunction(unsigned long opts, char *input, char *output)
{
   if(opts&opt1)
    printf("Option 1!\n");

    ...
}

...

myfunction(opt1|opt2,"blabla","blablabla");

This should be depending on the architecture enough for 32 or 64 different options.

Markus Dheus
  • 576
  • 2
  • 8
  • I tried you first solution. But getopt makes trouble?! (see the edits) – aciams Jul 17 '14 at 12:56
  • argc and argv (as seen from main) have argv[0] as the name of the program. I assume get opt is confused by the lack of it. I will fix my example to make that clear. The first option you put into the command line is actually argv[1]. Also it might be useful to try it out first with a static list of strings like the one I used in the example and then build the argument list yourself. Don't try too many new steps at a time ;-) – Markus Dheus Jul 17 '14 at 13:05
0

Just parse argc/argv yourself >o<

if (argc >= 2)
{
    for (int i = 1; i < argc; i++)
    {
        char * const arg = argv[i];
        // parse..
    }
}

Or, you can use Boost.ProgramOptions. (if you're in C++)

ikh
  • 10,119
  • 1
  • 31
  • 70
  • Thanks, I try to insert scanf() for user input and let the program seperate the input to a defined array called argv[]. Allocation is done after spliting the input line. Therefrom I want to get the argc. I will see what I get. – aciams Jul 17 '14 at 11:50
0

It is already done in argc and argv. The number of arguments you pass to your program is stored by the OS in argc (arguments counter) and then you can get the data in argv (arguments vector). You don't need to do what you are trying to, just make it simple.

campescassiano
  • 809
  • 5
  • 18
  • Oh, thank you to let me know what `argv` means - I've never thought 'v' might mean 'vector'!! – ikh Jul 17 '14 at 11:28
  • I don't want to use the program as main program, I want to use it as function, so I need to pass some arguments to the function – aciams Jul 17 '14 at 11:47