Cant seem to access multiple options using getopt() for C [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
TL;DR - My issue is that I can't seem to get both options to work. Only '-n' is working. I also want '-h' to work.
I am trying to create a program that essentially prints out the last few letters of '.txt' or '.log' file. However, I am running into an issue using getopt(). I am trying to access the different cases using the command line, but I can only access the first case
I have already tried include the colon (:) after "nLh" however it ends up outputting a "segmentation fault" (core dumped)" error.
Ex1: ./print.out -h (fails)
What I pass in
./print.out -h
Expected output
Usage: ./print.out -n
Actual output
Segmentation fault (core dump)
Ex2: ./print.out -n 60 (Successful)
What I pass in
./print.out -n 60
Expected output
Random text file from a txt file ... Random text file from a txt file
Actual output
Random text file from a txt file ... Random text file from a txt file
if(argc >1)
{
while ((option =getopt(argc,argv,"nLh"))!=-1)
{
switch (option)
{
case 'n':
if( isExtensionTXTorLog && charactersRead >0)
{
}
else if( argc == 3 && !isExtensionTXTorLog)
{
}
else
{
exit(2);
}
break;
case 'L':
break;
case 'h':
printUsage();
break;
case '?':
exit(0);
break;
default:
break;
}
}
}
else
{
accessDefault(buffer);
return 0;
}

You're using optind in the wrong way. optind is used to get non-options argument after parsing all the options. To parse option with argument use n:, then read optarg variable
Take look at this minimal example:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char option;
int n_param;
while ((option =getopt(argc,argv,"n:h"))!=-1)
{
//Variable initialization
switch (option)
{
case 'n':
n_param = atoi(optarg);
printf("Param N: %d\n", n_param);
break;
case 'h':
printf("Help\n");
exit(0);
break;
case '?':
printf("Unrecognized option\n");
exit(0);
break;
default:
break;
}
}
for (int index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
Example:
./a.out ARG1 -n 50 ARG2
Output:
Param N: 50
Non-option argument ARG1
Non-option argument ARG2

Related

Wrong output when printing one of the elements in argv

I am writing a program that recurses through directories but came across a strange problem with my code. I compile and run the code with the following:
./sorter -c food -d thisdir -o thatdir
The following gives me a total argument count of 7. However when I try to check my inputs, I get unexpected results:
int main(int argc, char ** argv){
int checkInputs = checkFlags(argc,argv);
if(checkInputs == 1){
fileSearch(".");
}
else if(checkInputs == 2){
printf("arg counts %d\n",argc);
printf("%s\n",argv[4]);
fileSearch(argv[4]);
}
else if(checkInputs == 3){
printf("arg counts %d\n",argc);
printf("%s\n",argv[4]);
fileSearch(argv[4]);
}
return 0;
}
It returns the expected output when checkInputs is 2 but when it is 3 I get the following when I print argv[4]:
-d
The following is my checkInputs function, which may be causing this:
int checkFlags(int argc, char * argv[]) {
int output;
if(argc < 3){
printf("Not enough arguments\n");
output = 0;
return output;
}
else{
int options;
char * input = NULL;
while((options = getopt(argc,argv,"c:d::o::")) != -1){
switch(options) {
case 'c':
input = optarg;
//printf("Mandatory flag: %s\n",optarg);
output = 1;
break;
case 'd':
//printf("We have an optional %s\n",argv[4]);
output = 2;
break;
case 'o':
//printf("We have two optionals: -d: %s & -o: %s\n",argv[4],argv[6]);
output = 3;
break;
/* Probably don't need this case statement*/
case '?':
if(optopt == 'c'){
printf("Unknown option, -%c not present\n",optopt);
exit(0);
}
break;
}
}
}
return output;
}
Everything works fine however if the program is only compiled with the first 2 flags.
By debugging your code, I actually get a segmentation fault, when checkInputs == 2 and ./program -c hello -d. You should fix this, by adding a IF and check if a path is provided, for the option -d. Also keep in mind, that the sequence of the parameters can differ. You can save the extra options in a variable to access them out of the checkFlags function.
Executing ./program -c food -d thisdir -o thatdir outputs:
Mandatory flag: food
We have an optional thisdir
We have two optionals: -d: thisdir & -o: thatdir
arg counts 7
-o
It prints the expected.

Getopt not grabbing and storing my input in C

This is my first post on this site so please forgive any formatting errors.
I am coding a small program to get simple information from a file like amount of words, sorting it etc. However I started simply by using getopt since I want to use the command line to parse my commands. This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
int value = 0;
int main(int argc, char **argv) {
extern char *optarg;
extern int optind;
int c, err = 0;
int cflag = 0, sflag = 0, fflag = 0;
char *substring;
// usage from instructions in case of error
static char usage[] = "usage: mywords [-cs] [-f substring] filename";
// only f flag requires additional input
while ((c = getopt(argc, argv, "csf:")) != -1)
switch (c) {
case 'c':
cflag = 1;
break;
case 's':
sflag = 1;
break;
case 'f':
fflag = 1;
printf("Before assigning to substring\n");
substring = optarg;
printf("After\n");
break;
case '?':
err = 1;
break;
}
if (fflag = 1) {
printf("%c ", &substring);
}
}
I will then input something like this to the command line after I run my makefile (which runs successfully with no errors):
mywords -f test
and ideally the output would be
test
The printf statements I have in the fflag are simple test prints to see if I was even reaching there. Thank you for your help in advance.
EDIT
It was fixed. David Collins had the right answer. Thank you so much everyone
I have noticed three issues in you code. (There may be other small issues but addressing the following should get you up and running I think.)
Testing for equality
You should use if (fflag == 1) instead of if (fflag = 1).
Pointer de-referencing
If you want to retrieve the value of the character pointed to by substring, you would use *substring instead of &substring.
But you probably don't want to do this. See below.
printf() format specifiers
When printing a string / character array, use the %s specifier instead of %c. (%c is for single characters). So you should have
if (fflag == 1) {
printf("%s ", substring);
}
Or - more simply - just
if (fflag) {
puts(substring)
}
since any non-zero value evaluates to true in C (and you initialize fflag to zero at the start of your program).

Segmentation fault when parsing command line arguments

I am getting a segmentation fault I am having trouble isolating the source of the fault. I believe that for some reason argv and argc are not getting values, but I cannot figure out why.
Here is the first part of my code.
int main(int argc, char **argv)
{
int i;
int numArrays = 0;
int test = 0;
int opt = 0;
printf ("Parsing....\n"); // This line gets printed
printf(argv); // this one doesn't even if being flushed immediately after
printf(argc); // when the previous line is deleted, this line also won't print
fflush(stdout);
opt = getopt(argc, argv, optString); // defined as optString = "qmc";
while (opt != -1) {
printf (opt);
switch (opt) {
//prevents program from printing to a file
case 'q':
tofile = 1;
break;
// max size of the prime numbers
case 'm':
maxPrime = atoi(optarg);
break;
case 'c':
numProcs = atoi(optarg);
break;
default:
break;
}
}
I'm tried to figure out what is going on, but I cannot see why argc and argv are not getting values. I have used this exact same parsing code before and it has worked perfectly. Usually segmentation faults are pretty easy (accessing memory locations you shouldn't be), but there is no reason I shouldn't have access to my command line arguments.
You are confused about how to use printf. What you're currently doing is a big no-no:
printf(argv);
printf(argc);
The function expects a const char* string that specifies the format of the output and optional variable argument list. You are passing a double-pointer, which is not a string, and an integer, which is not even a pointer!
You want something like this:
printf( "Number of arguments: %d\n", argc );
for( int i = 0; i < argc; i++ ) {
printf( "Arg %d: %s\n", i, argv[i] );
}
Read up on printf here: http://en.cppreference.com/w/c/io/fprintf

getopt not working correctly when run from unix command line

I wrote (copied and pasted from Google and simplified) a C program to use getopt to print out the values of the arguments passed in from the Unix command line.
From Unix command line:
./myprog -a 0 -b 1 -c 2
My C code is:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int i;
while ((i = getopt(argc, argv, "abc")) != -1) {
switch (i) {
case 'a':
printf("A = %s\n", optarg);
break;
case 'b':
printf("B = %s\n", optarg);
break;
case 'c':
printf("C = %s\n", optarg);
break;
default:
break;
}
}
return 0;
}
I want to program to print out each of the values passed e.g.
A = 0
B = 1
C = 2
However it is not printing out anything at all.
You forget about ":" after any option with argument. If you will change one line
while ((i = getopt(argc, argv, "a:b:c:")) != -1) {
you will get working variant.
Read properly man 3 getopt, it said about third argument of getopt that
… optstring is a string containing the legitimate option characters. If such a character is followed by a colon, the option requires an argument, so
getopt() places a pointer to the following text in the same argv-element, or the text of the following argv-element, in optarg. Two colons mean an option
takes an optional arg; if there is text in the current argv-element (i.e., in the same word as the option name itself, for example, "-oarg"), then it is
returned in optarg, otherwise optarg is set to zero. …

Reading command line arguments for flags and files C

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

Resources