2009-12-29 17 views
5

Hallo Ich schreibe ein einfaches Client-Server-Programm. In diesem Programm habe ich getopt() zu verwenden, um die Portnummer und IP-Adresse wie folgt zu erhalten:Wie bekomme ich einen Wert von optarg

Server -i 127.0.0.1 -p 10001

Ich weiß nicht, wie kann ich Werte von optarg erhalten, zu verwenden später im Programm.

Antwort

4

Wie wäre es wie folgt aus:

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

Oder in ein umfassenderes Beispiel:

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

Weitere Informationen in der Dokumentation von Getopt sehen.

+0

Die Antwort mit strdup ist eine bessere Lösung für dieses Problem. Es vermeidet die Erstellung eines Puffers fester Größe für eine unbekannte Länge Zeichenfolge – tvanfosson

12

Sie verwenden eine while-Schleife, um alle Argumente bewegen sich durch und sie wie so verarbeiten ...

#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

Es ist eines der zahlreichen Mängel der getopt Dokumentation: es nämlich nicht deutlich, dass optarg muss für die spätere Verwendung kopiert werden (zum Beispiel mit strdup()), weil es möglicherweise durch spätere Optionen überschrieben oder einfach nur von getopt freigegeben wird.

+6

von getopt docs, http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html: ... "Sie nicht Normalerweise muss der optarg-String kopiert werden, da es sich um einen Zeiger auf das ursprüngliche argv-Array handelt und nicht in einen statischen Bereich, der überschrieben werden könnte. " – dmityugov

+0

@dmityugov - das mag wahr sein, aber ich würde im Allgemeinen über Lösungen, die das innere Wissen der Implementierung nutzen, die Stirn runzeln. Der Code kann viel robuster und kostengünstiger hergestellt werden, indem die Zeichenkette unter der Kontrolle des Programmierers in den Speicher kopiert wird, anstatt die Bibliothek zu steuern. – tvanfosson

+1

Ein Zeiger in argv ist nicht sicher, weil "Der Inhalt von argv wird beim Scannen standardmäßig permutiert, so dass schließlich alle Nicht-Optionen am Ende sind." Das bedeutet, dass sich der Inhalt von argv ändert, wenn Optionen wiederholt aufgerufen werden. Wenn die Permutationen alle zu dem Zeitpunkt ausgeführt werden, zu dem die Optionen das erste Mal zurückgegeben werden, dann sollte das Dokument dies angeben. – Urhixidur

1

Im Falle einer IP und Port müssen Sie die Zeichenfolgen nicht duplizieren. Parsen Sie sie einfach und speichern Sie die Werte in einem 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 ---------- */            
Verwandte Themen