2009-12-29 7 views
5

Salut J'écris un programme client-serveur simple. Dans ce programme, je dois utiliser getopt() pour obtenir le numéro de port et l'adresse IP comme ceci:Comment obtenir une valeur d'optarg

serveur

-i 127.0.0.1 -p 10001

Je ne sais pas comment puis-je obtenir des valeurs de optarg, à utiliser plus tard dans le programme.

Répondre

4

Que diriez-vous comme ceci:

char buf[BUFSIZE+1]; 
snprintf(buf,BUFSIZE,"%s",optarg); 

Ou dans un exemple plus complet:

#include <stdio.h> 
#include <unistd.h> 

#define BUFSIZE 16 

int main(int argc, char **argv) 
{ 
    char c; 
    char port[BUFSIZE+1]; 
    char addr[BUFSIZE+1]; 

    while((c = getopt(argc, argv, "i:p:")) != -1) 
     switch (c) 
     { 
      case 'i': 
       snprintf(addr, BUFSIZE, "%s", optarg); 
       break; 
      case 'p': 
       snprintf(port, BUFSIZE, "%s", optarg); 
       break; 
      case '?': 
       fprintf(stderr, "Unrecognized option!\n"); 
       break; 
     } 

    return 0; 
} 

Pour plus d'informations, consultez la documentation de Getopt.

+0

La réponse à l'aide de strdup est une meilleure solution à ce problème. Il évite de créer un tampon de taille fixe pour une chaîne de longueur inconnue – tvanfosson

12

Vous utilisez une boucle while pour se déplacer à travers tous les arguments et les traiter comme si ...

#include <unistd.h> 

int main(int argc, char *argv[]) 
{ 
    int option = -1; 
    char *addr, *port; 

    while ((option = getopt (argc, argv, "i:p:")) != -1) 
    { 
     switch (option) 
     { 
     case 'i': 
      addr = strdup(optarg); 
      break; 
     case 'p': 
      port = strdup(optarg); 
      break; 
     default: 
       /* unrecognised option ... add your error condition */ 
       break; 
     } 
    } 

    /* rest of program */ 

    return 0; 
} 
2

Il est l'un des nombreux défauts de la documentation getopt: il ne dit pas clairement que optarg doit être copié pour une utilisation ultérieure (en utilisant strdup(), par exemple) car il peut être écrasé par des options ultérieures ou simplement être libéré par getopt.

+6

à partir de docs getopt, http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html: ... "Vous ne le faites pas habituellement besoin de copier la chaîne optarg, car il s'agit d'un pointeur dans le tableau argv d'origine, pas dans une zone statique qui pourrait être remplacée. " – dmityugov

+0

@dmityugov - cela peut être vrai, mais je désapprouverais généralement des solutions qui tirent parti de la connaissance interne de l'implémentation. Le code peut être rendu beaucoup plus robuste à un faible coût en dupliquant la chaîne en mémoire sous le contrôle du programmeur plutôt que par le contrôle de la bibliothèque. – tvanfosson

+1

Un pointeur dans argv n'est pas sûr, car "Le paramètre par défaut est de permuter le contenu de argv pendant l'analyse afin que toutes les non-options soient terminées.", Signifiant que le contenu de argv change comme options. Si les permutations sont toutes faites au moment où les options retournent la première fois, alors le doc devrait l'indiquer. – Urhixidur

1

Dans le cas d'une adresse IP et d'un port, vous n'avez pas besoin de dupliquer les chaînes. Il suffit de les analyser et de stocker les valeurs dans un sockaddr.

#include <arpa/inet.h>     // for inet_ntop, inet_pton                                                                           
#include <getopt.h>      // for getopt, optarg                                                                             
#include <netinet/in.h>     // for sockaddr_in, etc                                                                            
#include <stdio.h>      // for fprintf, printf, stderr                                                                          
#include <stdlib.h>      // for atoi, EXIT_SUCCESS                                                                            
#include <string.h>      // for memset                                                                               
#include <sys/socket.h>     // for AF_INET                                                                              

int main(int argc, char *argv[])                                                                                    
{                                                                                            
    struct sockaddr_in sa;                                                                                     
    char c;                                                                                         

    memset(&sa, 0, sizeof(sa));                                                                                    
    sa.sin_family = AF_INET;                                                                                     
    sa.sin_addr.s_addr = INADDR_ANY;                                                                                   
    sa.sin_port = 0;                                                                                       

    while ((c = getopt(argc, argv, "i:p:")) != -1)                                                                               
    {                                                                                           
     switch (c)                                                                                       
     {                                                                                          
      case 'p':                                                                                       
       sa.sin_port = htons(atoi(optarg));                                                                               
       break;                                                                                      
      case 'i':                                                                                       
       inet_pton(AF_INET, optarg, &(sa.sin_addr));                                                                             
       break;                                                                                      
      case '?':                                                                                       
       fprintf(stderr, "Unknown option\n");                                                                               
       break;                                                                                      
     } /* ----- end switch ----- */                                                                                  
    }                                                                                           

    char str[INET_ADDRSTRLEN];                                                                                    
    inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);                                                                             
    printf("%s:%d\n", str, ntohs(sa.sin_port));                                                                                

    return EXIT_SUCCESS;                                                                                      
} /* ---------- end of function main ---------- */            
Questions connexes