How do I iterate through clustered switches?

Hi there, first post.
I am having a huge issue wrapping my mind around a problem in a program I am currently writing. I need to be able to parse through multiple switches clustered as one command line argument, something like this for example:
 
  -rRsc


I can't use getopt, program_options or any third party libraries or anything like that.

The biggest issue I am facing when I say I cannot wrap my mind around it, is I don't understand how using a simple while loop or switch statement with boolean flags for each switch would be able to account for every conceivable combination of switches. So -rRsc is equal to -rsRc and all other combinations. The only way I've been able to get my program to work so far was with a massive if-else statement over 500 lines just to account for every combination and I know this is wrong. I just can't see how you wouldn't have to do the same thing if the user enters -r and its flagged but what if they enter -rc as this is completely different from just a -r. I need someone to explain how this can be done very simply, preferably with an example as I just can't seem to grasp what seems to be a very easy concept.

Thanks
Assuming I understand what you're asking, I'd read the data "-rRsc" into a string, then check, say, the first two characters to see that it is a "-r" switch. Then I'd go through character by character, setting booleans or whatever the case may be.

1
2
3
4
5
6
7
8
9
for(unsigned int i = 0; i < op.size(); ++i) { // supposing op has the characters after "-r"
    switch(op[i]) {
        case 'R':
            R_flag_set = true; // or whatever R implies
            break;
        case 's':
            s_flag_set = true; // or whatever s implies
            break;
// and so on 

Is this kind of what you were looking for?
In a way. But what if the s flag is set after the R so now you'd have -rR but what about possible switches afterward? That's the problem, I'm facing. I don't understand how to write efficient and as little code as possible to be able to process all possible combinations
OP wrote:
But what if the s flag is set after the R so now you'd have -rR but what about possible switches afterward?


That's what the for loop is doing. It is iterating through all of the flags that were entered.
So the above loop can account for any way the switches are entered? So for example, it can deal with -rRsc -rsRc -rscR -rRcs etc?
Yes, that loop will set the flags to true as long as you program it correctly.
Okay, but what if the switch starts with a character other than -r? I know this must be frustrating to explain, it's just that in the program I am writing different combinations of switches will do different things depending on whats entered. So not only I am trying to determine if every combination can be entered but also how to get my functions to work if certain combinations are entered.
can you post a set of examples on how the user might call the program??
i mean, examples on the possible CMD lines.
Sure, the possible switches are:
1
2
3
4
5
6
7
8
    -c (C++ file extensions)
    -j (Java file extensions)
    -m (Multimedia file extensions)
    -x (regex expression for file extensions)
    -r (recursive file scan)
    -R (reverse alphabetical order of file extensions)
    -s (sort by file size)
    -h (help)


If these switches are turned on:
1
2
3
4
5
6
7
8
    -c will search for .cpp|.c|.h|.hxx|.hpp files
    -j will search for .java|.class
    -m will search for .avi|.mkv|.mpeg|.mp3|.mp4
    -x will allow the user to enter a regex expression (such as "\.(docx|doc)")
    -r scans through directories recursively
    -R lists files by extension in reverse order (z - a)
    -s sorts files by ascending file size OR descending file size if -R is also entered
    -h shows how the program is used
Last edited on
Off the top of my head, here's how I'd look at these, in pseudocode:


- By some method, split the command line arguments into strings for each argument (that is, space separated string).
  If the user used the argument string "-r -R" then I would have this split into two strings, "-r" and "-R".
  If they compressed it to "-rR" I would have that as a single string.
- For each of these strings:
    - If the first character is not a '-', note the error on the console and either quit or just ignore that string.
    - For each of the remaining characters: (this is the loop I had before)
        - If I find 'h', display help and terminate (assuming someone asking for help isn't simultaneously wanting
          the program to do any work)
        - Otherwise check the character and set the appropriate boolean (practically all of the options are of this kind)
        - In the case of 'x', you'd need to check, say, the next string (for a case like "-x <regexp>") or the rest
          of the current one (for a case like "-x<regexp>") and store it as your regexp you'll use.
          It will be up to you how you'd want to handle someone who inputs something like "-xr <regexp>";
          in that case, you may decide to just set a boolean saying to read the next string as a
          regexp or something.
Okay so, if flags are set, wouldn't I then after have to if-else through and determine if the flags are set and if in a certain way do this, else do this? Wouldn't that still result in a lot of code for possible combinations?
Depending on how your program is set, you could just have the -c, -j, -m flags populate your regexp variable appropriately (or add to it, depending on how you want them to work).

If you want to save code work for the "reverse order" bit you could define an operator (say, less than) you are going to use to order the results and if you receive a -R just set that operator to the opposite (say, greater than) instead. Then just use that operator in code.
Okay I think I am beginning to understand.
So say a -c, -r and -R flag were set when the user entered -rcR, you'd set the R flag, r flag and the c flag. You would then make an if statement where if those three flags were set you would populate a regex with c++ file extensions, scan recursively for them and print them in reverse order or could you do it in a way without if-elses? Because then you would have to do if-elses in case an -s was used or a -j etc
Last edited on
i can think of two approaches:

1 - you can design the switches handler to contain multiple if statements that have no else's.
each if statement calls the proper function, like this:

1
2
3
4
5
if (   (InnerState & FIRST_FLAG) != 0 )
     first_handler(  /* argument list */ );
if(    (InnerState & SECOND_FLAG) !=0 )
     second_handler( /* argument list */ );
// . . . 


the second approach would be using pointers to functions.
define an array of pointers to functions, initialize it to the switch handling functions.
after you set the Inner-State flags you can put this loop that will call the proper functions:

1
2
3
4
5
6
7
8
9
10
11
// Func is the array of pointers to functions.
const unsigned int   NUMBER_OF_FUNCTIONS = 3;
void ( * Func [NUMBER_OF_FUNCTIONS] ) ( /* argument list */ ) = { f1 , f2 , f3 };

//sizeof(Func)/sizeof(Func[0])---->will evaluate to the number of elements in the array.

for( int i=0 ; i < ( sizeof( Func ) / sizeof( Func[0] ) ) ; i++)
{
        if( ( InnerState & ( 0x01 << i ) ) != 0 ) // if the i-th flag is set
                 ( * Func[i]  )   (  /* argument list */ ); // call the proper function.
}


the down side of this approach is that all functions pointed to by this array MUST have the same argument list and the same return type.
What do you mean by the switches handler?
i meant the function that will DO the action demanded by the switch.
sorry for the poor name.
That's okay! So the InnerState, what exactly is that mean?
InnerState is the integer that will hold the flags.
Topic archived. No new replies allowed.