I have a program that parses command line arguments using a while loop. Simply, while iterating through the length of argc, if an argument matches a flag than the next argument is taken as a variable. Now in my assignment we are asked to do this in a way that spaces between flags and integer arguments are optional.
For example if i input -k1 it is the same as -k 1 and 1 is the value stored.
I can't find anything that allows this. The only thing I can think is that if argc is an even number it means that there are no pals between a set of argument and i could use scanf("-k%d",key).
Any helpful pointers for me?
At a POSIX-compatible OS you can use a standart API for that: man getopt. It will do all the dirty job to parse the parameters and will provide you a convenient interface to deal with.
Here is a good example for it: http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html#Example-of-Getopt
Related
I'm working in my C program and I have a doubt about how to use the sscanf function.
I have to get from a string like something$HOME/something2 three strings: the first one has to contain "something", the second one "HOME" and the third one "/something2".
But also it has to be able to split $HOME or $HOME/something, or something$HOME...
What I wrote was something like that:
sscanf(str,"%m[^$]$%m[_a-zA-Z0-9]%*m", &ant, &act, &sig);
But for the cases $HOME, $HOME/something, something$HOME... it takes very strange strings. Any ideas of what can I put on my sscanf to get the other values by NULL in case they don't exist?
Sorry, but you should not use sscanf for that. Your input seems to be a shell command line argument and you seem to want implement variable expansion.
For that, you have to write your own parser that would parse the expression, identify and do variable expansion. It's not a job for scanf - it's a job for your custom loop where you inspect each and every character in a string.
There's a utility with like exactly that functionality called envsubst. You could inspect its source gettext/envsubst.c. You could also take a look at wordexp; however, wordexp function is a way broader function.
I want to compare the different elements of a command-line argument. It would be entered all together resulting in the string being found at argv[1]. However, I am not sure how to compare the elements and individual characters as I am looking for repetitions.
If I compared [2] to [3] in the string, there would be nothing there as only 1 string is entered in the command line argument and I need to compare the characters found within that string argv[1]. I am unable to include spaces so I wouldn't be able to compare argv[2] to argv[1].
Read Modern C and see this C reference.
If you code for Linux, read also documentation of GNU libc, in particular the section on parsing program arguments.
You could also use strcmp(3) to compare your program argument to some fixed constant string.
The program arguments are given to your main function, traditionally defined as int main(int argc, char**argv). They are always strings (of different addresses), and on POSIX you are practically certain that argc>0, argv[0] is a non-empty string (somehow the name of the program), all argv[i] with i >= 0 and i < argc are non-null, and argv[argc] is NULL.
You could code inside your main something like
if (argc>1 && !strcmp(argv[1], "foo")) {
/// handle `foo` as first program argument
}
I would recommend to study for inspiration the source code of GNU findutils or of GNU make.
I don't recommend modifying program arguments with e.g. some code like strcpy(argv[1], "bar"). It is not portable, perhaps forbidden, and certainly unreadable and brittle.
If you are on Linux, see also proc(5) about /proc/self/cmdline
I am writing a program A which on it's turn invokes arbitrary program B.
When invoking A, some arguments are required by A while some others should be redirected to B, but they are unknown for A.
How can I get A collect those arguments passed to it, however unrecognized
, into a dictionary maybe. So far, every time I use:
getopt_long_only(argc, argv, "...
or
getopt(argc, argv, "...
I am getting errors emitted for "unrecognized option" or "illegal option". And those are indeed unrecognized for A, but I want A to ignore that, do you think this is doable?
In general, the problem is extremely tricky, even intractable unless you set some ground rules for how your program is to be used.
You can suppress the automatic messages by setting opterr = 0; before you call your option parser. That, unfortunately, is the easy part.
Suppose you're given a command line:
wrapper_program -baxt cantaloupe -d designator
Further, suppose that neither -b nor -d is an option to the wrapper program. The difficulty is now determining whether the -b option takes an argument (in which case the argument is axt) or it does not. If -b doesn't take an argument, there are extra options starting with -a — but does that take an argument (which would be xt) or is the x also an option? And if x is an option, does that take an argument (which would be the t) or is the t an option too — and does that take an argument (which would be cantaloupe). If the first argument -baxt has an option with an argument attached, then do you want the cantaloupe option to end the argument parsing, or should the code do GNU-style argument permutation? If it should do argument permutation, does the -d option take an argument (designator) or is that a non-option argument?
You can set ground rules to sort this sort of thing out, but you have to think hard and code carefully — and test thoroughly. It is probably easier if you know whether the wrapped program takes long or short arguments.
You might find it better to demand that options for the wrapped program follow a double-dash:
wrapper_program -w wrapper-argument -- -b=axt -d designator cantaloupe
The idea is that the arguments to the wrapper program precede the -- and the arguments to the wrapped program follow it. This gives a clean, clear separation between the two sets of arguments.
An alternative is to have a 'pass-through' option (the C compilers often support this with notations such as -Wl,-arg-for-linker). For example, the -p option might take an argument which will be passed verbatim to the wrapped program:
wrapper_program -w wrapper-argument -p -b=axt -p -d -p designator cantaloupe
The -p options specify that the following argument should be passed to the wrapped program.
Using the -b=axt notation implies the use of getopt_long() rather than getopt(), though if -b takes an argument then the =axt option will be treated as the argument by getopt() whereas getopt_long() would, AFAIK, treat axt as the argument.
Be cautious about such designs. They're neither easy to write nor necessarily easy to use.
I have an assignment which tells me i need to accept arguments from the command line.
I know how to accept arguments from the command line, however this is what i need
I am told my arguments are as follows name_of_function name_of_variable argument1, arugment2
is there an easy way to map name_of_function to the name of the function and name_of_variable to the name of the global variable, without going strcmp on each of them ?
There is no tool or library that converts a string to the corresponding variable, function, or anything else in C. When you have e.g. a .NET runtime environment you could use reflection to see, if an object is in your program and to access it.
You will have to use strcmp or similar to interpret the command line arguments and decide how to deal with the commands.
I trying to emulate main() function like behavior for normal functions using string tokenizing and storing tokens in a NULL terminated char* array.
Every thing is fine except getopt(). It won't rearrange argv[0] coz it expects the first argument to be program name. But for my function the argv[0] isn't the program name. I want to make getopt() to also rearrange argv[0](non-option). How do I do that?
getopt(3) uses a global variable optind (option index) to track its progress through argv and initializes it to 1. Try setting optind = 0 before reading the options.
Try using
c = getopt(argc + 1, argv - 1, "xyz")
Edit: Which, as pointed out below, is a hack But I'd be interested to see a machine on which it didn't work.
Though the hack #Tom Tanner suggested worked for certain systems, it didn't compile for the target which I'm supposed to make it work. Another work around I found is to replace the first argument in my argv[] array with a dummy string and use getopt() with it.