I am working on a simple decimal to hex/binary calculator that will take command line arguments to specify which to convert to, -x for hex and -b for binary. I am using getopt() to parse in values.
I am having a couple issues namely how to work with multiple arguments after one option. My code (as of now) is as follows
int main(int argc, char *argv[]){
int opt;
int num;
while((opt = getopt(argc, argv, ":x:b:")) != -1){
switch(opt){
case 'x':
num = atoi(optarg);
dec_to_hex(num);
break;
case 'b':
num = atoi(optarg);
dec_to_bin(num);
break;
case'?':
print_usage();
break;
case ':':
print_usage();
break;
default:
print_usage();
}
}
return 0;
}
For example, if I call ./a.out -b 1234 4321
I want to call my dec_to_bin fucntion first one 1234, then on 4321.
I would also like to print usage if no/incorrect options are given. If I call ./a.out 1234
or ./a.out -x -p 1234
it should print usage.
I have tried working with a while loop in the switch statement cases like this,
case 'x':
while(optind < argc){
num = atoi(argv[optind++]);
dec_to_hex(num);
}
But that still will only print the first conversion. I also thought the return of '?', ':' or defualt would cover my incorrect/no options given. I am pretty stumped and would love any help. Thanks!
Options conventionally only take zero or one arguments. For your code, you really want the option to set the mode in which your program operates; for that you don't need arguments to the options. After deciding on the operating mode, you can iterate over all the non-option arguments, performing the appropriate conversion.
Something like this:
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#define CONV_DEC_TO_HEX 0
#define CONV_DEC_TO_BIN 1
char *prog_name;
void dec_to_hex(int num) {
printf("0x%x\n", num);
}
void dec_to_bin(int num) {
printf("0b%b\n", num);
}
void print_usage(FILE *out) {
fprintf(out, "usage: %s [-xb] arg1 [...argn]\n", prog_name);
}
int main(int argc, char *argv[]){
int opt;
int num;
int conv = -1;
prog_name = argv[0];
while((opt = getopt(argc, argv, "hxb")) != -1){
switch(opt){
case 'x':
conv = CONV_DEC_TO_HEX;
break;
case 'b':
conv = CONV_DEC_TO_BIN;
break;
case 'h':
print_usage(stdout);
exit(0);
default:
print_usage(stderr);
exit(2);
}
}
if (conv == -1) {
fprintf(stderr, "ERROR: please select one of -x or -b\n");
print_usage(stderr);
exit(2);
}
for (int i=optind; i<argc; i++) {
int arg = atoi(argv[i]);
switch(conv) {
case CONV_DEC_TO_HEX:
dec_to_hex(arg);
break;
case CONV_DEC_TO_BIN:
dec_to_bin(arg);
break;
}
}
return 0;
}
With no arguments:
$ ./calc
ERROR: please select one of -x or -b
usage: ./calc [-xb] arg1 [...argn]
With invalid arguments:
$ ./calc -z
./calc: invalid option -- 'z'
usage: ./calc [-xb] arg1 [...argn]
With valid arguments:
$ ./calc -x 123 234 345
0x7b
0xea
0x159
$ ./calc -b 123 234 345
0b1111011
0b11101010
0b101011001
And like all good programs, asking for help (with ./calc -h
) outputs to stdout instead of stderr.