Sponsored Content
Full Discussion: Input arguments with C++
Top Forums Programming Input arguments with C++ Post 302756729 by Corona688 on Wednesday 16th of January 2013 12:15:33 PM
Old 01-16-2013
I wrote some generic commandline parsing code years ago because I wasn't happy with how pointlessly complicated C getopt was, and have been using it in nearly all my projects ever since.

The idea is, you give the program an array of arguments to look for and pointers to variables to fill. Then you plug argc and argv into tsm_getopt, and it fills them if able.

Here is how it looks:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "tsm_getopt.h"

// Structure to keep all global variables in one place.
struct {
        float fval;
        const char *stringval;
        const char *mandatorystring;
        int ival;
        int optionalflag;
        float mandatoryfloat;
} globals={
        3.14159,                // Default value for fval
        "where in the world",   // Default value for stringval
        NULL,                   // Mandatory, NULL if not set for error
        0,                      // Default value for ival
        0,                      // default value for optionalflag
        0.0/0.0,              // mandatory, defaults to invalid 0/0 if not set
};

const opt options[]={
        // "fval" for "--fval" argument,
        // 'f' for '-f' argument,
        // 1 since it takes one argument,
        // a pointer to a float number,
        // "%f" to read one float,
        // and "Float Value" to print as help text.
        {"fval", 'f', 1, &globals.fval, "%f", "Float value"},
        // Similar, but an integer number.
        {"ival", 'i', 1, &globals.ival, "%d", "Integer value"},
        // A string.  Needs a pointer to a char *(not the char * itself).
        {"sval", 's', 1, &globals.stringval, NULL, "String Value"},
        {"mstr", 'm', 1, &globals.mandatorystring, NULL, "Mandatory string"},
        // An option with no parameters.
        // Changes globals.optionalflag from 0 to 1 if set.
        {"optionalflag", 'o', 0, &globals.optionalflag, NULL, "optional flag"},
        // Need this as the last thing in the list, to tell when the list ends
        {"mfloat", 'l', 1, &globals.mandatoryfloat, "%f", "Mandatory float"},
        {NULL},
};

int main(int argc, char *argv[])
{
        if(argc < 2) // No arguments
        {
                tsm_usage(argc, argv, options);
                exit(1);
        }

        if(tsm_getopt(argc, argv, options) < 0)
        {
                tsm_usage(argc, argv, options);
                exit(1);
        }

        // Check any mandatory arguments
        if(globals.mandatorystring == NULL)
        {
                printf("mandatorystring not set\n");
                exit(1);
        }

        if(globals.ival == 0)
        {
                printf("ival not set\n");
                exit(1);
        }

        if(isnan(globals.mandatoryfloat))
        {
                printf("mfloat not set\n");
                exit(1);
        }

        // Arguments should now be ready.
        printf("fval = %f\n", globals.fval);
        printf("stringval = %s\n", globals.stringval);
        printf("mandatorystring = %s\n", globals.mandatorystring);
        printf("ival = %d\n", globals.ival);
        printf("optionalflag = %d\n", globals.optionalflag);
        printf("mandatoryfloat = %f\n", globals.mandatoryfloat);
        return(0);
}

It uses this code:

Code:
/* tsm_getopt.c */
#include <stdio.h>
#include <string.h>
#include "tsm_getopt.h"

static int tsm_findarg(const char *str, const opt options[]);

static int tsm_findarg(const char *str, const opt options[])
{
        int n;
        if(str[1] == '\0')
                return(-1);

        for(n=0; options[n].lname != NULL; n++)
        {
                // "-s"
                if((options[n].sname) &&
                        (str[1] == options[n].sname) &&
                        (str[2] == '\0'))
                        return(n);

                // "-s=..."
                if((options[n].sname) &&
                        (str[1] == options[n].sname) &&
                        (str[2] == '='))
                        return(n);

                // "--sval" or "--sval=..."
                if(str[1] == '-')
                if(strncmp(str+2, options[n].lname, strlen(options[n].lname))==0)
                if((str[2+strlen(options[n].lname)]=='\0')||
                   (str[2+strlen(options[n].lname)]=='='))
                        return(n);
        }

        return(-1);
}

int tsm_usage(int argc, char *argv[], const opt options[])
{
        int n;

        fprintf(stderr, "Usage:  %s\n", argv[0]);

        for(n=0; options[n].lname != NULL; n++)
        {
                fprintf(stderr, "\t--%s", options[n].lname);
                if(options[n].sname)
                        fprintf(stderr,"(-%c)", options[n].sname);
                if(options[n].usage)
                        fprintf(stderr, "\t%s", options[n].usage);
                fprintf(stderr, "\n");
        }
}

int tsm_getopt(int argc, char *argv[], const opt options[])
{
        int arg=1;
        while(arg < argc)
        {
                int which;
                if(strcmp(argv[arg], "--") == 0)
                        return(arg+2);
                else if(argv[arg][0] == '-')
                {
                        which=tsm_findarg(argv[arg], options);
                        if(which < 0)
                        {
                                fprintf(stderr, "invalid option '%s'\n",
                                        argv[arg]);
                                return(-1);
                        }

                        if(options[which].args)
                        {
                                // Handle -s=asdf or --sval=asdf
                                char *eq=strchr(argv[arg], '=');
                                char *argstr=NULL;

                                if(eq != NULL)
                                {
                                        eq++;
                                        if(eq[0] == '\0') eq=NULL;
                                }

                                if(((argc - arg) < 2)&&(eq==NULL))
                                {
                                        fprintf(stderr, "Need argument for %s\n",
                                                argv[arg]);
                                        return(-1);
                                }

                                if(eq) argstr=eq;
                                else    argstr=argv[arg+1];

                                // Store if possible
                                if(options[which].val)
                                {
                                        if(options[which].cmdstr)
                                        {
                                                if(sscanf(argstr,
                                                        options[which].cmdstr,
                                                        options[which].val) != 1)
                                                {
                                                        fprintf(stderr, "Invalid value "
                                                                "'%s' for option '%s'\n",
                                                                argv[arg], argv[arg+1]);
                                                        return(-1);
                                                }
                                        }
                                        else
                                                *((char **)options[which].val)=argstr;

                                        if(eq == NULL)  arg++;
                                }
                        }
                        else if(options[which].val != NULL)
                        {
                                // flag if possible
                                *((int *)options[which].val)=1;
                        }

                        arg++;
                }
                else
                        return(arg);
        }

        return(arg);
}

Code:
/* tsm_getopt.h */
#ifndef __TSM_GETOPT_H__
#define __TSM_GETOPT_H__

typedef struct opt
{
        const char      *lname;         // Long option, mandatory.
        unsigned char   sname;          // Short option, optional.
        int             args;           // Has arguments.
                                                // When cmdstr is NULL, stores
                                                // pointer to arg in *val
                                                // when cmdstr isn't NULL,
                                                // scanf's string into val
        void            *val;           // What to store
        const char      *cmdstr;        // Command string for scanf
        const char      *usage;         // Usage description
} opt;

#ifdef __cplusplus
extern "C" {
#endif

// Parse commandline parameters.  Returns index of first unparsed value.
int tsm_getopt(int argc, char *argv[], const opt options[]);
// Print usage for optional parameters
int tsm_usage(int argc, char *argv[], const opt options[]);

#ifdef __cplusplus
}
#endif

#endif/*__TSM_GETOPT_H__*/

I've just modified it to accept both --arg string and --arg=string syntax.

I'd need to see your vect2 class to add it to this, but maybe you could add the ability to be initialized from strings to your vect2 class instead?
 

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Reading specific contents from 1 input files and appending it to another input file

Hi guys, I am new to AWK and unix scripting. Please see below my problem and let me know if anyone you can help. I have 2 input files (example given below) Input file 2 is a standard file (it will not change) and we have to get the name (second column after comma) from it and append it... (5 Replies)
Discussion started by: sksahu
5 Replies

2. Shell Programming and Scripting

Accepting user input and arguments in PERL

Hi All, Can we pass arguments while calling the perl script and as well as ask user input during execution of the script? My program is as below: I am passing arg1 and arg2 as argements to test.pl ]./test.pl arg1 arg2 Inside the test.pl I have : print "Do you want a name ? (y/n) : ";... (2 Replies)
Discussion started by: jisha
2 Replies

3. Shell Programming and Scripting

grep with two arguments to arguments to surch for

Hello, is it possible to give grep two documents to surche for? like grep "test" /home/one.txt AND /home/two.txt ? thanks (1 Reply)
Discussion started by: Cybertron
1 Replies

4. Shell Programming and Scripting

Script to delete files with an input for directories and an input for path/file

Hello, I'm trying to figure out how best to approach this script, and I have very little experience, so I could use all the help I can get. :wall: I regularly need to delete files from many directories. A file with the same name may exist any number of times in different subdirectories.... (3 Replies)
Discussion started by: *ShadowCat*
3 Replies

5. Shell Programming and Scripting

function terminating if i give input as space or no input and enter

HI i have written a script to ask input from the user. this script should promote the user for y/n input. if user enters anyother input then y/n the script promotes him again. this below code is working fine for all the cases. except for space and enter " if i give space and enter it is... (2 Replies)
Discussion started by: BHASKARREDDY006
2 Replies

6. Shell Programming and Scripting

[Solved] Read and validate input arguments

Hi, I need to get input arguments, as well as validate them. This is how I'm reading them: #!/bin/bash args="$@" # save arguments to variable ## Read input arguments, if so while ; do case $1 in -v | --verbose ) verbose=true;; -z | --gzip ) compression="gz";; ... (3 Replies)
Discussion started by: AlbertGM
3 Replies

7. Shell Programming and Scripting

Read input files and merge them in given order and write them to input one param or one file

Dear Friends, I am looking for a shell script to merge input files into one file .. here is my idea: 1st paramter would be outfile file (all input files content) read all input files and merge them to input param 1 ex: if I pass 6 file names to the script then 1st file name as output file... (4 Replies)
Discussion started by: hyd1234
4 Replies

8. Homework & Coursework Questions

Removing punctuations from file input or standard input

Just started learning Unix and received my first assignment recently. We haven't learned many commands and honestly, I'm stumped. I'd like to receive assistance/guidance/hints. 1. The problem statement, all variables and given/known data: How do I write a shell script that takes in a file or... (4 Replies)
Discussion started by: fozilla
4 Replies

9. Shell Programming and Scripting

How to avoid "Too many arguments" error, when passing a long String literal as input to a command?

Hi, I am using awk here. Inside an awk script, I have a variable which contains a very long XML data in string format (500kb). I want to pass this data (as argument) to curl command using system function. But getting Too many arguments error due to length of string data(payloadBlock). I... (4 Replies)
Discussion started by: cool.aquarian
4 Replies

10. Shell Programming and Scripting

How to pass arguments based on input file?

This script is running some exe file we are passing three argumnet below custome key word Want to update script based on input files every time it will take argument from input file below is the input files should take this input put it into the script. k.ksh cd /u/kali/temp ... (8 Replies)
Discussion started by: Kalia
8 Replies
All times are GMT -4. The time now is 04:57 PM.
Unix & Linux Forums Content Copyright 1993-2022. All Rights Reserved.
Privacy Policy