1. 程式人生 > >Linux下C程式命令列引數處理

Linux下C程式命令列引數處理

       Linux下開發C程式,甚至是GUI程式,都可能需要處理複雜的命令列引數。健全、可靠的複雜命令列引數處理機制,可使程式方便使用,也更顯專業。Linux下幾乎所有的命令都提供了引數處理機制,包括短選項和長選項。

  POSIX標準中對程式名、引數作了如下相關約定:
    * 程式名不宜少於2個字元且不多於9個字元;
    * 程式名應只包含小寫字母和阿拉伯數字;
    * 選項名應該是單字元活單數字,且以短橫‘-‘為字首;
    * 多個不需要選項引數的選項,可以合併。(譬如:foo -a -b -c ---->foo -abc)
    * 選項與其引數之間用空白符隔開;
    * 選項引數不可選。
    * 若選項引數有多值,要將其併為一個字串傳進來。譬如:myprog -u "arnold,joe,jane"。這種情況下,需要自己解決這些引數的分離問題。
    * 選項應該在操作數出現之前出現。

    * 特殊引數‘--'指明所有引數都結束了,其後任何引數都認為是運算元。
    * 選項如何排列沒有什麼關係,但對互相排斥的選項,如果一個選項的操作結果覆蓋其他選項的操作結果時,最後一個選項起作用;如果選項重複,則順序處理。
    * 允許運算元的順序影響程式行為,但需要作文件說明。
    * 讀寫指定檔案的程式應該將單個引數'-'作為有意義的標準輸入或輸出來對待。

  GNU鼓勵程式設計師使用--help、--verbose等形式的長選項。這些選項不僅不與POSIX約定衝突,而且容易記憶,另外也提供了在所有GNU工具之間保持一致性的機會。GNU長選項有自己的約定
    * 對於已經遵循POSIX約定的GNU程式,每個短選項都有一個對應的長選項。

    * 額外針對GNU的長選項不需要對應的短選項,僅僅推薦要有。
    * 長選項可以縮寫成保持惟一性的最短的字串。
    * 選項引數與長選項之間或通過空白字元活通過一個'='來分隔。
    * 選項引數是可選的(只對短選項有效)。
    * 長選項允許以一個短橫線為字首。

  C程式通過argc和argv引數訪問它的命令列引數,通過main()函式呼叫和處理:int main(int argc, char *argv[])。一般情況下,我們事先約定好引數的順序位置,然後在main函式中進行簡單處理。這種方式實現比較簡單,然後使用者使用起來很不方便,Linux下的各種工具的命令列引數可以是不分先後次序的。幸運的是,Linux為C程式設計師提供了相關的命令列引數解析函式:getopt()和getopt_long(),分別用於處理短選項和長選項,當然後者可以同時處理短、長選項。函式原型如下:

#include <unistd.h>


int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;

int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);


          getopt() 函式是一個標準庫呼叫,可允許使用直接的 while/switch 語句方便地逐個處理命令列引數和檢測選項(帶或不帶附加的引數)。getopt_long() 允許在幾乎不進行額外工作的情況下處理更具描述性的長選項,非常受開發人員的歡迎。下面用筆者開發的一個Daemon程式wsiod中的引數處理來說明具體的處理過程。wsiod引數幫助資訊如下:

[liuag] /home/liuag/workspace/WSIO/WSIO-1.3/server > ./wsiod --help
Usage:  wsiod [OPTION]

WSIO server based on web service.
Mandatory arguments to long options are mandatory for short options too.
        -h, --host           hostname in soap_bind, default is host which the service runs
        -p, --port           port which the sercer runs on, default is 8080
        -b, --backlog        request backlog, default is 100
        -t, --type           server type, default is COMMON
        -k, --keepalive      attempt to keep socket connections alive
        -c, --chunk          use HTTP chunking
        -d, --dime           use DIME encoding
        -D, --debug          print debug info
            --help           print this help

Server type:
        COMMON               the simplest server
        STANDALONE           stand-alone server, which can run on port 80
        MULTITHREAD          multi-thread stand-alone server
        POOL                 using a pool of servers
        QUEUE                using a queue of requests for server
        GSI                  prethreaded server with GSI enabled

Report bugs to <[email protected]>.

wsiod引數處理實現C程式段如下:

#include <unistd.h>
#include <getopt.h>

enum SERVERTYPE{COMMON, STANDALONE, MULTITHREAD, POOL, QUEUE, GSI};
int keepalive = 0, dime = 0, chunk = 0;

/* WSIO server main function */
int main(int argc, char **argv)
{
  int c;
  char host[128] = "localhost";
  char log_buf[LOGBUFSZ];
  int port = 8080, backlog = 100;
  enum SERVERTYPE servertype  = COMMON;
  int helpflg = 0,
      errflg = 0,
      debug = 0;
  struct option longopts[] =
  {
    {"host", 1, 0, 'h'},
    {"port", 1, 0, 'p'},
    {"backlog", 1, 0, 'b'},
    {"type", 1, 0, 't'},
    {"keepalive", 0, 0, 'k'},
    {"chunk", 0, 0, 'c'},
    {"dime", 0, 0, 'd'},
    {"debug", 0, 0, 'D'},
    {"help", 0, &helpflg, 1},
    {0, 0, 0, 0}
  };

  while ((c = getopt_long (argc, argv, "h:p:b:t:kcdD", longopts, NULL)) != EOF)
  {
    switch(c)
    {
      case 'h':
        sprintf(host, "%s", optarg);
        break;
      case 'p':
        port = atoi(optarg);
        break;
      case 'b':
        backlog = atoi(optarg);
        break;
      case 't':
        switch(*optarg)
    {
      case 'C':
        servertype = COMMON;
        break;
      case 'S':
        servertype = STANDALONE;
        break;
      case 'M':
        servertype = MULTITHREAD;
        break;
      case 'P':
        servertype = POOL;
        break;
      case 'Q':
        servertype = QUEUE;
        break;
      case 'G':
        servertype = GSI;
      default:
        break;
    }
        break;
      case 'k':
          keepalive = 1;
    break;
      case 'c':
          chunk = 1;
    break;
      case 'd':
          dime = 1;
    break;
      case 'D':
          debug = 1;
    break;
      case '?':
        errflg++;
        break;
      default:
        break;
    }
  }

  if(helpflg || errflg)
  {
     fprintf(stderr,"Usage:    wsiod [OPTION]/n/n%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
         "WSIO server based on web service./n",
    "Mandatory arguments to long options are mandatory for short options too./n",
    "/t-h, --host           hostname in soap_bind, default is host which the service runs/n ",
    "/t-p, --port           port which the sercer runs on, default is 8080/n",
    "/t-b, --backlog        request backlog, default is 100/n",
    "/t-t, --type           server type, default is COMMON/n",
    "/t-k, --keepalive      attempt to keep socket connections alive/n",
        "/t-c, --chunk          use HTTP chunking/n",
        "/t-d, --dime           use DIME encoding/n",
        "/t-D, --debug          print debug info/n",
    "/t    --help           print this help/n/n",
    "Server type:/n",
    "/tCOMMON               the simplest server/n",
    "/tSTANDALONE           stand-alone server, which can run on port 80/n"
    "/tMULTITHREAD          multi-thread stand-alone server/n",
    "/tPOOL                 using a pool of servers/n",
    "/tQUEUE                using a queue of requests for server/n",
    "/tGSI                  prethreaded server with GSI enabled/n/n",
    "Report bugs to <[email protected]>./n"
     );
    exit(0);
  }

  /* 省略部分 */

  return 0;
}

相關推薦

LinuxC程式命令引數處理

       Linux下開發C程式,甚至是GUI程式,都可能需要處理複雜的命令列引數。健全、可靠的複雜命令列引數處理機制,可使程式方便使用,也更顯專業。Linux下幾乎所有的命令都提供了引數處理機制,包括短選項和長選項。  POSIX標準中對程式名、引數作了如下相關約定: 

windowsC++程式命令引數讀取

linux下,命令列引數的讀取,可以使用系統函式getopt,還好Ludvik Jerabek實現了一個開源的getopt,我們可以直接拿來在windows程式設計中用。 STATIC_GETOPT 然後就可以體會getopt帶來的便利了: bool isHelp

Linux 程式設計學習筆記----命令引數處理

問題引入----命令列引數及解析 在使用linux時,與windows最大的不同應該就是經常使用命令列來解決大多數問題.比如下面這樣的: 而顯然我們知道C語言程式的入口是mian函式,即是從main函式開始執行,而main函式的原型是: int main( int a

boost之program_option-命令引數處理(霜之小刀)

歡迎轉載和引用,若有問題請聯絡 若有疑問,請聯絡 Email : [email protected] QQ:2279557541 命令列的引數處理什麼xxx –xxx -x=xx -x 這種東西如果我們自己從argc,argv裡面提取,我相信大家

linuxc程式 daemon、fork與建立pthread的順序問題

近期發如今寫linux c服務程式的時候,daemon與執行緒建立之間出現故障。發現程式在daemon之後,起的執行緒就全掛了。 查過一些文件之後,最終知道了why. daemon函式的操作事實上非常easy, 1.fork一個程序,2.處理

LinuxC程式動態庫的生成和呼叫

Linux下C程式動態庫的生成和呼叫 文章目錄 Linux下C程式動態庫的生成和呼叫 1 動態庫的打包和呼叫 2 靜態庫打包和呼叫 3 常用命令 4 gcc 和 g++ 區別 5 編譯和連結的理解

C程式設計--命令引數(argc 和 argv[])

概念 命令列引數是使用 main() 函式引數來處理的,其中,argc 是指傳入引數的個數,argv[] 是一個指標陣列,指向傳遞給程式的每個引數。 具體寫法:int main(int argc,char* argv[ ]) //注:main()括號內是固定的寫法。 或者寫成:int

python命令引數處理:argparse、optparse和getopt

一 命令列引數: (1)在python中: *sys.argv:命令列引數的列表。 *len(sys.argv):命令列引數的個數(argc)。 *python中提供了三個模組來輔助處理命令列引數:getopt,optparse和argparse。 (2)術語: *arg

C語言命令引數的使用

     之前曾經使用過很多次c語言的命令列引數了,但是總是每次使用的時候都不太確定,需要重新查資料,這次來個總結。c語言的命令列引數非常簡單,只需要一個簡單的例子就可以說明: #include <stdio.h> void main(int argc,char

linux中getopt_long解析命令引數(附上windows上的getopt_long原始碼)

     getopt_long支援長選項的命令列解析,使用man getopt_long,得到其宣告如下:       #include <getopt.h>       int getopt_long(int argc, char * const argv[

C 語言命令引數解析

C語言原始碼必須有且只有一個的函式是main函式,我們知道函式可以有引數,那麼main函式有沒有引數呢? 顯然是有的,而且它是固定的,只有兩個,第一個是整型變數(argc),第二個是字元型指標陣列(a

UNIX/LINUXC++程式計時方法

最近簡單學習了下Linux下C++程式計時的一些函式和方法,總結如下. 方法一: 如果是想統計某個程式的執行時間,那麼可以使用 time ./a.out 方法二: 如果是想對某個函式或者語句進行計時,那麼有別的方法。比如說,gettimeofday函式

Shell指令碼學習-命令引數處理

在Linux的Shell中怎樣處理tail -n 10 access.log這樣的命令列選項呢?這是被別人問起的一個問題,好好學習了一下,進行總結如下: 在bash中,可以用以下三種方式來處理命令列引數,每種方式都有自己的應用場景。 1.直接處理,依次

Linux c++程式中列印系統當前時間

    //方案一,將當前時間折算為秒級,再通過相應的時間換算即可     //此檔案必須是c++檔案     /*     #include<iostream>     #include<ctime>     using namespace std

C/C++中命令引數的原理總結

   在c/c++中,命令列引數的傳遞是利用main進行形參傳遞實現 【1】了實現命令列引數我們將使用main(int argc,char* argv[])這樣的形式進行定義argc和argv可以換成你自己喜歡的名稱不一定要用argv,argc這些形式只是習慣而已,char*

WindowsC語言命令編譯器的環境變數設定

安裝完VS任意一個版本後只要進行相應的環境變數的設定就能用命令列編譯C語言程式,此方法完美解決win8下VC6不相容又不想執行臃腫的VS 將該指令碼命令在命令列中執行一下即完成環境變數的設定,這裡以VS2012為例,其他版本需做相應更改,如VS2013,就設定VS130Co

Linux環境C程式設計指南---gcc 編譯器常用的命令引數一覽

1. gcc -E source_file.c-E,只執行到預編譯。直接輸出預編譯結果。2. gcc -S source_file.c -S,只執行到原始碼到彙編程式碼的轉換,輸出彙編程式碼。3. gcc -c source_file.c-c,只執行到編譯,輸出目標檔案。4. gcc (-E/S/c/) so

C程式編譯連結】gcc使用命令介紹 gcc的使用簡介與命令引數說明

1.gcc或者g++安裝rpm -qa|grep gcc ==>檢查gcc是否安裝gcc -v ==>檢查gcc版本 編譯器會在可執行檔案中植入一些資訊,可執行檔案會變大。一般開發時候使用 -g ,編譯一個 “release 版本” 時不使用 -g 編譯。gcc如果是最新的則不重

一個簡單的C#命令引數程式

 新建一個c#控制檯程式,命名為ConsoleApplication1 程式主體如下 class Program  {   static void Main(string[] args)   {   

DOS(CMD)處理換行問題/命令引數換行 arg ms-dos

程式來自:http://hi.baidu.com/nxhujiee/item/ae52584c36a13d0f6dc2f0f8 DOS(CMD)下批處理換行問題本人經常寫一些DOS批處理檔案,由於批處理中命令的參考較多且長,寫在一行太不容易分辨,所以總想找個辦法把一條命令