0

I have the following code which is working but it's kinda annoying to define a variable in each and every line:

char *argv[100];
int argc = 0;
argv[0] = "test";
argc = 1;
char verbose[4], source[20], target[20];
int linenum=0;
while(fgets(line, 256, file) != NULL)
{
    char arg[20], value[20];
    if(line[0] == '#' || strlen(line) < 6) continue;
    linenum++;
    if(sscanf(line, "%[^=]=%s", arg, value) != 2)
    {
        fprintf(stderr,"Syntax error: %s\n",line);
        continue;
    }
    if (value && strcmp(arg,"verbose")==0) {
        strncpy(verbose,value,sizeof(verbose) - 1);
        argv[argc++] = "-v";
        argv[argc++] = verbose;
        //argv[argc++] = value; //not working, shows 0
    }

    if (value && strcmp(arg,"source")==0) {
        strncpy(source,value,sizeof(source) - 1);
        argv[argc++] = "-s";
        argv[argc++] = source;
    }

    if (value && strcmp(arg,"target")==0) {
        strncpy(target,value,sizeof(target) - 1);
        argv[argc++] = "-t";
        argv[argc++] = target;
    }

    //and so on
    |
    |
    |
    |


}

How can I copy to a single char the "value" from inside the loop ? I mean by avoiding the usage of strncpy().

Timothy Jones
  • 21,495
  • 6
  • 60
  • 90
Sam Reina
  • 305
  • 1
  • 7
  • 22
  • `if (value...` does nothing. The code only does "if an array has an address, which is always true, then..." – Lundin Sep 27 '13 at 06:32
  • It is also unclear what you are asking. "value" is a string, it is not a single char. You copy strings with strcpy. Or do you mean something else? – Lundin Sep 27 '13 at 06:36
  • (Indeed, [strncpy should never be used, because it is an obsolete function](http://stackoverflow.com/questions/2114896/why-is-strlcpy-and-strlcat-considered-to-be-insecure) only intended to be used for an obscure string format on ancient Unix systems. Use strcpy or memcpy.) – Lundin Sep 27 '13 at 06:37

3 Answers3

1

You can use a table like this:

int source_checker(char *value) { /* .... */; return 0; }
int verbose_checker(char *value) { /* .... */; return 0; }
int target_checker(char *value) { /* .... */; return 0; }

typedef int (*checker_function)(char *); 
const char *label_table[] = { "source", "verbose", "target", 0 };
checker_function checker_table[] = { source_checker, verbose_checker, 
    target_checker, 0 };

typedef enum { tk_source, tk_verbose, tk_target, tk_END } token;


while(fgets(line, 256, file) != NULL)
{
    // ...
    for (size_t i = tk_source; i < tk_END; i++) {
      if (value && strcmp(arg, label_table[i]) == 0) {
          if (checker_table[i](value)) {
            break;
          }
      }
    }
perreal
  • 94,503
  • 21
  • 155
  • 181
  • thanks, it's a great idea but in my case cannot use it cause on each condition I do some validation on each line from config so cannot make it generic. I just want to avoid the nasty way of defining everytime a variable for strncpy – Sam Reina Sep 27 '13 at 06:47
  • 2
    you can create validator functions for each token and store function pointers to do token specific validations in a similar table. – perreal Sep 27 '13 at 06:51
  • I'm sure you're right about this but I'm still learning c, so sometimes it's difficult to implement into my code some great ideas without having an inspirational example – Sam Reina Sep 27 '13 at 06:55
  • I added an example for validator tables. To me, it looks like you need to be more generic to get rid of some clutter. – perreal Sep 27 '13 at 07:04
  • yes, thanks! I have only one question: how will it know for which arg to validate value? Because their order can change in config file – Sam Reina Sep 27 '13 at 07:13
  • for the source arg, the `source_checker` function will be called. So you will write the code related to source argument in the `source_checker` function. – perreal Sep 27 '13 at 07:16
0

You can use a loop for each of your if conditions, and store the differing values in arrays populated beforehand.

AbdullahC
  • 6,649
  • 3
  • 27
  • 43
-1

If you are trying to save a few lines of code, you could do this

#include <string.h>

....
char* tempstrings[100];
int temps=0;
..

if (value && strcmp(arg,"verbose")==0) {
    argv[argc++] = "-v";
    argv[argc++] = tempstrings[temps++] = strdup(value);
}

...

// at the end of the program, clean up all the temporary strings
for(int i=0;i<temps;i++) free(tempstrings[i];
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
  • 1
    Introducing a non-standard function to a standard program, for the purpose of intentionally creating a memory leak doesn't sound like a very good idea to me. – Lundin Sep 27 '13 at 06:41
  • ok, I got rid of the memory leak. I don't think strdup is non-standard. If you don't have it, then `char* x=malloc(strlen(s)+1); strcpy(x,s); return s;` will just about do it. – Mark Lakata Sep 27 '13 at 06:55
  • `strdup` is not part of the C standard, but it is part of the POSIX standard. It is a pointless, superfluous function anyhow, since it is so very easy to replace with 100% standard functions, as you demonstrated in your comment. – Lundin Sep 27 '13 at 11:23