在使用linux時,與windows最大的不同應該就是常常使用指令行來解決大多數問題.比方以下這種:

而顯然我們知道C語言程式的入口是mian函數,即是從main函數開始運作,而main函數的原型是:
程式的 main 函數能夠通過參數 argc 和 argv 來訪問程式的參數清單(假設你不須要訪問參數清單,你能夠直接忽略它們)。
第一個參數 argc 訓示了指令行中參數的數量(這個值包括指令本身,假設後面沒有參數,則值為1)。
第二個參數 argv 是一個字元串數組。
其各個成員分别指向各個參數,即argv[0]指向指令本身,詳細見下圖.數組的大小由 argc 指定,而數組的元素則為各個指令行參數
的元素,表示以 NULL 結束的字元串形式。
使用指令行參數的過程是以被簡化為檢查 argc 和 argv 的内容。假設你對程式自己的名
字沒有興趣,記得跳過第一個參數.
以下的程式示範使用 argc 和 argv 的方法:
*/
if (argc > 1)
{
/* 有,那麼輸出這些參數。*/
int i;
printf ("The arguments are:\n");
for (i = 1; i < argc; ++i)
printf (" %s\n", argv[i]);
}
return 0;
結果例如以下:
差點兒全部 GNU/Linux 程式都遵循一些處理指令行參數的習慣。程式期望得到的參數能夠被分為兩種: 選項( options ,又作 flags ) 和其他(非選項)參數。選項用于調整程式的
行為方式,而其他參數提供了程式的輸入(比如,輸入檔案的名字)。
選項通常有兩種格式:
· 短選項( short options ) 由一個短杠(hyphen)和一個字元(通常為一個大寫或小寫字母)組成。短選項能夠友善使用者的輸入。
· 長選項( long options ) 由兩個短杠開始,之後尾随一個由大寫和小寫字母和短杠組成的名字。
長選項友善記憶和閱讀(尤其在腳本中使用的時候)
通常程式會為它支援的選項提供長短兩種形式,前者為便于使用者了解,而後者為簡化輸入。比如,多數程式都能了解 –h 和 –help 這兩個參數,并以同樣方法進行處理。一般而
言,當從 shell 中調用一個程式的時候,程式名後緊跟的就是選項參數。假設一些選項須要一個參數,則參數緊跟在選項之後。比如,很多程式将選項 –output foo 解釋為“将輸出文
件設定為 foo”。
在選項之後可能出現其他指令行參數,通經常使用于指明輸入檔案或輸入資料。
比如,指令行 ls –s / 列舉根檔案夾的内容。選項 –s 改變了 ls 的預設行為方式,通知它為每一個條目顯示檔案大小(以 KB 為機關)。
參數 / 向 ls 指明了被列舉的檔案夾。
選項 –size 與–s 選項具有同樣的含義,是以調用 ls –size / 會得到全然同樣的結果。
這時候我們就會發現一個問題,那就是假設參數比較多,并且要有一定的順序怎麼辦?
怎樣解析指令行的參數,推斷參數的位置和正确與否呢?
這就是這次要講的東西.
<code>getopt()</code> 函數位于 unistd.h 系統頭檔案裡。其原型如示:
給定了指令參數的數量 (<code>argc</code>)、指向這些參數的數組 (<code>argv</code>) 和選項字元串 (<code>optstring</code>) 後,<code>getopt()</code> 将傳回第一個選項,并設定一些全局變量。使用同樣的參數再次調用該函數時,它将傳回下一個選項。并設定對應的全局變量。假設不再有識别到的選項,将傳回 <code>-1</code>。此任務就完畢了。
<code>getopt()</code> 所設定的全局變量包含:
<code></code>
<code>optarg</code>——指向目前選項參數(假設有)的指針。
<code>optind</code>——再次調用 <code>getopt()</code> 時的下一個 argv 指針的索引。
<code>optopt</code>——最後一個已知選項。
對于每一個選項,選項字元串 (<code>optstring</code>) 中都包括一個相應的字元。
具有參數的選項後面跟有一個 <code>:</code> 字元。
當中optstrings 能夠使以下的元素:
1.單個字元,表示選項
2.單個字元後面一個冒号:表示該選項後面必須跟一個參數.參數緊跟在選項後面或者以空格隔開,該參數的指針賦給optarg.
3.單個字元後面跟兩個冒号:: ,表示該選項後面能夠跟一個參數.參數必須緊跟在選項後面不能以空格隔開.該參數一樣賦給optarg.
如,假設opstrings = "ab:c::d::",指令行參數例如以下:
這個指令行參數中,去掉短參數的-,當中a,b,c就是選項,host是b的參數,hello是c的參數,可是world不是d的參數,由于有空格隔開.
能夠反複調用 <code>getopt()</code>,直到其傳回 <code>-1</code> 為止;不論什麼剩下的指令行參數通常視為檔案名稱或程式對應的其它内容。
每運作一次,getopt函數将傳回查找到的指令行輸入的參數字元,并更新系統的全局變量,預設情況下,getopt函數會又一次排列指令行參數的順序,全部不可知的或者錯誤的指令行參數都排列到最後,getopt将傳回-1,同一時候optind存儲第一個未知的或者出錯的選項的下标.
以下我們看兩個示範樣例程式.
1.有一個程式有三個選項a,b,c,當中b必須帶參數,而c能夠帶能夠不帶.請寫一個程式使用getopt來解析這個程式的指令行參數.
以下是代碼示範樣例:
':
printf("result=?
, optopt=%c, optarg=%s\n", optopt, optarg);
break;
default:
printf("default, result=%c\n",result);
printf("argv[%d]=%s\n", optind, argv[optind]);
printf("result=-1, optind=%d\n", optind); // 列印最後有可能出錯的位置
for(result = optind; result < argc; result++) // 列印餘下的錯誤選項
printf("-----argv[%d]=%s\n", result, argv[result]);
for(result = 1; result < argc; result++) // 列印又一次排列的選項清單
printf("\nat the end-----argv[%d]=%s\n", result, argv[result]);
執行結果例如以下:
第一次指令行參數為:
解析的結果為:
其它的請自己嘗試吧,能夠嘗試一下沒有錯誤的,或者更加錯誤的,
2.一個假想的 doc2html 程式的指令行處理。
該 doc2html 程式将某種類型的文檔轉換為 HTML,詳細由使用者指定的指令行選項控制。它支援下面選項:
<code>-I</code>——不建立keyword索引。
<code>-l lang</code>——轉換為使用語言代碼 <code>lang</code> 指定的語言。
<code>-o outfile.html</code>——将經過轉換的文檔寫入到 outfile.html,而不是列印到标準輸出。
<code>-v</code>——進行轉換時提供具體資訊;能夠多次指定,以提高診斷級别。
将使用其它檔案名來作為輸入文檔。
還将支援 <code>-h</code> 和 <code>-?</code>。以列印幫助消息來提示各個選項的用途。
先将代碼貼例如以下:
display_usage();
/* You won't actually get here. */
opt = getopt( argc, argv, optString );
globalArgs.inputFiles = argv + optind;
globalArgs.numInputFiles = argc - optind;
convert_document();
return EXIT_SUCCESS;
以下分解上面的代碼:
頭檔案:
建立的 <code>globalArgs</code> 結構,用于以合理的方式存儲指令行選項。由于這是個全局變量,程式中不論什麼位置的代碼都能夠訪問這些變量。以确定是否建立keyword索引、生成何種語言等等事項。最好讓 <code>main()</code> 函數外的代碼将此結構視為一個常量、僅僅讀存儲區。由于程式的不論什麼部分都能夠依賴于其内容。每一個指令行選擇都有一個相應的選項,而其它變量用于存儲輸出檔案名稱、指向輸入檔案清單的指針和輸入檔案數量。
選項字元串 <code>optString</code> 告知 <code>getopt()</code> 能夠處理哪個選項以及哪個選項須要參數。
假設在處期間遇到了其它選項,<code>getopt()</code> 将顯示一個錯誤消息,程式将在顯示了用法消息後退出。
以下的代碼段包括一些從 <code>main()</code> 引用的使用方法消息函數和文檔轉換函數的小存根。
能夠對這些存根進行自由更改,以用于更為實用的目的。
最後,以下的代碼段中所看到的。在 <code>main()</code> 函數中使用此結構。和優秀的開發者一樣,須要首先初始化 <code>globalArgs</code> 結構,然後才開始處理指令行參數。在程式中。能夠借此設定在一定情況下合理的預設值。以便在以後有更合适的預設值時更友善地對其進行調整
以下的代碼段中的 <code>while</code> 循環和 <code>switch</code> 語句是用于本程式的指令行處理的代碼部分。僅僅要 <code>getopt()</code> 發現選項。<code>switch</code> 語句将确定找到的是哪個選項,将能在 <code>globalArgs</code> 結構中看到詳細情況。當 <code>getopt()</code> 終于傳回 <code>-1</code> 時,就完畢了選項處理過程,剩下的都是輸入檔案了。
既然已經完畢了參數和選項的收集工作,接下來就能夠運作程式所設計的不論什麼功能(在本例中是進行文檔轉換)。然後退出
當然上面的使用optget是簡單的指令行處理,假設你要進行長參數的或者略微複雜的處理,那就繼續往下看吧.<code>getopt_long()</code> 是同一時候支援長選項和短選項的<code>getopt()</code> 版本号。
getlongopt的原型是:
第一個參數是目前傳遞進來的參數個數,第二個參數是目前傳遞進來的參數清單,第三個參數是目前程序全部可支援的短參數的字元串,第四個參數是struct option,表示全部的長參數的相應關系.
結構體聲明例如以下:
name 成員是指向長選項名稱(帶兩個短橫線)的指針。has_arg 成員設定為 no_argument、optional_argument, 或 required_argument(均在 getopt.h 中定義)之中的一個。以訓示選項是否具有參數。假設 flag 成員未設定為 NULL。在處理期間遇到此選項時。會使用 val 成員的值填充它所指向的 int 值。假設 flag 成員為 NULL。在 getopt_long() 遇到此選項時,将傳回 val 中的值;通過将 val 設定為選項的 short 參數,能夠在不加入不論什麼其它代碼的情況下使用 getopt_long()——處理 while loop 和 switch 的現有 getopt() 将自己主動處理此選項。
這已經變得更為靈活了,由于各個選項如今能夠具有可選參數了。更重要的是。僅須要進行非常少的工作,就能夠友善地放入現有代碼中。
此函數的傳回情況例如以下:
1.在使用此函數處理一個參數時,全局變量optarg指向下一個要處理的變量,并傳回struct option的第四個成員.普通情況下,假設struct option的第三個參數位置設定null,第四個參數一般設定為該長選項相應的短選項的字元值,即傳回相應的短選項字元.
2.假設解析完最後一個成員将傳回1
3.假設getlongopt遇到一個錯誤的選項,他将列印一個錯誤消息并傳回'?'
4.當get_long解析一個長選項而且發現後面沒有參數則傳回':',表示缺少參數.
應用舉例.
1.一個程式的所需的短選項和長選項例如以下:
在這個程式中,首先須要确定兩個結構:
1,一個字元串,包括所須要的短選項字元,假設選項後面有參數,字元後面加一個冒号:.本例中,這個字元串應該是:"ho:v",由于-o後面有參數filename,是以要加冒号.
2,一個包括長選項的結構體數組.每一個結構體四個域.
第一個域為長選項字元串.第二個域為表示對應的選項是否需要參數,僅僅能為0,沒有參數,1,必需要,2,能夠要.第三個域決定傳回結果類型(即是flags,建議設null),假設為null,則此函數将傳回後一個域(即val,一般設定為目前擷取的短參數值),否則,此函數将傳回0.第四個域為函數的傳回值,一般設定為對用的短選項的ascii值.
另外,結構體數組的最後一個元素所有設定為null和0,表示結束.
結構體能夠例如以下所看到的:
下面是程式的代碼:
print_usage (stderr, 1); // unknow
default: // else
print_usage (stderr, 1);
}while (next_option !=-1);
以下是測試結果:
1.指令行:
2.對上面的轉換程式的改動:
<code>getopt_long()</code> 函數在 <code>getopt.h</code> 頭檔案(而非 <code>unistd.h</code>)中,是以将須要将該頭檔案包括進來。我還包括了 <code>string.h</code>。由于将稍後使用 <code>strcmp()</code> 來幫助确定處理的是哪個長參數。
其它頭檔案
已經為 <code>--randomize</code> 選項在 <code>globalArgs</code> 中加入了一個标志。并建立了 <code>longOpts</code> 數組來存儲關于此程式支援的長選項的資訊。除了 <code>--randomize</code> 外。全部的參數都與現有短選項相應(比如,<code>--no-index</code> 等同于 <code>-I</code>)。通過在選項結構中包括其短選項等效項,能夠在不向程式加入不論什麼其它代碼的情況下處理等效的長選項。
擴充後的參數
新的經改進的選項處理
我還加入了 <code>0</code> 的 case,以便處理不論什麼不與現有短選項比對的長選項。在此例中,僅僅有一個長選項。但代碼仍然使用 <code>strcmp()</code> 來確定它是預期的那個選項。
這樣就所有搞定了;程式如今支援更為具體(對暫時使用者更加友好)的長選項。
UNIX 使用者始終依賴于指令行參數來改動程式的行為。特别是那些設計作為小工具集合 (UNIX 外殼環境)的一部分使用的有用工具更是如此。
程式須要可以高速處理各個選項和參數,且要求不會浪費開發者的太多時間。畢竟,差點兒沒有程式設計為僅處理指令行參數,開發者更應該将精力放在程式所實際進行的工作上。
<code>getopt()</code> 函數是一個标準庫調用,可同意使用直接的 while/switch 語句友善地逐個處理指令行參數和檢測選項(帶或不帶附加的參數)。與其類似的 <code>getopt_long()</code> 同意在差點兒不進行額外工作的情況下處理更具描寫叙述性的長選項,這很受開發者的歡迎。
既然已經知道了怎樣友善地處理指令行選項,如今就能夠集中精力改程序式的指令行,能夠加入長選項支援。或加入之前因為不想向程式加入額外的指令行選項處理而擱置的不論什麼其它選項。
不要忘記在某處記錄全部的選項和參數,并提供某種類型的内置幫助函數來為健忘的使用者提供幫助。
linux進階程式設計 楊宗德
http://www.ibm.com/developerworks/cn/aix/library/au-unix-getopt.html
轉載請注明出處.http://blog.csdn.net/suool/article/details/38089001
The Next:
1. ANSI C檔案I/O管理
2. POSIX檔案以及檔案夾管理
3. Linux下的一些編碼特性和規範
4. Python 兩大網絡架構
5. network programming.
版權聲明:本文部落格原創文章,部落格,未經同意,不得轉載。
本文轉自mfrbuaa部落格園部落格,原文連結:http://www.cnblogs.com/mfrbuaa/p/4679874.html,如需轉載請自行聯系原作者