getopt only reads in only the first command - c

I have a question regarding the behavior of my getopt function.
My code looks like this:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int opt;
while((opt = getopt(argc, argv, "gi:o:ctp")) != -1) {
switch(opt) {
case 'i':
printf("entered i\n" );
break;
case 'o':
printf("entered o\n" );
break;
}
}
return 0;
}
However when I entered ./run -i in -o out, it only prints out entered i and stops.
Could anyone help me out?

You need to pass another argument to -i and -o because a colon follows those letters in the optstring.
Like this:
./run -i in -o out
Alternatively, you could make the arguments' arguments optional by adding additional colons in the optstring:
while((opt = getopt(argc, argv, "gi::o::ctp")) != -1) {

Related

Check for specific command line arguments and then assign them to variables

Obligatory total noob here.
I am making a simple C program that reads some variables from a file from a simple function.
What I'm trying to accomplish, however, is to allow whoever calls the program to override the values read from the file if hey so specify in the command line arguments.
I would like to have something like this:
char* filename;
int number;
...
readConfig(filename, number, ...);
if (argc > 1) {
// Check if the variables were in the args here, in some way
strcpy(filename, args[??]);
number = atoi(args[??]);
}
I would like the program to be called as
program -filename="path/to/file.txt" -number=3
I figured out I could just tokenize each argument and match it to every assignable variable and discard the others, but I'm pretty sure that there's a more elegant way to do this (perhaps with getopts?)
Thank you so much for your help.
I found this on geeksforgeeks:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int opt;
// put ':' in the starting of the
// string so that program can
//distinguish between '?' and ':'
while((opt = getopt(argc, argv, ":if:lrx")) != -1)
{
switch(opt)
{
case 'i':
case 'l':
case 'r':
printf("option: %c\n", opt);
break;
case 'f':
printf("filename: %s\n", optarg);
break;
case ':':
printf("option needs a value\n");
break;
case '?':
printf("unknown option: %c\n", optopt);
break;
}
}
// optind is for the extra arguments
// which are not parsed
for(; optind < argc; optind++){
printf("extra arguments: %s\n", argv[optind]);
}
return 0;
}
So, when you pass -f, you need to also pass filename, like: ./args -f filename it will say:
$ ./a.out -f file.txt
filename: file.txt
When you pass -i, -l, or -r, or -ilr, it will say:
$ ./a.out -ilr
option: i
option: l
option: r
If you pass -f but without a filename, it will say option needs argument. Anything else will be printed to extra arguments
So, with it, you can add options to getopts, add new case, do a thing, like:
getopts(argc, argv, ":fn:")
-f filename, -n number, pretty easy

Segmentation fault in atoi command

I have the following code:
int main(int argc, char *argv[])
{
int value,direction=0;
char c;
printf ("go\n");
while((c = getopt(argc, argv, "wr:")) != -1) {
printf ("go\n");
printf("%c\n",c);
switch(c) {
case 'w':
printf ("go\n");
value=atoi(optarg);
printf ("go\n");
printf("The input value is %x",value);
direction=1; //1 for write
break;
case 'r':
direction=0; // 0 for read
break;
default:
printf("invalid option: %c\n", (char)c);
usage();
return -1;
}
}
}
Now when i run the program by writing
./spicode.out -w 25
I need to pick the 25 after w using optarg, but its producing a segmentation fault.
What am i doing wrong?
You should put colon between commandline options.
c = getopt(argc, argv, "w:r")
From gnu.org :
An option character in this string can be followed by a colon (‘:’) to
indicate that it takes a required argument
Therefore wr: becomes w:r

getopt isn't working for one argument

This is just a simple program I wrote in order to get some practice with getopt, and structs.
typedef struct {
int age;
float body_fat;
} personal;
typedef struct {
const char *name;
personal specs;
} person;
int main(int argc, char *argv[])
{
char c;
person guy;
while((c = getopt(argc, argv, "n:a:b:")) != -1)
switch(c) {
case 'n':
guy.name = optarg;
break;
case 'a':
guy.specs.age = atoi(optarg);
break;
case 'b':
guy.specs.body_fat = atof(optarg);
break;
case '?':
if(optopt == 'a') {
printf("Missing age!\n");
} else if (optopt == 'b') {
printf("Missing body fat!\n");
} else if (optopt == 'n') {
printf("Missing name!\n");
} else {
printf("Incorrect arg!\n");
}
break;
default:
return 0;
}
printf("Name: %s\nAge: %i\nFat Percentage: %2.2f\n",
guy.name, guy.specs.age, guy.specs.body_fat);
return 0;
}
Everything works just fine except for the 'b' option. For some reason specifying that one doesn't change anything. It always returns as 0.0. I don't get why this would be if the other args work just fine.
Your example is missing the header files which would declare the corresponding prototypes. Adding these
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
makes it work for me. I also changed the type for c to int (a char will not hold a -1), and did a
memset(&guy, 0, sizeof(guy));
just to ensure it was a known value. Compiler warnings are your friend. I used this (a script named gcc-normal) to apply warnings:
#!/bin/sh
# $Id: gcc-normal,v 1.4 2014/03/01 12:44:54 tom Exp $
# these are my normal development-options
OPTS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wconversion"
${ACTUAL_GCC:-gcc} $OPTS "$#"
Though the RCS-identifier is fairly recent, it is an old script which I use in builds.

Using getopt with no arguments

By default I want the program will read input from stdin and send it's output to stdout.
The -f option will cause the
program to read the input from a text file and the -o option will cause the program to write the
output to a file instead of stdout.
The –c if specified will display the output in a CSV format (either in stdout or to a file depending if -o is specified).
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
int main(int argc, char * argv[]){
char opt;
char *filename_in, *filename_out;
int i, flagC=0,flagF=0,flagO=0;
while((opt = getopt(argc,argv,"cf:o:")) != -1){
switch(opt){
case 'c':
flagC=1;
break;
case 'o':
flagO=1;
filename_out = optarg;
break;
case 'f':
flagF=1;
filename_in = optarg;
openFile(filename_in);
break;
case '?':
printf("Opt ?");
return 0;
default:
printf("Opt Default");
return 0;
}
}
if((flagC==0) && (flagO==0) && (flagF==0)){
// puts("Please enter a string:");
}
for (i = optind; i < argc; i++)
printf("%s ", argv[i]); //prints anything without argument and space between
return 0;
}
Is there a better way to read input from stdin aside from checking each flag I created is set to 0?
char input[100];
if((flagC==0) && (flagO==0) && (flagF==0)){
// puts("Please enter a string:");
// scanf("%s", &input);
}

Linux C getopt ignore after the first unspecified argument

I wanted to make the program accomplish "execvp(argv[1],argv+1);" if the first argument is undefined, but getopt parsing all arguments starting with "-". How to ignore all the arguments after the first undefined argument? Is this possible using getopt? Currently, I have code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
void print_usage() {
printf("Usage: here print usage\n");
}
int main(int argc, char *argv[]) {
int option = 0;
char user[32]={0}, command[50]={0};
while ((option = getopt(argc, argv,"c:u:h")) != -1) {
switch (option) {
case 'c' : strcpy(command,optarg);
break;
case 'u' : strcpy(user,optarg);
break;
case 'h' : print_usage();
exit(EXIT_SUCCESS);
break;
default:
print_usage();
exit(EXIT_SUCCESS);
}
}
if(strlen(user)!=0) {
if (strlen(command)!=0)
printf("execute %s for %s\n",command,user);
else
printf("please specify command\n");
}
else {
if (strlen(command)!=0)
printf("please specify user\n");
else if (argc > 2)
printf("execute %s for everyone\n",argv[1]);
}
return 0;
}
When you execute, I got:
./thisprogram ls -l
./thusprogram: invalid option -- 'l'
I would like to make like this;
./thisprogram ls -l /
razem 52
lrwxrwxrwx 1 root root 7 05-31 20:40 bin -> usr/bin
drwxr-xr-x 5 root root 4096 10-21 22:44 boot
drwxr-xr-x 19 root root 3160 11-02 17:10 dev
and so on... but I have no idea.
Just stop parsing when you encounter an unknown argument.
int done = 0;
while (!done && (option = getopt(argc, argv,"c:u:h")) != -1) {
switch (option) {
...
default:
done = 1;
break;
}
}
(or if you want, , use case '?': instead of the default: case,as getopt returns '?' when it encounters an unknown argument)

Resources