2009-12-29 124 views
5

嗨,我正在寫一個簡單的客戶端服務器程序。在這個節目,我不得不使用getopt()得到這樣的端口號和IP地址:如何從optarg獲得價值

服務器-i 127.0.0.1 -p 10001

我不知道我怎樣才能從OPTARG值,使用後來在程序中。

回答

4

這個怎麼樣:

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

或者在更完整的例子:

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

欲瞭解更多信息,請參閱的Getopt文檔。

+0

使用strdup的答案是解決此問題的更好方法。它避免了從getopt docs,http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html爲未知長度的字符串 – tvanfosson 2013-07-21 20:49:14

12

您使用while循環遍歷所有參數移動,像這樣處理它們...

#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

這是getopt的文檔的衆多缺陷之一:它並沒有說明清楚,OPTARG必須被複制以備後用(例如使用strdup()),因爲它可能被後面的選項覆蓋,或者被getopt簡單釋放。

+6

創建一個固定大小的緩衝區:...「您不通常需要複製optarg字符串,因爲它是指向原始argv數組的指針,而不是可能被覆蓋的靜態區域。「 – dmityugov 2013-05-16 09:50:43

+0

@dmityugov - 這可能是事實,但我通常會對利用內部實現知識的解決方案感到不滿。通過在程序員的控制下將字符串複製到內存中而不是庫控制下,可以以較小的代價使代碼更健壯。 – tvanfosson 2013-07-21 21:34:01

+1

指向argv的指針並不安全,因爲「默認情況下是在掃描argv的內容時對其進行置換,以便最終所有非選項都處於末尾。」,這意味着argv的內容會隨着選項的重複調用而發生變化。如果排列都是由選項第一次返回的時間完成的,那麼文檔應該說明如此。 – Urhixidur 2013-07-24 12:35:15

1

在ip和端口的情況下,您不需要複製字符串。只需解析它們並將這些值存儲在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 ---------- */