当我们的程序需要运行在命令行环境下的时候,分解复杂的命令行参数往往成为一件不难但又麻烦的事情。我们经常发现.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) 阅读(2172)
评论(2) 编辑 收藏 引用 所属分类:
C++