I have an assignment in C that requires options to be read in for different forms of a program. Before I start on that, though, I want to make sure that the getopt portion is working fine. However, the program keeps dropping the last parameter and I don't know why. Whenever I enter the last char, the program goes to the default value that kills the program. Any help is appreciated!
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main(int argc, char **argv)
{
int sFlag = 0;
int lFlag = 0;
int dFlag = 0;
int rFlag = 0;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "slr:")) != -1)
{
switch(c)
{
case 's':
sFlag = 1;
break;
case 'l':
lFlag = 1;
break;
case 'r':
rFlag = 1;
break;
default:
printf("unknown parameter introduced");
exit(-1);
break;
}
}
printf("s = %i, l = %i, d = %i, r = %i", sFlag, lFlag, dFlag, rFlag);
return 1;
}
The colon symbol after r in "slr:" tells getopt() to wait for a mandatory argument which follows -r.
Examples:
getopt(argc, argv, "slr:") can parse ./project -s -l -r r_arg (or ./project -r r_arg -s etc.)
getopt(argc, argv, "s:lr:") can parse ./project -s s_arg -l -r r_arg
getopt(argc, argv, "s:lr:") can also parse ./project -s -l -r r_arg with no error, but the program works differently from user's expectation. This is because getopt() expects -s to be followed by its argument, however it looks like, so the next argument -l is consumed and will not hit your switch(c).
Related
Hi I am working on a Program in a book. The Program is working almost as it is supposed to, except for one mistake. Every time I try to use the "-l" case I get a Segmentation Fault. Any Ideas?
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char *lieferung = "";
int knusprig = 0;
int zahl = 0;
char ch;
while ((ch = getopt(argc, argv, "l : k")) != EOF){
switch (ch) {
case 'l':
lieferung = optarg;
break;
case 'k':
knusprig = 1;
break;
default:
fprintf(stderr, "Unbekannte Option: '%s'\n", optarg);
return 1;
}
}
argc -= optind;
argv += optind;
if (knusprig)
puts("Knuspriger Rand.");
if (lieferung[0])
printf("Zu liefern: %s.\n", lieferung);
puts("Zutaten:");
for (zahl = 0; zahl < argc; zahl++)
puts(argv[zahl]);
return 0;
}
Thanks in advance.
The third argument get getopt shouldn't contain any spaces. Because there are spaces, it reads this argument as "-l takes no argument, -(space) takes an argument, -(space) takes no argument, and -k takes no argument.
Since getopt doesn't expect -l to pass an argument, optarg is set to NULL, which you then subsequently assign to lieferung. You then dereference that variable, resulting in the segfault.
Git rid of the spaces in the format string:
while ((ch = getopt(argc, argv, "l:k")) != EOF){
I think the format is incorrect. Replace "l : k" with "l:k".
I am working on trying to take in command line arguments. If I want to have multiple optional command line arguments how would I go about doing that? For example you can run the program in the following ways:
(a is required every instance but -b -c -d can be given optionally and in any order)
./myprogram -a
./myprogram -a -c -d
./myprogram -a -d -b
I know that getopt()'s third argument is options. I can set these options to be "abc" but will the way I have my switch case set up causes the loop to break at each option.
The order doesn't matter so far as getopt() is concerned. All that matters is your third argument to getopt() (ie: it's format string) is correct:
The follow format strings are all equivalent:
"c:ba"
"c:ab"
"ac:b"
"abc:"
In your particular case, the format string just needs to be something like "abcd", and the switch() statement is properly populated.
The following minimal example¹ will help.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char **argv)
{
int aflag = 0;
int bflag = 0;
char *cvalue = NULL;
int index;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "abc:")) != -1)
{
switch (c)
{
case 'a':
aflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'c':
cvalue = optarg;
break;
case '?':
if (optopt == 'c')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
}
printf ("aflag = %d, bflag = %d, cvalue = %s\n",
aflag, bflag, cvalue);
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
¹Example taken from the GNU manual
I need to use getopt to parse the following command:
./center -n name –cp Anumber –i Anumber –t Anumber –s Anumber -fc nameOfaFile
All of them can be given out in any order.
So its clear i have to use getOpt.
So i have been investigation and this is what i have so far
void check_parameters (int argc, char** argv) {
int opt;
while((opt = getopt(argc, argv, "n:cp:i:c:fc:")) != -1) {
printf("give me opt %c \n", opt)
swicth(opt){
case 'n' :
//do something
case 'cp' :
//do something
case 'i' :
//do something
}
}
}
I do know for a fact that the 3 parameter: the OptString is where i tell getOpt what are the char of the options it should expect
Also in optarg is where the argument is
its not working!
when i printf( "give me opt %c", opt ) its giving me the numbers, not the char!
for this reason it does not work. it does not check the parameters correctly
Edit:
After doing man 3 getopt
the return value of getopt is: If an option was successfully found, then getopt() returns the option character. If all command-line options have been parsed, then getopt() returns -1.
it returns the option character? it always return integer 1. always! i don't understand how getopt works. how does the switch compare to characters?!
First of all, this:
case 'cp':
...makes no sense. You can't represent two characters with a char or int. Besides, if running your program with -cp 101, getopt will treat it as -c p 101, for a completely different result. If you want to use long options, use getopt_long instead and the appropriate calling syntax, per example: ./a.out -n 42 --cp 101.
Now, here's a working example of getopt() in action:
#include <stdio.h>
#include <getopt.h>
int main(int argc, char* argv[]) {
int opt;
while((opt = getopt(argc, argv, "n:cp:i:c:fc:")) != -1) {
switch (opt){
case 'n':
printf("n was %s\n", optarg);
break;
case 'i':
printf("i was %s\n", optarg);
break;
}
}
return 0;
}
getopt handles only single-character option names, not things like -cp or -fc (which it interprets as multiple option flags in a single string: -c -p, -f -c). If you want to stick to the syntax you defined, then it's easier to just roll your own:
// first check whether argc is odd, then:
for (i = 1; i < argc; i += 2) {
if (strcmp(argv[i], "n") == 0) {
name = argv[i+1];
} else if (strcmp(argv[i], "cp") == 0) {
// etc. etc.
}
}
I'm trying to scan the command line for certain letters, symbols and values. I want to scan for "-w", a number, and "-s". I got a response in my last question, I was told to use getopt() and after a little bit of Googling, I think I might get it, but I'm not sure.
This is what I think I'm doing:
int c = 0;
int b = argv[2];
while((c = getopt(argc, argv, "-w", "-s", b))
I think I'm scanning argc for "-w", "-s" and the argv[2] value (which is the number). But I do not know if I am using it correctly?
Your while loop should be
while ((c = getopt(argc, argv, "w:s:"))
: the colon means it needs an argument. now convert optarg to an integer or whatever you wanted.
int number = 0;
int sflag = 0;
int opt;
while ((opt = getopt(argc, argv, "w:s")) != -1)
{
switch (opt)
{
case 's':
sflag = 1;
break;
case 'w':
number = atoi(optarg);
break;
default:
/* Report usage and exit? */
break;
}
}
The conversion on the number is lazy; you can do more a more careful job calling a function that calls strtol(), for instance. You might need to have a wflag variable that you set analogously to the sflag variable so that you can distinguish -w 0 from 'no -w option specified on the command line'.
Hello I'm new with C and I'm trying to start this lab where the command syntax is to first list any command line flags then list one or more file names.
I'm having trouble organizing how I want to scan the input arguments and differentiating them between flags and file names.
I thought of doing a loop to see if the argument is a flag or file name. But I'm unsure how to begin implementing it. Since the first 4 arguments can be potential flags in any order then anything after is the file name. But it is also possible for no flags to be given and just start with filenames. I don't know at all how to initalize this loop to go through each argument 1 by 1. Can anyone help please?
Example of possible command line arguments:
wc fcopy.c head.c (no flags given just file names)
wc -l -c -w -L fcopy.c head.c a.exe (flags given and multiple files)
wc -l -w -c -L fcopy.c (flags given and 1 file name)
Reading command line args one by one is pretty simple:
int main( int argc, // Number of strings in array argv char *argv[])
The two basic args to a C function are argc (int number of args), and argv (an array of strings for the args)
The first string is always the name of the program that is running, after that is the args that were passed over the command line.
if(argc > 1)
for( count = 1 count < argc; count++ )
printf("%s", argv[count]);
Will display to the screen each of the arguments passed in past the name of the calling program.
I assume your flags are passed with a "-" as the first character? If so, you can check the contents of the first character in each string for a '-' to tell if its a flag or not.
You can use getopt()
Check these questions:
Parsing command-line arguments?
Handling command line options before and after an argument in C
Argument-parsing helpers for C/UNIX
Getopt shift optarg
Check out getopt, it allows you to parse command line arguments and their flags:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char **argv)
{
int aflag = 0;
int bflag = 0;
char *cvalue = NULL;
int index;
int c;
opterr = 0;
while ( (c = getopt (argc, argv, "abc:")) != -1 )
switch (c) {
case 'a':
aflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'c':
cvalue = optarg;
break;
case '?':
if (optopt == 'c')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
printf ("aflag = %d, bflag = %d, cvalue = %s\n",
aflag, bflag, cvalue);
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
Example of Parsing Arguments with getopt
Also see http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html