Thread: Efficient storage of program options

  1. #1
    Registered User
    Join Date
    Jan 2017
    Posts
    16

    Efficient storage of program options

    Hi,

    I'm writing a program that will conditionally take actions based on certain options set when it is called from the command line.

    I've decided to store the state of the options in a structure defined as:

    Code:
    /* Structure to store options */
    struct options {
        int found;
        int overwrite;
        int checkfornp;
        int stripnp;
    };
    The idea is to pass the structure to any function that expects it and have the function be able to do things like:

    Code:
    if(opts.checkfornp) {
        /* do checking code */
    }
    I have a function that I call near the beginning of main() that gets the options, if any, from the first argument sent to the program:

    Code:
    int OptCheck(char *ops, struct options *opts) {
        /*checking for options */
        int i, showhelp=0;
        char o;
        if( *ops == '-' ) {
            opts->found=1;
            for(i=1;(o=*(ops+i)) !='\0';i++) {
                switch(o) {
                case 'o':
                    opts->overwrite=1; /* overwrite source file enabled */
                    break;
                case 'p':
                    opts->checkfornp=1; /* printable characters check requested */
                    break;
                case 's':
                    opts->stripnp=1; /* strip non-printable characters requested */
                    break;
                default :
                    printf("Unknown option: %c.\n",o);
                    showhelp=1;
                    break;
                }
            }
        }
        return showhelp;
    }
    I'm wondering, is there a more efficient way to do this?

    I don't mean "easier", I mean more efficient.

    Also I'm trying not to include anything except stdio.h in the program.

    Thanks in advance for any thoughts.

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    The best way to handle this is to put the options in a struct, as you've done, and then make the variable for that struct global. Passing it around is messy. Globals exist for exactly this kind of use. Avoiding globals no matter what the cost is just stupid. It's a good idea to make the global nature of the variable apparent with a prefix, like g_options.

  3. #3
    Registered User
    Join Date
    Jan 2017
    Posts
    16
    Okay, assuming it was global, or regardless if it was or wasn't.

    Any ideas on if there is a more efficient way than the if>for>switch method of parsing the argv[1] value and setting the options in the structure?

    Thanks.

  4. #4
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    I don't understand what you mean by "efficient" in this context. The only "efficiency" worth worrying about in processing command line options is program readability (i.e., programmer efficiency).

    Normally, you would pass argv to your argument processing function. It looks like you must have a loop around the call to your function in main, which is a suboptimal design.

  5. #5
    Registered User
    Join Date
    Sep 2014
    Posts
    364
    There are functions for parameter reading in unistd.h.
    Here is a skeleton for your program:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    typedef struct {
        int found;
        int overwrite;
        int checkfornp;
        int stripnp;
    } options;
    
    // global options, so every function can access it
    options g_options;
    
    int main (int argc, char *argv[])
    {
        int i;
    
    // start of parameter processing
        while ((i = getopt (argc, argv, "hops")) != -1) {
            switch (i) {
    
                case 'h':
                    printf ("Usage: %s [-h] [-o] [-p] [-s]\n", argv[0]);
                    printf ("    -h    this helptext\n");
                    printf ("    -o    overwrite source file enabled\n");
                    printf ("    -p    printable characters check requested\n");
                    printf ("    -s    strip non-printable characters requested\n");
                    return EXIT_SUCCESS;
    
                case 'o':
                    g_options.overwrite = 1;
                    break;
    
                case 'p':
                    g_options.checkfornp = 1;
                    break;
    
                case 's':
                    g_options.stripnp = 1;
                    break;
    
                default:
                    fprintf(stderr, "See '%s -h' for more information.\n", argv[0]);
                    return EXIT_FAILURE;
                    break;
            }
        }
    // end of parameter processing
    
    /*
     * here comes your code
     */
    
        return EXIT_SUCCESS;
    }
    Other have classes, we are class

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,708
    Efficiency comes in many forms; which is most important to you?

    - how efficiently (in time) you can write and debug the code to make it do what you want.
    - how efficiently (in memory space) the program uses the least amount of code and data memory.
    - how efficiently (in execution time) the program uses options.

    Unless you know (through profiling and testing) that options 2 or 3 are a specific problem, then your first worry should be getting something working as efficiently as possible (The Fallacy of Premature Optimization).

    In a work environment, your boss won't care that it uses 20 less bytes than someone else could have written it, but they will care a lot if it takes you a week longer to do it than seemed reasonable.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jan 2017
    Posts
    16
    Quote Originally Posted by algorism View Post
    ...Normally, you would pass argv to your argument processing function...
    I am using this function for setting the options rather than for dealing with all arguments, so I am passing argv[1] into the function because that is the only valid place for options in this program.

    But I may have a function for dealing with all the arguments and then call my current function from it rather than directly from main, in which case I will take your suggestion and pass it argv.

    For now though I'm trying to do things in small chunks. Originally all the options were simply variables set in main like opover, opnpcheck, etc. and I created the function (partially) to test my understanding of passing by reference. Once I had it working with a definition like this:

    Code:
        int OpsCheck(char *ops, int *gotops, int *opover, int *opcheckp, int *opstrip);
    I felt a good next step would be finding a "cleaner" way that passing in a bunch of variables.

    The contenders where: An Array. A Structure.

    C Arrays are something I understand a bit, though I often find myself forgetting, for a moment, that I can only assign a single value at each array index, whereas I had basically no understanding of structures.

    I thought an array int option[127] where I would assign a 1 to the array index coresponding to the integer ascii value of the character in the string of options, and then have the values of the same numbers as constants. Thus option[OVERWRITE] where OVERWRITE had been defined as 111 would allow me to do things like:

    Code:
        if(option[OVERWITE]) {
            /* do overwrite code */
        }
    But after some thought I decided to attempt using a structure since I need to learn how they work anyway and this seemed like a good time.

    One of the reasons I eventually committed to using a structure, was when I "got it" that I could later modify things and make my option structure be a member of a larger application structure if I wished.

    Using something like MyProgram.options.overwrite and MyProgram.infile feels like a comfortable way to do it and allows me to start with just options.overwrite for now.

    I need to do things in small steps so my poor old brain won't be overloaded trying to grok too many things about the language at the same time.

    Thanks for the input.

  8. #8
    Registered User
    Join Date
    Jan 2017
    Posts
    16
    Quote Originally Posted by WoodSTokk View Post
    There are functions for parameter reading in unistd.h. ...
    [/code]
    That's good to know. I've made a note to look at that library later. For now I am trying hard not to use any libraries that I don't have too so that it forces me to do more things myself thus understand things at a lower level before moving on to other things.

    Thanks for the input.

  9. #9
    Registered User
    Join Date
    Jan 2017
    Posts
    16
    Quote Originally Posted by Salem View Post
    Efficiency comes in many forms; which is most important to you?

    - how efficiently (in time) you can write and debug the code to make it do what you want.
    - how efficiently (in memory space) the program uses the least amount of code and data memory.
    - how efficiently (in execution time) the program uses options.

    Unless you know (through profiling and testing) that options 2 or 3 are a specific problem, then your first worry should be getting something working as efficiently as possible (The Fallacy of Premature Optimization).

    In a work environment, your boss won't care that it uses 20 less bytes than someone else could have written it, but they will care a lot if it takes you a week longer to do it than seemed reasonable.
    I very much "get" and appreciate what you are saying. Much of what you are saying doesn't apply in this case though since my primary concern at this time is learning and understanding the C language. I already wrote the code to do this job several times so far, sometimes in main, sometimes in separate functions. I only asked about efficiency once I thought I had something that seemed reasonably efficient from all the angles I could see so that I could get input from you folks in case there was something that a programmer who KNOWS C would feel was obviously better. My knowledge of C is limited enough that I wouldn't have been surprised if one of you posted something with unknown basic language constructs that I was unaware of that would allow me to assign all the values simply in a single line of code with no loop.

    Actually that isn't completely true, I would have been surprised at least a bit. From what I DO know about C, and in fact one of the main reasons I am learning it, is that it doesn't have a lot of magic syntax that mysteriously does the work, but rather it works on a lower level than other "programming languages" I am familiar with (though not like assembly languages thankfully) and as such you simultaneously get to, and have to, understand what everything is actually doing.

    Thanks for the input.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. problem C-Program (Cache?, Storage?, ...)
    By Nesbesz in forum C Programming
    Replies: 1
    Last Post: 11-25-2015, 04:32 PM
  2. Replies: 16
    Last Post: 09-22-2014, 12:53 AM
  3. An efficient storage scheme for fourier data
    By Sebastiani in forum General Discussions
    Replies: 16
    Last Post: 11-07-2010, 01:22 PM
  4. command/program options
    By azsquall in forum C++ Programming
    Replies: 10
    Last Post: 06-23-2009, 02:39 PM
  5. What's the best way to handle many program options?
    By stickmangumby in forum C Programming
    Replies: 19
    Last Post: 06-06-2007, 04:06 PM

Tags for this Thread