當我們的程序需要運行在命令行環境下的時候,分解復雜的命令行參數往往成為一件不難但又麻煩的事情。我們經常發現.net的開發工具的命令行格式都是"/parameterA:valueA /parameterB:valueB"。如果我們希望使用這種格式的命令行參數的話,如何分析就成為我們需要解決的一個問題。
我們可以通過WinMain或者GetCommandLine()來獲得一個unicode格式的命令行參數。這個命令行參數是沒有被分析過的,一個完整的字符串。首先,我們使用空格分解字符串,不過在遇到雙引號的時候,我們忽略空格一直到遇到另一個雙引號為止。所以下面的命令行參數:
"e:\Coding\VL++\Tools\KfpCompiler\Debug\KfpCompiler.exe" /library:"C:\Kernel FP\Library\" /output:"C:\Kernel FP\Output\" /code:"C:\Kernel FP\Game\Project.kproj" /print-error /print-report
將會被分解成6行:
1 "e:\Coding\VL++\Tools\KfpCompiler\Debug\KfpCompiler.exe"
2 /library:"C:\Kernel FP\Library\"
3 /output:"C:\Kernel FP\Output\"
4 /code:"C:\Kernel FP\Game\Project.kproj"
5 /print-error
6 /print-report
對于每一行的命令,我們可以總結出以下幾種格式:
1、值
2、/參數
3、/參數:值
我們可以規定,如果值的第一個字符和最后一個字符都是雙引號的話,那么忽略這兩個雙引號。我使用Vczh GUI寫了一個win32程序顯示命令行分析的結果,代碼和截圖如下:
首先是程序的代碼。這個程序閱讀命令行參數之后,將分析結果顯示在一個文本框上:
1 #include "..\..\..\Library\Windows\VL_WinGUI.h"
2
3 using namespace vl;
4 using namespace vl::windows;
5 using namespace vl::windows::placement;
6
7 class MainForm : public VL_WinForm
8 {
9 protected:
10 VL_WinEdit* edtCommandLines;
11
12 void InitControls()
13 {
14 edtCommandLines=new VL_WinEdit(this,true);
15 edtCommandLines->SetVScroll(true);
16 edtCommandLines->SetHScroll(true);
17
18 ApplyPlacement(
19 pControl(edtCommandLines,10)
20 );
21
22 this->OnShow.Bind(this,&MainForm::MainForm_OnShow);
23 }
24
25 void MainForm_OnShow(VL_Base* Sender)
26 {
27 VL_WinParameters* Parameters=GetApplication()->GetParameters();
28 Parameters->Parse(L'/',L':');
29 VUnicodeString Output;
30
31 Output+=L"Command : ["+Parameters->GetCommandLineString()+L"]\r\n";
32 for(VInt i=0;i<Parameters->GetCount();i++)
33 {
34 Output+=L"Parameter : ["+Parameters->GetParameter(i)+L"]\r\n";
35 Output+=L"Value : ["+Parameters->GetValue(i)+L"]\r\n";
36 }
37 edtCommandLines->SetText(Output);
38 }
39
40 public:
41 MainForm():VL_WinForm(true)
42 {
43 SetClientWidth(400);
44 SetClientHeight(300);
45 SetBorder(vwfbSingle);
46 SetText(L"Command Lines");
47 InitControls();
48 MoveCenter();
49 }
50 };
51
52 void main()
53 {
54 (new MainForm)->Show();
55 GetApplication()->Run();
56 }
然后是運行結果:
程序中用到的VL_WinParameters類的代碼如下:
頭文件:
1 class VL_WinParameters : public VL_Base
2 {
3 protected:
4 class CommandPair
5 {
6 public:
7 typedef VL_List<CommandPair , false> List;
8
9 VUnicodeString Parameter;
10 VUnicodeString Value;
11 };
12
13 VUnicodeString FString;
14 CommandPair::List FCommands;
15 VWChar FParameterChar;
16 VWChar FValueChar;
17 VBool FParsed;
18 public:
19 VL_WinParameters(VUnicodeString Command);
20 ~VL_WinParameters();
21
22 VUnicodeString GetCommandLineString();
23 VInt GetCount();
24 VUnicodeString GetParameter(VInt Index);
25 VUnicodeString GetValue(VInt Index);
26 VBool IsParsed();
27 void Parse(VWChar ParameterChar , VWChar ValueChar);
28 };
實現文件:
1 VL_WinParameters::VL_WinParameters(VUnicodeString Command)
2 {
3 FString=Command;
4 FParsed=false;
5 FParameterChar=L'\0';
6 FValueChar=L'\0';
7 }
8
9 VL_WinParameters::~VL_WinParameters()
10 {
11 }
12
13 VUnicodeString VL_WinParameters::GetCommandLineString()
14 {
15 return FString;
16 }
17
18 VInt VL_WinParameters::GetCount()
19 {
20 return FCommands.GetCount();
21 }
22
23 VUnicodeString VL_WinParameters::GetParameter(VInt Index)
24 {
25 return FCommands[Index].Parameter;
26 }
27
28 VUnicodeString VL_WinParameters::GetValue(VInt Index)
29 {
30 return FCommands[Index].Value;
31 }
32
33 VBool VL_WinParameters::IsParsed()
34 {
35 return FParsed;
36 }
37
38 void VL_WinParameters::Parse(VWChar ParameterChar , VWChar ValueChar)
39 {
40 if(!ParameterChar || !ValueChar)return;
41 if(FParameterChar!=ParameterChar || FValueChar!=ValueChar)
42 {
43 FParameterChar=ParameterChar;
44 FValueChar=ValueChar;
45
46 FCommands.Clear();
47 VL_List<VUnicodeString , false> CommandStrings;
48 {
49 PCWChar Buffer=FString.Buffer();
50 VUnicodeString CurrentCommand;
51 VBool InString=false;
52
53 while(true)
54 {
55 if(InString)
56 {
57 switch(*Buffer)
58 {
59 case L'\0':
60 InString=false;
61 if(CurrentCommand!=L"")
62 {
63 CommandStrings.Add(CurrentCommand);
64 CurrentCommand=L"";
65 }
66 break;
67 case L'\"':
68 InString=false;
69 default:
70 CurrentCommand+=*Buffer;
71 }
72 }
73 else
74 {
75 switch(*Buffer)
76 {
77 case L' ':case L'\0':
78 if(CurrentCommand!=L"")
79 {
80 CommandStrings.Add(CurrentCommand);
81 CurrentCommand=L"";
82 }
83 break;
84 case L'\"':
85 InString=true;
86 default:
87 CurrentCommand+=*Buffer;
88 }
89 }
90 if(*Buffer)
91 {
92 Buffer++;
93 }
94 else
95 {
96 break;
97 }
98 }
99 }
100 for(VInt i=0;i<CommandStrings.GetCount();i++)
101 {
102 CommandPair Pair;
103 PCWChar Buffer=CommandStrings[i].Buffer();
104 if(*Buffer==FParameterChar)
105 {
106 Buffer++;
107 while(true)
108 {
109 if(*Buffer)
110 {
111 if(*Buffer==FValueChar)
112 {
113 Buffer++;
114 break;
115 }
116 else
117 {
118 Pair.Parameter+=*Buffer;
119 Buffer++;
120 }
121 }
122 else
123 {
124 break;
125 }
126 }
127 }
128 if(*Buffer)
129 {
130 Pair.Value=Buffer;
131 if(Pair.Value.Length()>=2 && Pair.Value.GetChar(0)==L'\"' && Pair.Value.GetChar(Pair.Value.Length()-1)==L'\"')
132 {
133 Pair.Value=Pair.Value.SubString(1,Pair.Value.Length()-2);
134 }
135 }
136 FCommands.Add(Pair);
137 }
138 FParsed=true;
139 }
140 }
posted on 2008-12-24 01:13
陳梓瀚(vczh) 閱讀(2184)
評論(2) 編輯 收藏 引用 所屬分類:
C++