get optarg with getopt - c

I have the following code:
char opt;
int bla1,bla2,bla3;
char *myarg = NULL;
while((opt = getopt(argc,argv,"a:b:cd")) != -1)
{
switch (opt)
{
case 'a':
bla1 = atoi(optarg);
break;
case 'b':
myarg = optarg;
break;
case 'c':
bla2 = 1;
break;
case 'd':
bla3 = 1;
break;
default:
break;
}
}
I want to be able to use optarg for case 'b' but in case none is selected to get a default value. Right now requires arg and cannot bypass it and if I replace "b:" with "b" it ignores the argument.
How can I make it work in both situations?

Some but not all versions of getopt allow you to indicate that an argument is optional by putting two colons after the relevant option character.
Wanting an optional argument to an option is a sign that your program is complicated enough that you should consider supporting long option names. Unfortunately there is no standard function to do this, but GNU libc has two: getopt_long and the even more powerful argp. If your software is GPL-compatible, you can get either of them from gnulib and then you don't depend on glibc.

Related

C code setjmp declare functions?

I'm absolutely not a coder, but I'm trying to get a very old program to compile from fortran to C, so that I can play a game i've not played in 20+ years (originally created on HP3000 in the late 70s!) on my linux box.
Someone has written a make.sh file, using f2c (fortran to C) so that it can compile using GCC under linux, but that was done many moons ago.
I'm getting the following error message:
stubs.c: In function ‘exexc_’:
stubs.c:76:13: warning: implicit declaration of function ‘mmsa_’; did
you mean ‘memset’? [-Wimplicit-function-declaration]
case 'A': mmsa_(); break;
The relevant piece of code i.e. exexc function in stubs.c is:
#include <setjmp.h>
int setjmp(jmp_buf env);
void exexc_(name, i1, i2, i3, i4, i5, namelen)
char *name;
shortint *i1, *i2, *i3, *i4, *i5;
long namelen;
{
static jmp_buf env;
static int first = 1;
static char segment[6];
ipx[0] = *i1;
ipx[1] = *i2;
ipx[2] = *i3;
ipx[3] = *i4;
ipx[4] = *i5;
strncpy(segment, name, namelen);
if( ! first ) longjmp(env, 1);
if( first )
{
first = 0;
setjmp(env);
switch(segment[3]) {
case 'A': mmsa_(); break;
case 'B': mmsb_(); break;
case 'C': mmsc_(); break;
case 'D': mmsd_(); break;
case 'E': mmse_(); break;
case 'F': mmsf_(); break;
case 'G': mmsg_(); break;
case 'H': mmsh_(); break;
case 'I': mmsi_(); break;
case 'J': mmsj_(); break;
case 'K': mmsk_(); break;
case 'L': mmsl_(); break;
default:
fprintf(stderr, "Whoa, attempted to call segment %s\n", segment);
fflush(stderr);
exit(1);
}
fprintf(stderr, "Oops, segment %s didn't call next segment\n", segment);
fflush(stderr);
exit(2);
}
}
What do i need to change in the stubs.c file, so that 'case 'A': mmsa_()' function is declared? If it helps, then mmsa refers to another file i think mmsa.c in the same local directory.
Happy to give more info if you need it. I've not played this game in over 20+ years(!), so any help would be gratefully received.
this is "just" a warning, and the function call doesn't have any parameters, nor any return value is retrieved, so it should be safe to write:
void mmsa_(void);
void mmsb_(void);
...
and so on.
And if you have header files declaring those functions, it's even better as you can include them instead of declaring them directly.
of course you have to link with libraries or objects containing the code of mmsa_ and other functions, or you'll get a link error (the problem would be just moved to the link phase)
as an aside: consider refactoring your code to remove the K&R old-style parameter declaration which is very much outdated and error prone.

switch-case automatic break

Are there any C compilers with extensions that provide the ability to automatically break at the end of each case statement (similar to what Swift has available) or an alterate switch available in a future C spec?
Mostly interested in this to avoid clutter in extensive switch-case scenarios.
I find this works "ok" but would prefer something clearer about the behavior.
#define case break; { } case
#define switch_break switch
switch_break (action)
{
default: printf ("Unknown action");
case action_none : // Nothing
case action_copy : doCopy ();
case action_paste : doPaste ();
case action_none : break; /* C requires a statement after final case */
}
If you hate writing break everytime, wrap the switch statement inside a function. Then break can be replaced with return statements. For example
int switch_func(char c) {
switch(c) {
case 'a': return 1;
case 'b': return 3;
case 'c': return 5;
case 'd': return 7;
. . .
default: return 0;
}
}
Reduces code only if return values are present.

Can't read arguments with getopt_long

I have the code below.
But when I run it with --debug=2, the debug variable gets value 100. I 'd expect 2...
Where is my mistake?
Here the code:
int debug=0;
int opt;
struct option longopts[] = {
{ "debug", required_argument, &debug, 'd' }
};
while ((opt = getopt_long(argc, argv, "d", longopts, NULL))!= -1)
{
switch (opt)
{
case 'd':
switch (debug)
{
case 1:
logPrio = LOG_INFO;
printf("1");
break;
case 2:
printf("2");
logPrio = LOG_CRIT;
break;
}
}
}
printf ("--%d--", debug);
Specifying &debug in longopts doesn't store the integer value of the option to the specified address, getopt_long expects you to extract integer values yourself.
According to the manual, the int *flag member of struct option does something completely different:
flag "specifies how results are returned for a long option. [If
non-NULL], getopt_long() returns 0, and flag points to a variable
which is set to val if the option is found, but left unchanged if
the option is not found.
You specify &debug for flag and 'd' for val, so debug gets set to 'd' (the number 100) when --debug is specified. Since you're already storing the result of getopt_long into the opt variable, you don't need to store &debug in longopts at all. Instead, use the optarg variable to get the argument to --debug:
case 'd':
debug = atoi(optarg);
switch (debug) {
...

My book says to make a program that tracks the amount of money a power user owes to the company using only switch statements

It had the same syntax error at all places marked with double forward slash, syntax error was "case label does not reduce to integer constant"
I can't use if statements because my book is dumb and hates if statements (but only in the switch statement chapter)
#include <stdio.h>
int main()
{
double price;
int power;
char user,hrs;
printf("Enter what kind of consumer (R for residential, C for commercial, I for industrial): ");
scanf("%c",user);
printf("Enter amount of kilowatt hours used: ");
scanf("%d",power);
switch(user)
{
case 'R':
case 'r':
price=6.00+.052*power;
break;
case 'C':
case 'c':
switch(power)
{
case (power>1000): //
price=60.00+(power-1000)*.045;
case power<=1000: //
price=60.00;
}
break;
case 'I':
case 'i':
{
printf("Hours (P for peak, O for off-peak):");
scanf("%c",hrs);
switch(hrs)
{
case 'P':
case 'p':
switch(power)
{
case power>1000: //
price=76.00+.065*(power-1000);
break;
case power<=1000: //
price=76.00;
break;
}
case 'O':
case 'o':
switch(power)
{
case power>1000: //
price=40.00+.028*(power-1000);
break;
case power<=1000: //
price=40.00;
break;
}
break;
default:
printf("Business hour ID not recognized; try again");
break;
}
}
break;
default:
printf("Consumer ID not recognized; try again");
break;
}
printf("Price is %f", price);
return(0);
}
The expressions in your case statements must be constants like 'p', not expressions like power>1000.
If you need to do expressions like power>1000, you should use if/else structures to handle all appropriate cases.
The value of a case statement must be a constant integer.
You are free to use chars (e.g. 'a', 'x', etc) because they will be converted to integers by the compiler (using their ASCII code).
Using any other type of constant will yield unexpected and probably unpleasant results.
Besides, the compiler will complain (and rightly so) if you use the same value in two different case statements. This can be trickier than it seems. For instance :
#define WHATEVER 1
switch (xxx)
{
case 1 : return 1;
case WHATEVER : return 10; // error: duplicate case value
}
Frankly I don't think your exercise is such a good illustration of the practical use of a case statement.
99% of the times, the case values will come from an enumerated type, like for instance:
typedef enum {
CMD_START,
CMD_STOP
} Command;
function process_command (Command c)
{
switch (c)
{
case CMD_START:
do_start();
break;
case CMD_STOP:
do_stop();
break;
default:
panic ("unknown command %d", c);
}
}
When you switch on power, the case targets must be constants.
Since you are actually only interested in the binary outcome of power>1000, you can apply the switch to that:
switch(power>1000)
{
case 1:
price=76.00+.065*(power-1000);
break;
default:
price=76.00;
break;
}
The exercise is meant for you to understand that using a switch this way is very close to if-else. However, only do this to satisfy an academic exercise. No one would actually want to maintain code written this way. It is more natural to use if-else:
if(power>1000)
{
price=76.00+.065*(power-1000);
}
else
{
price=76.00;
}

Is this a good practice to validate menus?

i need to show a menu that derive another menu and this derive another menu.
But i'm validating those menus with this form: (Only C standard library)
do{
validOption = 1;
printf("Option #1\n");
printf("Option #2\n");
printf("Option #3\n");
scanf("%i",&option);
switch(option){
case 1: /* Do something */ break;
case 2: /* Do something */ break;
case 3: /* Do something */ break;
default: validOption = 0; printf("Invalid Option\n"); break;
}
}while(!validOption);
But at the time of derive a menu i dont know if use the same option variable and validOption flag.
I think that is not a problem since the derived option variable is going to be overwritten and
I will not need the previous option variable since that option variable has been used for its only
purpose that is join in a specific case.
Now, validOption flag is not a problem too, since when a successfully case occurs means that validOption = 1 (will not iterate more)
and it will match with the previous validOption that have a value of 1 (since has been joined in a case). So will not interfere.
Is a good practice to use the same variables (option, validOption) within derived menus?
Also i need to validate with a getint() function, which make me think that if
is even necessary validate menus seeing it in a practical way.
#include<stdio.h>
int main(){
int option;
int validOption;
do{
printf("Option #1\n");
printf("Option #2\n");
printf("Option #3\n");
scanf("%i",&option);
switch(option){
case 1:
validOption = 1;
do{
printf("Option #1\n");
printf("Option #2\n");
printf("Option #3\n");
scanf("%i",&option);
switch(option){
case 1: validOption = 1; /* Another menu with the same option and validOption variables */ break;
case 2: validOption = 1; /* Do something */ break;
case 3: validOption = 1; /* Do something */ break;
default: validOption = 0; printf("Invalid Option\n"); break;
}
}while(!validOption);
break;
case 2: validOption = 1; /* Do something */ break;
case 3: validOption = 1; /* Do something */ break;
default: validOption = 0; printf("Invalid Option\n"); break;
}
}while(!validOption);
return 0;
}
//I've put validOption = 1; within all cases just for explaining purposes
I would rather call it nested loop than derived.
Coming to your question: Is it valid to re-use same variable within a loop when the 1st value of the variable is no longer needed? (Am I right in rephrasing your question?)
Yes, it's valid. While there's nothing technically wrong with it, I would say No. Because, it causes unnecessary confusion and makes the code readability difficult especially when you it within the same loop (as you do within your outer loop). It becomes even harder as the code base grows. Hence, I would discourage such a coding practice.
You want to validate your integer: Since, you are only going to do pass-by-value (to getint()), there's no problem in using another variable. You can use option1 and option2
Pass the values to getint() to validate it.

Resources