1. 程式人生 > >C語言中getopt()和getopt_long()函式的用法

C語言中getopt()和getopt_long()函式的用法

一、命令列引數的使用

C程式的主函式有兩個引數,其中,第一個引數是整型,可以獲得包括程式名字的引數個數,第二個引數是字元陣列指標或字元指標的指標,可以按順序獲得命令列上各個字串引數。其原形是:

int main(int argc, char *argv[]);
或者是:
int main(int argc, char **argv);
比如在命令列輸入:
./test hello world  

則argc=3,argv[0]="./test",argv[1]="hello",argv[3]="world"

在主函式中可以直接對命令列引數進行處理,但當命令列引數個數較多時,如果按照順序一個一個定義引數含義很容易造成混亂,而且如果程式只按順序處理引數的話,一些“可選引數”的功能將很難實現。在Linux中,可以使用getopt()、getopt_long()、getopt_long_only()等函式來對複雜的命令列引數進行處理。

二、getopt()函式

原型:
#include <unistd.h>
 
extern char *optarg;
extern int optind, opterr, optopt;
int getopt(int argc, char * const argv[], const char *optstring);
描述:

1、getopt函式的前兩個引數,就是main函式的argc和argv,這兩者直接傳入即可,要考慮的就只剩下第三個引數。

2、optstring的格式舉例說明比較方便,例如:

    char *optstring = "abcd:";
上面這個optstring在傳入之後,getopt函式將依次檢查命令列是否指定了 -a, -b, -c及 -d(這需要多次呼叫getopt函式,直到其返回-1),當檢查到上面某一個引數被指定時,函式會返回被指定的引數名稱(即該字母)

最後一個引數d後面帶有冒號,: 表示引數d是可以指定值的,如 -d 100 或 -d user。字元後帶兩個':'表示該選項帶可選引數(引數可有可無)。

3、optind表示的是下一個將被處理到的引數在argv中的下標值。

4、如果指定opterr = 0的話,在getopt、getopt_long、getopt_long_only遇到錯誤將不會輸出錯誤資訊到標準輸出流。
例一:

#include <unistd.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
    
    int ch;
    printf("\n\n");
    printf("optind:%d,opterr:%d\n",optind,opterr);
    printf("--------------------------\n");
       while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
       {
        printf("optind: %d\n", optind);
           switch (ch) 
        {
               case 'a':
                       printf("HAVE option: -a\n\n");   
                       break;
               case 'b':
                       printf("HAVE option: -b\n"); 
                       printf("The argument of -b is %s\n\n", optarg);
                       break;
               case 'c':
                       printf("HAVE option: -c\n");
                       printf("The argument of -c is %s\n\n", optarg);
                       break;
               case 'd':
                   printf("HAVE option: -d\n");
                     break;
              case 'e':
                    printf("HAVE option: -e\n");
                    printf("The argument of -e is %s\n\n", optarg);
                  break;
              case '?':
                       printf("Unknown option: %c\n",(char)optopt);
                       break;
               }
       }


}

例二:

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

int main(int argc, char *argv[])
{
    int opt;
    char *optstring = "a:b:c:d";

    while ((opt = getopt(argc, argv, optstring)) != -1)
    {
        printf("opt = %c\n", opt);
        printf("optarg = %s\n", optarg);
        printf("optind = %d\n", optind);
        printf("argv[optind - 1] = %s\n\n",  argv[optind - 1]);
    }

    return 0;
}
輸出結果;
[email protected]:~/Desktop/getopt$ ./test_getopt -a 100 -b 200 -c admin -d  
opt = a  
optarg = 100  
optind = 3  
argv[optind - 1] = 100  
  
opt = b  
optarg = 200  
optind = 5  
argv[optind - 1] = 200  
  
opt = c  
optarg = admin  
optind = 7  
argv[optind - 1] = admin  
  
opt = d  
optarg = (null)  
optind = 8  
argv[optind - 1] = -d  

三、getopt_long()函式

getopt_long函式包含了getopt函式的功能,並且還可以指定“長引數”(或者說長選項),與getopt函式對比,getopt_long比其多了兩個引數。

原型:

#define _GNU_SOURCE

#include <getopt.h>

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);
int getopt_long_only(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex);
描述:

1、注意相比getopt,使用getopt_long需要加標頭檔案<getopt.h>;
2、getopt_long除了會接受長選項,其他概念和getopt是一樣的;
3、如果使用getopt_long想只接受短選項,設定longopts為NULL即可;如果只想接受長選項,相應地設定optstring為NULL即可;
4、長選項名是可以使用縮寫方式,比如:選項有--file\--create,那麼輸入--c/--cr/--cre等均會被正確識別為create選項;
5、對於帶引數的長選項格式是:--arg=param或--arg param;
6、longopts是指向struct option陣列的第一個元素的指標,struct option定義在<getopt.h>中;
7、longindex如果非NULL,則是返回識別到struct option陣列中元素的位置指標;

8、當所給的引數存在問題時,函式的返回值是'?'

struct option的說明:

           struct option {
               const char *name;
               int         has_arg;
               int        *flag;
               int         val;
           };

name: 長選項名
has_arg: 是否帶引數或可選引數,這個值在getopt.h中有巨集定義,如下:
     # define no_argument        0                表明這個長引數不帶引數(即不帶數值,如:--name)
     # define required_argument  1           表明這個長引數必須帶引數(即必須帶數值,如:--name Bob)
     # define optional_argument  2            表明這個長引數後面帶的引數是可選的,(即--name和--name Bob均可)
flag: 確定函式返回值的情況,如果flag==NULL,則識別選項後返回val(常用的如:設定val為長命令的短命令字元);否則,識別後getopt_long返回0,flag指向一個設定到val的變數;
val: 設定為返回值,或者是flag指向的變數;這裡要注意不要寫-1到val,否則其作用是getopt_long返回-1,然後停止解析選項;

[注意] longopts的最後一個元素必須是全0填充,否則會報段錯誤

例子:

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

int
main(int argc, char **argv)
{
   int opt;
   int digit_optind = 0;
   int option_index = 0;
   char *optstring = "a:b:c:d";
   static struct option long_options[] = {
       {"reqarg", required_argument, NULL, 'r'},
       {"noarg",  no_argument,       NULL, 'n'},
       {"optarg", optional_argument, NULL, 'o'},
       {0, 0, 0, 0}
   };

   while ( (opt = getopt_long(argc, argv, optstring, long_options, &option_index)) != -1)
   {
        printf("opt = %c\n", opt);
        printf("optarg = %s\n", optarg);
        printf("optind = %d\n", optind);
        printf("argv[optind - 1] = %s\n",  argv[optind - 1]);
        printf("option_index = %d\n", option_index);
   }

   return 0;
}

輸出結果:

[[email protected] c]$ ./test_getopt -a 100 --reqarg 100 --noarg
opt = a
optarg = 100
optind = 3
argv[optind - 1] = 100
option_index = 0
opt = r
optarg = 100
optind = 5
argv[optind - 1] = 100
option_index = 0
opt = n
optarg = (null)
optind = 6
argv[optind - 1] = --noarg
option_index = 1

最後說明一下,getopt_long_only與getopt_long的區別在於:getopt_long僅僅只能將"--"開始的選項視為長選項,但getopt_long_only將"-"開頭選項也會視為長選項,當長選項列表均不滿足時,且短選項滿足時,"-"才會解析為短選項;

參考文獻:

相關推薦

C言中getopt()getopt_long()函式用法

一、命令列引數的使用 C程式的主函式有兩個引數,其中,第一個引數是整型,可以獲得包括程式名字的引數個數,第二個引數是字元陣列指標或字元指標的指標,可以按順序獲得命令列上各個字串引數。其原形是: int main(int argc, char *argv[]);或者是:in

關於c言中mallocremalloc函式的分析

首先申明,這是本人第一次寫部落格,其目的僅僅是為了加強自己對知識點的掌握,為到達在本子上記筆記的效果 進入正題。對於malloc,它的作用就是為了動態分配空間,像c++中的new一樣。這裡就不說他們兩的區別了。malloc函式有這樣幾個特點。 1.分配的空間地址是連續的,

C言中printfscanf函式基本的引數型別輸出形式

printf函式的引數型別和輸出形式 字元 引數型別 輸出形式 d,i int 十進位制數 o int 無符號八進位制數(不含前導0) x,X int 無符號十六進位制數(沒有前

C言中static修飾的函式普通函式的區別

用static修飾的函式,本限定在本原始碼檔案中,不能被本原始碼檔案以外的程式碼檔案呼叫。而普通的函式,預設是extern的,也就是說,可以被其它程式碼檔案呼叫該函式。 在函式的返回型別前加上關鍵字static,函式就被定義成為靜態函式。普通 函式的定義和宣告預設情況下是extern的,但靜

C言中 typeof()函式用法

前言:     typeof關鍵字是C語言中的一個新擴充套件,這個特性在linux核心中應用非常廣泛。 一,說明     typeof的引數可以是兩種形式: 表示式 或 型別 。

C言中char*char[]用法區別分析

本文例項分析了C語言中char* 和 char []的區別。分享給大家供大家參考之用。具體分析如下: 一般來說,很多人會覺得這兩個定義效果一樣,其實差別很大。以下是個人的一些看法,有不正確的地方望指正。 本質上來說,char *s定義了一個char型的指標,它只知道所指向的

c言中fscanffprintf

寫的權限 set per efi errno fclose pri form price 很多時候我們需要寫入數據到文件中時都覺得很困擾,因為格式亂七八槽的,可讀性太差了,於是我們就想有沒有什麽函數可以格式化的從文件中輸入和輸出呢,還真有。下面我將講解一下fscanf和fp

C言中sprintf()函數的用法

用法 href bsp HA 連接 art tail 格式化 類型轉換 sprintf函數的用法1、該函數包含在stdio.h的頭文件中。 2、sprintf和平時我們常用的printf函數的功能很相似。sprintf函數打印到字符串中,而printf函數打印輸出到屏幕

C言中typedefsizeof的註意事項

isp sizeof spa 註意 list數據 對象 audio 應該 user typedef的作用是給一個數據類型起一個別名。 typedef struct LIST { int data; }SeqList; SeqList 就相當於struct LIS

c言中external,static關鍵字用法

static用法: 在C中,static主要定義全域性靜態變數、定義區域性靜態變數、定義靜態函式。 1、定義全域性靜態變數:在全域性變數前面加上關鍵字static,該全域性變數變成了全域性靜態變數。全域性靜態變數有以下特點。 a.在全域性區分配記憶體。 b.如果沒有初始化,其預設值為

C言中 malloc free

from:http://blog.sina.com.cn/s/blog_af1a77fa0102xceb.html 一、malloc()和free()的基本概念以及基本用法: 1、函式原型及說明: void *malloc(long NumBytes):該函式分配了NumBytes個位元

c言中strchr()字串處理函式

strchr()這個函式並不像strcpy(),strcat(),strcmp(),strupr(),strlwr(),strlen()這幾個字串處理函式那麼直觀,所以需要通過一個程式碼來理解一下: 程式碼來自c語言開發入門及專案實戰一書: #include<stdi

c言中staticauto的區別

1、static變數存放在靜態儲存區,在程式整個執行期間都不釋放;而auto變數存放在動態儲存區,隨著生命週期的結束而立即釋放。 2、static變數只賦值一次,以後就不用賦值;而auto變數在函式每呼叫一次都要賦初值

關於C言中“x++”“++x”的問題

關於一個變數在不同環境下自增自減的問題。 #include<stdio.h> int main() { int x = 8; int y = 0; y = (++x) + (x++) + (++x); printf("%d\n",y);

C言中“指標”“指標變數”的區別是什麼

比較嚴格的說法是這樣的:系統為每一個記憶體單元分配一個地址值,C/C++把這個地址值稱為“指標”。如有int i=5;,存放變數i的記憶體單元的編號(地址)&i被稱為指標。“指標變數”則是存放前述“地址值”的變數,也可以表述為,“指標變數”是存放變數所佔記憶體空間“

C言中i++++i的區別

C語言中i++和++i的區別 C語言中++i和i++是有區別的!快速理解的話就是用一句話概括: 1、i++是先賦值再運算+1; 2、++i是先運算+1再賦值; i++和++i都是c語言裡的自增,但是它們自增的順序不同。++i表示,i自增1後再參與其它運算,而i++ 則是i參與運算後,i的

C言中char * char []的區別

問題引入: 在實習過程中發現了一個以前一直預設的錯誤,同樣char *c = "abc"和char c[]="abc",前者改變其內容程式是會崩潰的,而後者完全正確。 程式演示: #include <iostream> usingnamespa

C言中,如何通過函式來改變一個變數的值

最近看面試題,遇到一些關於通過函式改變一個變數的值得問題,現在終結一下: 先看下面一段程式碼: #include <stdio.h>#include <stdlib.h> void GetMemory(char *p) { p=(char

C言中constC++中const關鍵字的區別

# include "iostream" using namespace std; struct Teacher {     char name[30];     int age; }; void operatorTeacher(Teacher *pT) {   

由淺至深->C言中unionenum關鍵字的經典問題分析

引言:由淺至深系列的第二篇文章,繼續體悟語言中的一些細節! 文章嚮導 union的自我介紹 union與系統大小端 enum列舉的引入 真正意義上的常量? 正文 一、union的自我介紹   union(聯合/共用體)在語