在程式碼的撰寫過程當中,不可能一開始就寫得很複雜,一定是從簡單地判斷開始去做,發現有問題,就慢慢的一步一步堆疊上去。
1. 長選項,和短選項,先分開來測;
2. 每一個選項,我都挑2個選項來測;所以會有2種組合;
3. 因為在實務上,不太可能只接1個選項,可能是2個選項、3個選項,所以測試時,就以1個選項和2個選項來做為測試方法,所以也會有2種組合;
4. 因為選項後面,又可以再區分為有帶參數和沒帶參數,也是2種組合。
5. 綜合2~5點,我們會有2 * 2 * 2 = 8種組合。為了方便起見,所有選項後面的參數,就用1234和5678來表示。
getopt_long()函式所傳進去的第4個引數const struct option *longopts,是一個option的結構陣列;option結構的第2個成員int has_arg; 是決定這一個長選項是否要帶參數。從這一個差異點來著手,自己的測試命令列指令是:
Step I: 當長選項的has_arg為沒有參數 (0: no_argument)時:
01. ./main --author
02. ./main --force
03. ./main --author 1234
04. ./main --force 5678
05. ./main --author --force
06. ./main --author --force 5678
07. ./main --author 1234 --force
08. ./main --author 1234 --force 5678
Step II: 當長選項的has_arg為必有參數 (1: required_argument)時:
09. ./main --add
10. ./main --append
11. ./main --add 1234
12. ./main --append 5678
13. ./main --add --append
14. ./main --add --append 5678
15. ./main --add 1234 --append
16. ./main --add 1234 --append 5678
Step III: 當長選項的has_arg為可有參數 (2: optional_argument)時:
17. ./main --all
18. ./main --file
19. ./main --all 1234
20. ./main --file 5678
21. ./main --all --file
22. ./main --all --file 5678
23. ./main --all 1234 --file
24. ./main --all 1234 --file 5678
長選項的部份完成之後,再來看短選項的部份,也就是getopt_long()的第3個引數const char *optstring。
在這個引數當中,若選項後面沒有接冒號表沒有參數;反之則為必有參數。
Step IV: 當短選項為沒有參數 ()時:
25. ./main -X
26. ./main -Y
27. ./main -X 1234
28. ./main -Y 5678
29. ./main -X -Y
30. ./main -X -Y 5678
31. ./main -X 1234 -Y
32. ./main -X 1234 -Y 5678
Step V: 當短選項為必有參數 (:)時:
33. ./main -x
34. ./main -y
35. ./main -x 1234
36. ./main -y 5678
37. ./main -x -y
38. ./main -x -y 5678
39. ./main -x 1234 -y
40. ./main -x 1234 -y 5678
以上的5大項,都是在理想化的狀態之下做的實驗和測試;倘若使用者輸入不存在的選項呢?是否應該也要有相對應的防呆機制?
Step VI: 輸入一個不存在的長選項時:
41. ./main --ask
42. ./main --oops
43. ./main --ask 1234
44. ./main --oops 5678
45. ./main --ask --oops
46. ./main --ask --oops 5678
47. ./main --ask 1234 --oops
48. ./main --ask 1234 --oops 5678
Step VII: 輸入一個不存在的短選項時:
49. ./main -Q
50. ./main -r
51. ./main -Q 1234
52. ./main -r 5678
53. ./main -Q -r
54. ./main -Q -r 5678
55. ./main -Q 1234 -r
56. ./main -Q 1234 -r 5678
從Step I ~ VII的測試項目當中,不難發現:
a). getopt_long()函式在判斷命令列參數時,是以每一個參數是否為"--"或是'-'開頭。
b). 若為"--"開頭,表示長選項;有找到相對應的長選項,getopt_long()會回傳0。
c). 若為'-'開頭,表示短選項;有找到相對應的短選項,getopt_long()會回傳該字元。
d). 若連續2個選項寫在一起,如:"--author --force", "--author -Y", "-X --force", "-X -Y"等等,getopt_long()函式並不會判斷這是2個不同的選項;而是會判斷成"--force"是"--author"的參數。所以這一部份必須由程式設計師們去做一個防呆的判斷。
e). 無論長短選項,選項後面需要接上參數,而沒有接時,getopt_long()會回傳'?'字元。
f). 若是輸入不存在選項時,getopt_long()也會回傳'?'字元。
g). 綜合e). 和f). ,至於是何種原因導致getopt_long()回傳'?'字元,這也是由程式設計師來判斷。
理解以上a). ~ g). 的getopt_long()設計原則之後,我們就可以執行一個較為複雜的指令。就會得到一個很漂亮,完全符合我們預期的結果!
[root@localhost ~]# [root@localhost ~]# ./main --author --force 1234 --add 5678 --append --all 9012 --file -X 3456 -Y -x -y 7890 --ask 1234 --oops 5678 -Q 9012 -r 3456 You got a long option argv[1]: "--author". You got a long option argv[2]: "--force", but DOESN'T need argument argv[3]: "1234". You got a long option argv[4]: "--add" with an argument: argv[5]: "5678" The long option argv[6]: "--append" need an argument!! You got a long option argv[7]: "--all" with an argument: argv[8]: "9012". You got a long option argv[9]: "--file". You got a short option argv[10]: "-X", but DOESN'T need argument argv[11]: 3456 You got a short option argv[12]: "-Y". The short option argv[13]: "-x" need an argument!! You got a short option argv[14]: "-y" with an argument: argv[15]: "7890" ./main: unrecognized option '--ask' Unknown long option argv[16]: --ask // usage()函式內容省略! ./main: unrecognized option '--oops' Unknown long option argv[18]: --oops // usage()函式內容省略! ./main: invalid option -- 'Q' Unknown short option argv[20]: -Q // usage()函式內容省略! ./main: invalid option -- 'r' Unknown short option argv[22]: -r // usage()函式內容省略! [root@localhost ~]# [root@localhost ~]#(To be continue .... )
沒有留言:
張貼留言