Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] getopt() only catching first parameter

Status
Not open for further replies.

enjunear

Advanced Member level 3
Joined
Dec 21, 2010
Messages
960
Helped
309
Reputation
618
Reaction score
303
Trophy points
1,343
Location
USA, midwest
Activity points
9,749
I'm working on a C program for a class and having trouble with the getopt routine at the front of the program. Here is that section of code:

Code:
    int i, done;

    opterr = 0;
    while ((i = getopt(argc, argv, "pft")) != -1)
    {
        switch (i)
        {
            case 't':
                // this is a test flag to show how the flags work
                // this will print out the parms
                printf("%s\n", argv[optind]);
                break;
            
            case 'p':
                // add code for the p flag set
                port_num = atoi(argv[optind]);
                break;
            
            case 'f':
                // add code for the f flag set
                break;
            
            case '?':
            default:
                done = 1;
                break;
        }
        
        if (done) break;
    }
If I run the program with flags -p 2000 -t foo, it only processes 'p', and skips all arguments after that. Also, if you run with -t foo -p 2000, it processes the 't', but skips the 'p'.

I figure this is something straightforward, I'm just not seeing the issue. I can't do a live debug, because the app needs to be compiled and run on a remote system.

Ideas? TIA
 

Hi,

One possible problem is you do not have a colon following each option requiring an arguement in the parameter list:

The options argument is a string that specifies the option characters that are valid for this program. An option character in this string can be followed by a colon (‘:’) to indicate that it takes a required argument. If an option character is followed by two colons (‘::’), its argument is optional; this is a GNU extension.

After the first pass through the CASE statement, the second pass retrieves the numerical argument passes through the CASE statement and hits the default: case terminating the loop.

Example:

Code:
#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;
     }

Code:
    % testopt
     aflag = 0, bflag = 0, cvalue = (null)
     
     % testopt -a -b
     aflag = 1, bflag = 1, cvalue = (null)
     
     % testopt -ab
     aflag = 1, bflag = 1, cvalue = (null)
     
     % testopt -c foo
     aflag = 0, bflag = 0, cvalue = foo
     
     % testopt -cfoo
     aflag = 0, bflag = 0, cvalue = foo
     
     % testopt arg1
     aflag = 0, bflag = 0, cvalue = (null)
     Non-option argument arg1
     
     % testopt -a arg1
     aflag = 1, bflag = 0, cvalue = (null)
     Non-option argument arg1
     
     % testopt -c foo arg1
     aflag = 0, bflag = 0, cvalue = foo
     Non-option argument arg1
     
     % testopt -a -- -b
     aflag = 1, bflag = 0, cvalue = (null)
     Non-option argument -b
     
     % testopt -a -
     aflag = 1, bflag = 0, cvalue = (null)
     Non-option argument -

This example can be found at Using GETOPT


Hope this helps with your endeavor.
 

I'm working on a C program for a class and having trouble with the getopt routine at the front of the program. Here is that section of code:

Code:
    int i, done;

    opterr = 0;
    while ((i = getopt(argc, argv, "pft")) != -1)
    {
        switch (i)
        {
            case 't':
                // this is a test flag to show how the flags work
                // this will print out the parms
                printf("%s\n", argv[optind]);
                break;
            
            case 'p':
                // add code for the p flag set
                port_num = atoi(argv[optind]);
                break;
            
            case 'f':
                // add code for the f flag set
                break;
            
            case '?':
            default:
                done = 1;
                break;
        }
        
        if (done) break;
    }
If I run the program with flags -p 2000 -t foo, it only processes 'p', and skips all arguments after that. Also, if you run with -t foo -p 2000, it processes the 't', but skips the 'p'.

I figure this is something straightforward, I'm just not seeing the issue. I can't do a live debug, because the app needs to be compiled and run on a remote system.

Ideas? TIA

if you check your code you have written
Code:
 int i,done;

do you know what exactly the value of done ??? No that is why when you do
Code:
 if(done) break;
the loop breaks and only parses one argument.

just change to
Code:
 int i,done=0;
it will do the job.

Hope it helps.
 

I messed up a critical line when I first copypasta'd the code. "done" is initially set to 0, so it's not tripping out of the while loop on the first pass due to that. Here's the whole top part of the program where the issue lies, and two screen-dumps from two test cases showing the "processes the first flag, but not the second" issue.

Thanks for the replies... sadly, I'm still not following what getopt() wants to see in the incoming argument vector.

Code:
/*
 *******************************************************************************
 *
 *  tcp_client.c --
 *    program to send packets to a server (default port 2000)
 *
 *******************************************************************************
 */

#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>

/*
 *  Initialize the socket address info struct.
 */

struct sockaddr_in sock_in, temp, from_addr;
int    from_len;

#define PORT 2000

extern    int    errno;

main(argc, argv)
int    argc;
char    **argv;

{
    struct timeval     timeout;
    register int     n;
    u_short     len;
    char         *cp;
    int         i, j, retry, resplen, done = 0;
    int         dsmask, flags, sockFD, port_num = PORT;
    char        buf[100],answer[4048];
    char        hostname[100];
    struct    hostent    *h_name;
    struct    servent    *s_name;

    int         numTimeOuts    = 0;

    sockFD = -1;
    strcpy(hostname, "spock.ee.iastate.edu");

    opterr = 0;
    printf("argc = %u\n", argc);
    for (i=0 ; i<argc; i++)
        printf("argv[%u] = %s\n", i, argv[i]);
    
    while ((i = getopt(argc, argv, "hpft")) != -1)
    {
        printf("argument = %c\n", i);

        switch (i)
        {
            case 'h':
                strcpy(hostname, argv[optind]);
                printf("Got hostname = %s\n", hostname);
                break;
            case 't':
                // this is a test flag to show how the flags work
                // this will print out the parms
                printf("%s\n", argv[optind]);
                break;
            case 'p':
                // add code for the p flag set
                port_num = atoi(argv[optind]);
                printf("Got portnum = %u\n", port_num);
                break;
            case 'f':
                // add code for the f flag set
                printf("Got to 'f' flag\n");
                break;
            case '?':
            default:
                printf("Got to DEFAULT case.\n");
                done = 1;
                break;
        }
        printf("done with switch\n");
        if (done) printf("done\n");
        if (done) break;
    }
    
    printf("out of switch, i=%i\n", i);
    
    strcpy(buf,"hello there\n");

    h_name = gethostbyname(hostname);
    sock_in.sin_family = AF_INET;
    .
    .
    .
Run code using: ./tcp_client -h bones -p 9999
Screen dump
Code:
argc = 5
argv[0] = ./tcp_client
argv[1] = -h
argv[2] = bones
argv[3] = -p
argv[4] = 9999
argument = h
Got hostname = bones
done with switch
out of switch, i=-1
port = 2000 -- 129.186.215.41 **COMMENT .41=bones**
Run code using: ./tcp_client -p 9999 -h bones
Screen dump
Code:
argc = 5
argv[0] = ./tcp_client
argv[1] = -p
argv[2] = 9999
argv[3] = -h
argv[4] = bones
argument = p
Got portnum = 9999
done with switch
out of switch, i=-1
port = 9999 -- 129.186.215.40 **COMMENT .40=spock, default**
----------------------- Edit ----------------------------
Got it figured out. Thanks for the help!
 
Last edited:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top