日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

va_list和vsnprintf、getopt

發(fā)布時間:2023/11/30 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 va_list和vsnprintf、getopt 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原理解釋:

VA_LIST 是在C語言中解決變參問題的一組宏,在<stdarg.h>頭文件下。

VA_LIST的用法:? ? ?
? ? ?
1)首先在函數(shù)里定義一具VA_LIST型的變量,這個變量是指向參數(shù)的指針
? ? ?
2)然后用VA_START宏初始化變量剛定義的VA_LIST變量,這個宏的第二個參數(shù)是第一個可變參數(shù)的前一個參數(shù),是一個固定的參數(shù)。
? ? ?
3)然后用VA_ARG返回可變的參數(shù),VA_ARG的第二個參數(shù)是你要返回的參數(shù)的類型。
? ? ?
4)最后用VA_END宏結(jié)束可變參數(shù)的獲取。然后你就可以在函數(shù)里使用第二個參數(shù)了。如果函數(shù)有多個可變參數(shù)的,依次調(diào)用VA_ARG獲取各個參數(shù)。

VA_LIST
在編譯器中的處理:

(1)在運行VA_START(ap,v)以后,ap指向第一個可變參數(shù)在堆棧的地址。
2VA_ARG()取得類型t的可變參數(shù)值,在這步操作中首先apt = sizeof(t類型),讓ap指向下一個參數(shù)的地址。然后返回ap-sizeof(t類型)t類型*指針,這正是第一個可變參數(shù)在堆棧里的地址。然后用*取得這個地址的內(nèi)容。
3VA_END(),X86平臺定義為ap = ((char*)0),使ap不再指向堆棧,而是跟NULL一樣,有些直接定義為((void*)0),這樣編譯器不會為VA_END產(chǎn)生代碼,例如gccLinuxX86平臺就是這樣定義的。

要注意的是:由于參數(shù)的地址用于VA_START宏,所以參數(shù)不能聲明為寄存器變量,或作為函數(shù)或數(shù)組類型。

使用VA_LIST應(yīng)該注意的問題:
??
1)因為va_start, va_arg, va_end等定義成宏,所以它顯得很愚蠢,可變參數(shù)的類型和個數(shù)完全在該函數(shù)中由程序代碼控制,它并不能智能地識別不同參數(shù)的個數(shù)和類型.也就是說,你想實現(xiàn)智能識別可變參數(shù)的話是要通過在自己的程序里作判斷來實現(xiàn)的.
??
2)另外有一個問題,因為編譯器對可變參數(shù)的函數(shù)的原型檢查不夠嚴(yán)格,對編程查錯不利.不利于我們寫出高質(zhì)量的代碼。
?

小結(jié):可變參數(shù)的函數(shù)原理其實很簡單,而VA系列是以宏定義來定義的,實現(xiàn)跟堆棧相關(guān)。我們寫一個可變函數(shù)的C函數(shù)時,有利也有弊,所以在不必要的場合,我們無需用到可變參數(shù),如果在C++里,我們應(yīng)該利用C++多態(tài)性來實現(xiàn)可變參數(shù)的功能,盡量避免用C語言的方式來實現(xiàn)。

va_list ap; //聲明一個變量來轉(zhuǎn)換參數(shù)列表 ?
va_start(ap,fmt);? ? ? ? ? //初始化變量 ?
va_end(ap); ? ? //結(jié)束變量列表,va_start成對使用 ?
可以根據(jù)va_arg(ap,type)取出參數(shù) ?

已經(jīng)經(jīng)過調(diào)試成功的輸出程序

#include<stdio.h>
#include <stdarg.h>

#define bufsize 80
char buffer[bufsize];

int vspf(char *fmt, ...)
{
va_list argptr;
int cnt;
va_start(argptr, fmt);

cnt = vsnprintf(buffer,bufsize ,fmt, argptr);

va_end(argptr);

return(cnt);
}

int main(void)
{
int inumber = 30;

float fnumber = 90.0;

char string[4] = "abc";

vspf("%d %f %s", inumber, fnumber, string);

printf("%s\n", buffer);

return 0;
}






頭文件:

#include <stdarg.h>

函數(shù)聲明:

int vsnprintf(char*str,size_tsize,constchar*format,va_listap);

參數(shù)說明:

  • char *str [out],把生成的格式化的字符串存放在這里.
  • size_t size [in], str可接受的最大字節(jié)數(shù),防止產(chǎn)生數(shù)組越界.
  • const char *format [in],指定輸出格式的字符串,它決定了你需要提供的可變參數(shù)的類型、個數(shù)和順序。
  • va_list ap [in], va_list變量. va:variable-argument:可變參數(shù)
  • 函數(shù)功能:將可變參數(shù)格式化輸出到一個字符數(shù)組。

    用法類似于vsprintf,不過加了size的限制,防止了內(nèi)存溢出(sizestr所指的存儲空間的大小)。

    返回值:執(zhí)行成功,返回寫入到字符數(shù)組str中的字符個數(shù)(不包含終止符),最大不超過size;執(zhí)行失敗,返回負(fù)值,并置errno.[1]

    備注:

    linux環(huán)境下是:vsnprintf

    VC6環(huán)境下是:_vsnprintf


    2用法實例

    #include <stdio.h>

    #include <stdlib.h>

    #include <stdarg.h>

    char *make_message(const char *fmt, ...) {

    /* 初始時假設(shè)我們只需要不超過100字節(jié)大小的空間 */

    int n, size = 100;

    char *p;

    va_list ap;

    if ( (p = (char *) malloc(size*sizeof(char))) == NULL)

    return NULL;

    while (1) {

    /* 嘗試在申請的空間中進(jìn)行打印操作 */

    va_start(ap, fmt);

    n = vsnprintf (p, size, fmt, ap);

    va_end(ap);

    /* 如果vsnprintf調(diào)用成功,返回該字符串 */

    if (n > -1 && n < size)

    return p;

    /* vsnprintf調(diào)用失敗(n<0),或者p的空間不足夠容納size大小的字符串(n>=size),嘗試申請更大的空間*/

    size *= 2; /* 兩倍原來大小的空間 */

    if ((p = (char *)realloc(p, size*sizeof(char))) == NULL)

    return NULL;

    }

    }

    int main() {

    /* 調(diào)用上面的函數(shù) */

    char* str = make_message("%d,%d,%d,%d",5,6,7,8);

    printf("%s\n",str);

    free(str);

    /* we allocate the memory in the make_message function, so we should release it by caller(main function). */

    return 0;

    }








    linux 中解析命令行參數(shù)(getopt_long用法)optarg,optind?


    getopt_long支持長選項的命令行解析,使用man getopt_long,得到其聲明如下:
    #include <getopt.h>
    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);
    說明:函數(shù)中的argc和argv通常直接從main()到兩個參數(shù)傳遞而來。optsting是選項參數(shù)組成的字符串,如果該字符串里任一字母后有冒號,那么這個選項就要求有參數(shù)。下一個參數(shù)是指向數(shù)組的指針,這個數(shù)組是
    option結(jié)構(gòu)數(shù)組,option結(jié)構(gòu)稱為長選項表,其聲明如下:
    struct option {
    const char *name;
    int has_arg;
    int *flag;
    int val;
    };
    結(jié)構(gòu)中的元素解釋如下:
    const char *name:選項名,前面沒有短橫線。譬如"help"、"verbose"之類。
    int has_arg:描述長選項是否有選項參數(shù),如果有,是哪種類型的參數(shù),其值見下表:
    符號常量 ? ? ? ? ? ? 數(shù)值 ? ? ? ? ? ?含義
    no_argument ? ? ? ? ? ?0 ? ? ? ? ? ?選項沒有參數(shù)
    required_argument ? ? ?1 ? ? ? ? ? ?選項需要參數(shù)
    optional_argument ? ? ?2 ? ? ? ? ? ?選項參數(shù)是可選的
    int *flag:
    如果該指針為NULL,那么getopt_long返回val字段的值;
    如果該指針不為NULL,那么會使得它所指向的結(jié)構(gòu)填入val字段的值,同時getopt_long返回0
    int val:
    如果flag是NULL,那么val通常是個字符常量,如果短選項和長選項一致,那么該字符就應(yīng)該與optstring中出現(xiàn)的這個選項的參數(shù)相同;
    最后一個參數(shù):longindex參數(shù)一般賦為NULL即可;如果沒有設(shè)置為NULL,那么它就指向一個變量,這個變量會被賦值為尋找到的長選項在longopts中的索引值,這可以用于錯誤診斷。
    注:GNU提供的getopt-long()和getopt-long-only()函數(shù),其中,后者的長選項字串是以一個短橫線開始的,而非一對短橫線。
    linux 命令行約定:
    幾乎所有的GNU/Linux程序都遵循一些命令行參數(shù)定義的約定。程序希望出現(xiàn)的參數(shù)可以分成兩種:選項(options or flags)、其他類型的的參數(shù)。Options修飾了程序運行的方式,其他類型的參數(shù)則提供了輸入(例如,輸入文件的名稱)。
    對于options類型參數(shù)可以有兩種方式:
    1)短選項(short options):顧名思義,就是短小參數(shù)。它們通常包含一個連字號和一個字母(大寫或小寫字母)。例如:-s,-h等。
    2)長選項(long options):長選項,包含了兩個連字號和一些大小寫字母組成的單詞。例如,--size,--help等。
    *注:一個程序通常會提供包括short options和long options兩種參數(shù)形式的參數(shù)。
    對于其他類型參數(shù)的說明:
    這種類型的參數(shù),通常跟隨在options類型參數(shù)之后。例如,ls –s /功能為顯示root目錄的大小。’/ ’這個參數(shù)告訴ls要顯示目錄的路徑。
    getopt_long()函數(shù)使用規(guī)則:
    (1)使用前準(zhǔn)備兩種數(shù)據(jù)結(jié)構(gòu)
    字符指針型變量
    該數(shù)據(jù)結(jié)構(gòu)包括了所有要定義的短選項,每一個選項都只用單個字母表示。如果該選項需要參數(shù)(如,需要文件路徑等),則其后跟一個冒號。例如,三個短選項分別為‘-h’‘-o’‘-v’,其中-o需要參數(shù),其他兩個不需要參數(shù)。那么,我們可以將數(shù)據(jù)結(jié)構(gòu)定義成如下形式:
    const char * ?const shor_options = “ho:v” ;
    如果是否有參數(shù)是可選的,則在后面有兩個冒號。
    struct option 類型數(shù)組
    該數(shù)據(jù)結(jié)構(gòu)中的每個元素對應(yīng)了一個長選項,并且每個元素是由四個域組成。通常情況下,可以按以下規(guī)則使用。
    第一個元素,描述長選項的名稱;
    第二個選項,代表該選項是否需要跟著參數(shù),需要參數(shù)則為1,反之為0;
    第三個選項,可以賦為NULL;
    第四個選項,是該長選項對應(yīng)的短選項名稱。
    另外,數(shù)據(jù)結(jié)構(gòu)的最后一個元素,要求所有域的內(nèi)容均為0,即{NULL,0,NULL,0}。下面舉例說明,還是按照短選項為‘-h’‘-o’‘-v’的例子,該數(shù)據(jù)結(jié)構(gòu)可以定義成如下形式:
    const struct option long_options = {
    { ?“help”, ? ? ?0, ? NULL, ? ‘h’ ?},
    { ?“output”, ? ?1, ? NULL, ? ‘o’ ?},
    { ?“verbose”, ? 0, ? NULL, ? ‘v’ ?},
    { ?NULL, ? ? ?0, ? ?NULL, ? 0 ?}
    };
    (2)調(diào)用方法
    參照(1)準(zhǔn)備的兩個數(shù)據(jù)結(jié)構(gòu),則調(diào)用方式可為:
    getopt_long( argc, argv, short_options, long_options, NULL);
    (3)幾種常見返回值
    (a)每次調(diào)用該函數(shù),它都會分析一個選項,并且返回它的短選項,如果分析完畢,即已經(jīng)沒有選項了,則會返回-1。
    (b)如果getopt_long()在分析選項時,遇到一個沒有定義過的選項,則返回值為‘?’,此時,程序員可以打印出所定義命令行的使用信息給用戶。
    (c)當(dāng)處理一個帶參數(shù)的選項時,全局變量optarg會指向它的參數(shù)
    (d)當(dāng)函數(shù)分析完所有參數(shù)時,全局變量optind(into argv)會指向第一個‘非選項’的位置
    實踐小例子:
    view plaincopy to clipboardprint?
    #include <stdio.h>
    #include <getopt.h>
    char *l_opt_arg;
    char* const short_options = "nbl:";
    struct option long_options[] = {
    { "name", ? ? 0, ? NULL, ? ?'n' ? ? },
    { "bf_name", ?0, ? NULL, ? ?'b' ? ? },
    { "love", ? ? 1, ? NULL, ? ?'l' ? ? },
    { ? ? ?0, ? ? 0, ? ? 0, ? ? 0},
    };
    int main(int argc, char *argv[])
    {
    int c;
    while((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1)
    {
    switch (c)
    {
    case 'n':
    printf("My name is XL.\n");
    break;
    case 'b':
    printf("His name is ST.\n");
    break;
    case 'l':
    l_opt_arg = optarg;
    printf("Our love is %s!\n", l_opt_arg);
    break;
    }
    }
    return 0;
    }
    編譯并運行:
    [root@localhost liuxltest]# gcc -o getopt getopt.c
    [root@localhost liuxltest]# ./getopt -n -b -l forever
    My name is XL.
    His name is ST.
    Our love is forever!
    [root@localhost liuxltest]#
    [root@localhost liuxltest]# ./getopt -nb -l forever
    My name is XL.
    His name is ST.
    Our love is forever!
    [root@localhost liuxltest]# ./getopt -nbl forever
    My name is XL.
    His name is ST.
    Our love is forever!
    剛開始接觸 一些處理命令行參數(shù)的操作,開始不太明白,用例子測試了一下,感覺比以前明了多了。
    命令行參數(shù)有長參數(shù)如version, 還有短參數(shù) 如 v, 那么用這兩個都可以。程序處理的時候,會首先把長參數(shù)轉(zhuǎn)換成對應(yīng)的短參數(shù),如會把version轉(zhuǎn)成v, 再進(jìn)行 v 對應(yīng)的操作就可以了。
    命令行參數(shù)的選項,有的需要參數(shù),有的不需要參數(shù),或者有的參數(shù)是可選的,那么怎么區(qū)分呢?
    首先,對這些選項,如何組織起來? 是以字符串的形式組織起來了。如我有一個程序,有兩個選項,-a, -b, 我輸入的時候是 ?./a.out ?-a -b, 那么中間會處理成這種 ab這種字符串的形式,這個字符串就是所有的命令行的輸入選項。區(qū)別是否有參數(shù)就在于此。如果某個選項必須有參數(shù),則這一選項后有一個參數(shù),如果參數(shù)是可選的,則其后面有兩個冒號。如
    -a ?是沒有參數(shù)的, -b 后面必須有參數(shù), -c 后面是否有參數(shù)是可選的。則短的命令行選項是: ? ab:c::
    下面我們通過一個簡單的例子看一下。
    #include <stdio.h>
    #include <unistd.h>
    #include <getopt.h>
    char *l_opt_arg;
    const char* const short_options = "myl:";
    struct option long_options[] = {
    ? ? ? ? { "name", ? ? ?0, ? NULL, ? ?'m'}, //長選項對應(yīng)的短選項參數(shù), 第二個0表示選項后面無參數(shù), 1為有參數(shù),2為可選
    ? ? ? ? { "yourname", ?0, ? NULL, ? ?'y'},
    ? ? ? ? { "love", ? ? ?1, ? NULL, ? ?'l'},
    ? ? ? ? { ? ? ?0, ? ? ?0, ? ? ?0, ? ? 0},
    };
    int main(int argc, char *argv[])
    {
    ? ? ? ? int c, i;
    ? ? ? ? printf("before:\n");
    ? ? ? ? for (i = 1; i < argc; i++)
    ? ? ? ? ? ? ? ? printf("arg:%d\r\targv:%s\n", i, argv[i]);
    ? ? ? ? printf("\n");
    ? ? ? ? while((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1)
    ? ? ? ? {
    ? ? ? ? ? ? ? ?
    ? ? ? ? ? ? ? ? switch (c)
    ? ? ? ? ? ? ? ? {
    ? ? ? ? ? ? ? ? ? ? ? ? case 'm':
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("My name is A.\n");
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? ? ? ? ? case 'y':
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("His name is B.\n");
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? ? ? ? ? case 'l':
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? l_opt_arg = optarg;
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("Our love is %s!\n", l_opt_arg);
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? }
    ? ? ? ? }
    ? ? ? ? printf("optind:%d\n", optind);
    ? ? ? ? printf("\nafter:\n");
    ? ? ? ? for (i=1; i<argc; i++)
    ? ? ? ? ? ? ? ? printf("arg:%d\r\targv:%s\n", i, argv[i]);
    ? ? ? ? printf("................................\n");
    ? ? ? ? for (i = optind; i < argc; i++)
    ? ? ? ? ? ? ? ? printf("arg:%d\rargv:%s\n",i,argv[i]);
    ? ? ? ? return 0;
    }
    注意,此程序可接收的的選項有三個, 一個是m ,不帶參數(shù), y 不帶參數(shù), l ?要求有參數(shù)。
    那如果-m 不帶參數(shù),如果我寫了參數(shù),會怎么樣呢?下面看測試
    在調(diào)用 getopt_long 以后, optind 的值隨之變化 。在while循環(huán)后,我們再把開始的命令行參數(shù)打印出來,看一下有什么不同。
    把上面的代碼命名為: getopt_long.c
    編譯,可執(zhí)行文件為 a.out
    $ gcc ?getopt_long.c ??
    $ ./a.out -m -y
    before:
    arg:1 : -m
    arg:2 : -y
    My name is A.
    His name is B.
    optind:3
    after:
    arg:1 : -m
    arg:2 : -y
    $ ./a.out -m -y -l banana
    before:
    arg:1 : -m
    arg:2 : -y
    arg:3 : -l
    arg:4 : banana
    My name is A.
    His name is B.
    Our love is banana!
    optind:5
    after:
    arg:1 : -m
    arg:2 : -y
    arg:3 : -l
    arg:4 : banana
    $./a.out -m lisi -y zhangsan ?-l banana ?aaa
    before:
    arg:1 : -m
    arg:2 : lisi
    arg:3 : -y
    arg:4 : zhangsan
    arg:5 : -l
    arg:6 : banana
    arg:7 : aaa
    My name is A.
    His name is B.
    Our love is banana!
    optind:5
    after:
    arg:1 : -m
    arg:2 : -y
    arg:3 : -l
    arg:4 : banana
    arg:5 : lisi?arg:6 : zhangsan?arg:7 : aaa
    注意 argv 里面值的順序已經(jīng)和原來不一樣了,對命令行的參數(shù)重新組織了一下順序,也就是不認(rèn)識的命令行參數(shù),都放在了argv的最后,其中 optind 指向了這些沒有被解釋的參數(shù)的第一個。
    optind有作用吧!如果你想輸出哪些命令行參數(shù)沒有被識別,可以打印出來
    for (i=optind; i<argc; i++)
    printf("%s\n", argv[i]); ?即可
    附:如果是長參數(shù),則使用 --, 如 --help, 因為 -help時,(選項不需要參數(shù)的情況) 會把它當(dāng)成 四個選項, -h -e -l -p. 所以使用長參數(shù)時,要用兩個 橫線 --




    #include <getopt.h>
    #include <stdio.h>
    #include <stdlib.h>
    const char* program_name;
    void print_usage (FILE* stream, int exit_code)
    {
    ? ? ? ? fprintf (stream, "Usage: %s options [ inputfile ... ]\n", program_name);
    ? ? ? ? fprintf (stream, " -h --help ? ? ? ? ? ? ? ? ? ? ? 顯示這個幫助信息.\n"
    ? ? ? ? ? ? ? ? ? ? ? ? ?" -o --output filename 將輸出定位到文件.\n"
    ? ? ? ? ? ? ? ? ? ? ? ? ?" -v --version ? ? ? ? ? ? ? ? ?打印版本信息.\n");
    ? ? ? ? exit (exit_code);
    }


    int main (int argc, char* argv[])
    {
    ? ? ? ? int next_option;//下一個要處理的參數(shù)符號
    ? ? ? ? int haveargv = 0;//是否有我們要的正確參數(shù),一個標(biāo)識


    ? ? ? ?
    ? ? ? ? const char* const short_options = "ho:v";


    ? ? ? ?
    ? ? ? ? const struct option long_options[] = {
    ? ? ? ? ? ? ? ? { "help", ? ? ? ?0, ? ? NULL, ? ?'h' },
    ? ? ? ? ? ? ? ? { "output", ? ? ?1, ? ? NULL, ? ?'o' },
    ? ? ? ? ? ? ? ? { "version", ? ? 0, ? ? NULL, ? ?'v' },
    ? ? ? ? ? ? ? ? { NULL, ? ? ? ? ?0, ? ? NULL, ? ? 0 ?}};//最后一個元素標(biāo)識為NULL


    ? ? ? ?
    ? ? ? ? const char *output_filename = NULL;
    ? ? ? ?
    ? ? ? ? int verbose = 0;
    ? ? ? ?
    ? ? ? ? program_name = argv[0];


    ? ? ? ? do
    ? ? ? ? {
    ? ? ? ? ? ? ? ? next_option = getopt_long (argc, argv, short_options, long_options, NULL);
    ? ? ? ? ? ? ? ? switch (next_option)
    ? ? ? ? ? ? ? ? {
    ? ? ? ? ? ? ? ? ? ? ? ? case 'h': ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? haveargv = 1;
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? print_usage (stdout, 0);
    ? ? ? ? ? ? ? ? ? ? ? ? case 'o': ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? output_filename = optarg;
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? haveargv = 1;
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? ? ? ? ? case 'v': ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? verbose = 1;
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? haveargv = 1;
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? ? ? ? ? case ':': ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? ? ? ? ? case '?': ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? print_usage (stderr, 1);
    ? ? ? ? ? ? ? ? ? ? ? ? case -1: ? ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (!haveargv)
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? print_usage (stderr, 1);
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? ? ? ? ? default: ? ? ?
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? print_usage (stderr, 1);
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
    ? ? ? ? ? ? ? ? }
    ? ? ? ? }while (next_option != -1);


    ? ? ? ? printf("optind.................%d\n",optind);


    ? ? ? ? if (haveargv)
    ? ? ? ? {
    ? ? ? ? ? ? ? ? int i;
    ? ? ? ? ? ? ? ? for (i = optind; i < argc; ++i)
    ? ? ? ? ? ? ? ? printf ("Argument: %s\n", argv[i]);
    ? ? ? ? }


    ? ? ? ? return 0;
    }






    getopt的用法與optarg


    getopt被用來解析命令行選項參數(shù)。就不用自己寫東東處理argv了。
    #include <unistd.h>
    extern char *optarg; ?//選項的參數(shù)指針
    extern int optind, ? //下一次調(diào)用getopt的時,從optind存儲的位置處重新開始檢查選項。?
    extern int opterr, ?//當(dāng)opterr=0時,getopt不向stderr輸出錯誤信息。
    extern int optopt; ?//當(dāng)命令行選項字符不包括在optstring中或者選項缺少必要的參數(shù)時,該選項存儲在optopt中,getopt返回'?’、
    int getopt(int argc, char * const argv[], const char *optstring);
    調(diào)用一次,返回一個選項。 在命令行選項參數(shù)再也檢查不到optstring中包含的選項時,返回-1,同時optind儲存第一個不包含選項的命令行參數(shù)。
    首先說一下什么是選項,什么是參數(shù)。
    字符串optstring可以下列元素,
    1.單個字符,表示選項,
    2.單個字符后接一個冒號:表示該選項后必須跟一個參數(shù)。參數(shù)緊跟在選項后或者以空格隔開。該參數(shù)的指針賦給optarg。
    3 單個字符后跟兩個冒號,表示該選項后必須跟一個參數(shù)。參數(shù)必須緊跟在選項后不能以空格隔開。該參數(shù)的指針賦給optarg。(這個特性是GNU的擴(kuò)張)。
    getopt處理以'-’開頭的命令行參數(shù),如optstring="ab:c::d::",命令行為getopt.exe -a -b host -ckeke -d haha?
    在這個命令行參數(shù)中,-a和-h就是選項元素,去掉'-',a,b,c就是選項。host是b的參數(shù),keke是c的參數(shù)。但haha并不是d的參數(shù),因為它們中間有空格隔開。
    還要注意的是默認(rèn)情況下getopt會重新排列命令行參數(shù)的順序,所以到最后所有不包含選項的命令行參數(shù)都排到最后。
    如getopt.exe -a ima -b host -ckeke -d haha, 都最后命令行參數(shù)的順序是: -a -b host -ckeke -d ima haha
    如果optstring中的字符串以'+'加號開頭或者環(huán)境變量POSIXLY_CORRE被設(shè)置。那么一遇到不包含選項的命令行參數(shù),getopt就會停止,返回-1。
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    int main(int argc, char **argv)
    {
    int result;
    ? ? opterr = 0; ?//使getopt不行stderr輸出錯誤信息
    ? ? while( (result = getopt(argc, argv, "ab:c::")) != -1 )
    {
    switch(result)
    {
    case 'a':
    printf("option=a, optopt=%c, optarg=%s\n", optopt, optarg);
    break;
    case 'b':
    printf("option=b, optopt=%c, optarg=%s\n", optopt, optarg);
    break;
    case 'c':
    printf("option=c, optopt=%c, optarg=%s\n", optopt, optarg);
    break;
    case '?':
    printf("result=?, optopt=%c, optarg=%s\n", optopt, optarg);
    break;
    default:
    printf("default, result=%c\n",result);
    break;
    }
    printf("argv[%d]=%s\n", optind, argv[optind]);
    }
    printf("result=-1, optind=%d\n", optind); ? //看看最后optind的位置
    ? ? for(result = optind; result < argc; result++)
    printf("-----argv[%d]=%s\n", result, argv[result]);
    ?//看看最后的命令行參數(shù),看順序是否改變了哈。
    for(result = 1; result < argc; result++)
    printf("\nat the end-----argv[%d]=%s\n", result, argv[result]);
    return 0;
    }


    unistd里有個 optind 變量,每次getopt后,這個索引指向argv里當(dāng)前分析的字符串的下一個索引,因此
    argv[optind]就能得到下個字符串,通過判斷是否以 '-'開頭就可。下面是個測試程序
    #include <stdio.h>
    #include <unistd.h>
    int main(int argc, char* argv[])
    {
    int tmp = 4;


    while( (tmp = getopt(argc, argv, "abck")) != -1 ?)
    {


    printf("-%c\t", tmp);
    int opt = optind ;
    while( opt < argc )
    {
    if ( argv[opt][0] != '-' )
    {
    printf("%s\t", argv[opt]);
    opt ++;
    }
    else
    break;
    }
    printf("\n");
    }
    getchar();
    }














    函數(shù)說明 ?getopt()用來分析命令行參數(shù)。參數(shù)argc和argv是由main()傳遞的參數(shù)個數(shù)和內(nèi)容。參數(shù)optstring 則代表欲處理的選項字符串。此函數(shù)會返回在argv 中下一個的選項字母,此字母會對應(yīng)參數(shù)optstring 中的字母。如果選項字符串里的字母后接著冒號“:”,則表示還有相關(guān)的參數(shù),全域變量optarg 即會指向此額外參數(shù)。如果getopt()找不到符合的參數(shù)則會印出錯信息,并將全域變量optopt設(shè)為“?”字符,如果不希望getopt()印出錯 信息,則只要將全域變量opterr設(shè)為0即可。


    返回值 ?如果找到符合的參數(shù)則返回此參數(shù)字母,如果參數(shù)不包含在參數(shù)optstring 的選項字母則返回“?”字符,分析結(jié)束則返回-1。


    范例 ?#include<stdio.h>
    #include<unistd.h>
    int main(int argc,char **argv)
    {
    int ch;
    opterr = 0;
    while((ch = getopt(argc,argv,”a:bcde”))!= -1)
    switch(ch)
    {
    case ‘a(chǎn)’:
    printf(“option a:’%s’\n”,optarg);
    break;
    case ‘b’:
    printf(“option b :b\n”);
    break;
    default:
    printf(“other option :%c\n”,ch);
    }
    printf(“optopt +%c\n”,optopt);
    }


    執(zhí)行 ?$./getopt –b
    option b:b
    $./getopt –c
    other option:c
    $./getopt –a
    other option :?
    $./getopt –a12345
    option a:’12345’

    總結(jié)

    以上是生活随笔為你收集整理的va_list和vsnprintf、getopt的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲天堂av一区二区三区 | 天天操天天操天天 | 色网站免费 | 7m精品福利视频导航 | 欧美性xxxx图片 | 一二三四区在线 | 日韩激情视频在线 | 三级欧美视频 | 国产一级视频 | 中国毛片在线观看 | 4438成人网| 免费在线播放视频 | 久久久久久91 | 黄色小视频大全 | 国产嫩草影院久久久 | 国产精品久久久久久久久久免费看 | 欧美日韩不卡一区 | 西西人体做爰大胆gogo直播 | 国产免费自拍 | 91蝌蚪少妇 | 噜噜噜久久久 | 91娇羞白丝 | 男人午夜免费视频 | 欧美一区二区视频在线观看 | 美女操操操 | 狠狠撸视频 | 国产伦精品一区二区三区千人斩 | 欧美日韩999 | 亚洲成人a√| 男女无遮挡猛进猛出 | 伊人一区| 超碰成人久久 | 中文 欧美 日韩 | 伊人午夜 | 国产最爽的乱淫视频国语对白 | 国产porn| 中文字幕一区二区三区在线视频 | 午夜精品国产精品大乳美女 | 色欧美88888久久久久久影院 | 激情专区| 日本在线www | 波多野结衣av电影 | 91成人午夜 | 国产精品亚洲天堂 | 久综合网| 一区二区欧美日韩 | 爽妇综合网 | 超碰caopeng| 天天干天天天 | 精品一区二区三区无码按摩 | 高清视频在线播放 | 狠狠干2024 | 国产成人一区二区三区视频 | 国产成人av无码精品 | 爆乳2把你榨干哦ova在线观看 | 穿情趣内衣被c到高潮视频 欧美性猛交xxxx黑人猛交 | 国产福利片在线 | 免费荫蒂添的好舒服视频 | 日本乱论视频 | 久久人久久 | 国产日韩欧美精品 | 男人的天堂伊人 | 中文字幕av影视 | 在线国产小视频 | 精品一区二区免费 | 超碰国产97| 久久无码人妻一区二区三区 | 大奶骚 | 免费观看一级一片 | 人妻在客厅被c的呻吟 | 一区二区久久精品66国产精品 | 男女男精品视频 | 欧美性综合 | 国产精品传媒一区二区 | 国产精品视频免费观看 | 国产吞精囗交免费视频 | 国产一二视频 | 欧美激情在线观看一区 | 亚洲精品乱码久久久久久蜜桃不卡 | 老熟妇高潮一区二区高清视频 | 国产高清一区二区三区四区 | 禁片天堂 | 最近2019中文字幕大全第二页 | 狠狠视频| 亚洲v| 成人娱乐网 | 妺妺窝人体色WWW精品 | 国产亚洲久一区二区 | 亚洲资源在线 | 高清一区二区三区四区 | 精品免费一区二区三区 | 亚洲高清久久久 | 国产成人精品电影 | 91高清视频免费观看 | 高潮毛片又色又爽免费 | 在线播放网址 | www.色亚洲| 色哟哟视频在线观看 | 亚洲av永久无码精品 |