getopt error handling for multiple comma separated

2019-07-28 18:18发布

问题:

how to validate a string variable for multiple combinations of comma separated values received from command line for getopt?

       case 'a' :
                    flaga=1;
                    alg = optarg;
                    printf("you entered option -a \"%s\"\n", optarg);

                    if(strcmp(alg,"lr") == 0 )
                       {
                         ....//valid
                       }
                    else if(strcmp(alg,"lda") == 0 )
                       {
                         ....//valid
                       }
                    else if(strcmp(alg,"knn") == 0 )
                       {
                          ...//valid
                       }
                     """""
                      """"
                    else
                      {
                       printf("wrong value entered for option -a \n");
                       exit();
                       }

option -a can accept these values : "knn","lda","lr","kart","nb","svm" .

The above code handles errors perfectly if user passes only single value .

But option -a can accept multiple values as comma separated ,

                    Eg :   -a knn,lr,lda

User can pass these values in any combination of any values !!

                    Eg :   -a knn,lr,lda
                    Eg :   -a knn,lda.lr
                    Eg :   -a lda,lr

How to Check if user has passed valid values for option -a ?

The above code i have written is included in switch case and can handle if only single value for option -a is passed .

回答1:

You can try with the strtok() function:

char *token;

token = strtok(optarg, ",");
while (token != NULL)
{
    if (!strcmp(token, "knn") && !strcmp(token, "lr") && !strcmp(token, "la")
        *error handling*
    token = strtok(NULL, ",");
}

PS: strtok() is part of string.h

EDIT: I don't think this code will have your desired behaviour. This will be better:

char *token;
size_t i = 0;
char knn = 0, lr = 0, la = 0;

token = strtok(optarg, ",");
while (token != NULL)
{
    if (!strcmp(token, "knn") && knn == 0)
        knn = 1;
        ... // valid
    else if (!strcmp(token, "lr") && lr == 0)
        lr = 1;
        ... // valid
    else if (!strcmp(token, "la") && la == 0)
        la = 1;
        ... // valid
    else
    {
        printf("Wrong value entered for option -a\n");
        exit();
    }
    token = strtok(NULL, ",");
    i++;
}

if (i > 3)
{
    printf("Too many values entered for option -a\n");
    exit();
}


回答2:

When you allow several options that are separated with a comma, you must split the string at the commas and process every token. One way to split strings is the library funtion strtok from <string.h>. Take care to remove whitespace from the tokens when you compare them.

Another question is how you want to represent the result. One way is to fill an initially zeroes out array of options with ones as appropriate. Another way is to use a bit-combination so that options 0,1 and 3 correspond to 2⁰ + 2¹ + 2³ = 1 + 2 + 8 = 11. That's the method I used below.

The example program below provides a function multi_opt that parses a list of options that are separated by commas. When an unknown option is dound, the program exits immediately. You may opt to return an invalid bit cobination instead and pass the responsibility of error handling to the calling code.

The function also works when the argument string is empty, in which case no options are set. The main function shows how to use that function..

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

/*
 *      Return index of str in opt or -1 if it can't be found.
 */
int find_opt(const char *str, const char **opt)
{
    int i;

    for (i = 0; opt[i];i++) {
        if (strcmp(str, opt[i]) == 0) return i;
    }

    return -1;
}

/*
 *      Return a bit combination of the options from opt found in str.
 */
unsigned int multi_opt(const char *str, const char **opt)
{
    unsigned int res = 0u;
    char buf[strlen(str) + 1];
    char *p = buf;

    // copy to modifiable buffer and strip whitespace
    while (*str) {
        if (!isspace((unsigned char) *str)) *p++ = *str;
        str++;
    }

    *p= '\0';

    // split string and process tokens
    p = strtok(buf, ",");
    while (p) {
        int i = find_opt(p, opt);

        if (i < 0) {
            fprintf(stderr, "Unknown option %s\n", p);
            exit(1);
        }

        res |= (1u << i);

        p = strtok(NULL, ",");
    }

    return res;
}

int main()
{
    const char *opt[] = {
        "knn", "lda", "lr", "kart", "nb", "svm", NULL
    };
    char *msg = " knn, lda, svm ";
    unsigned int u;
    int i;

    u = multi_opt(msg,opt);

    for (i = 0; opt[i]; i++) {
        printf("%s: %s\n", opt[i], (u & 1u << i) ? "on" : "off");
    }

    return 0;
}


回答3:

          char *alg,alg1;

       case 'a' :
                 flaga=1;
                 alg = optarg;
                 printf("1. you entered option -a \"%s\"\n", alg);

This printf o/p :1. you entered option -a "svm,lr"

                 alg1 = strtok(optarg, ",");
                 while (alg1 != NULL)
                     {
                      if(strcmp(alg1,"lr") == 0 )
                           {
                              //valid
                            }
                         '""""""
                         '"""""""
                      else
                          {
                          }
                      alg1 = strtok(NULL, ",");
                      j++;
                   }
                 printf("2.you entered option -a \"%s\"\n", alg);

This printf o/p :2. you entered option -a "svm" But expected : svm,lr