去年写了个小程序,把qq围棋的wgs格式的棋谱转换为sgf格式,当时直接是cin文件路径,wgs那么变态的文件名,每次转换前都要先重命名才方便转换。还有一点,有很多棋谱要转时不方便,得一个个的输入。想到linux上很多工具,一般都是接收选项和参数的,可以用通配符匹配所有同类型文件,很是方便,于是查了些资料,发现实现起来其实很简单。
这里用到了main()函数的命令行处理选项,C/C++语言中有关命令行参数涉及到程序的主函数main(int argc,char *argv[])这样两个参数,其中int argc表示命令行参数的个数(包括可执行程序名本身),char *argv[]表示每个参数的具体内容,argv[0]为命令行中可执行程序名本身,argv[1]为命令行中第二个参数的内容,依次类推。(表示很早就看到过这两个参数,可是一直不明白意思,C++ Primer 7.2.6节介绍了处理命令行选项的内容。)
输出命令行参数个数及参数内容的例程:
#include<iostream>
using namespace std;
int main(int argc,char* argv[])
{
cout<<"argc = "<<argc<<endl;
for(int i=0;i<argc; ++i)
cout<<"argv["<<i<<"] = "<<argv[i]<<endl;
return 0;
}
执行结果:
$ ./argv.exe hello world ! argc = 4 argv[0] = g:\weiqi\argv.exe argv[1] = hello argv[2] = world argv[3] = !
在命令行参数的提交中,系统会自动给指针数组后加上一个NULL,所以上面的代码可以写成如下简单形式,简化代码提高效率。(1)
#include<iostream>
using namespace std;
int main(int argc,char* argv[])
{
cout<<"argc = "<<argc<<endl;
while(*argv!=NULL)
cout<<*argv++<<endl;
return 0;
}
棋谱转换程序下篇博文发出,这里只发一下使用通配符转换的log:
$ ./wgs2sgf.exe *.wgs 转换成功,已保存为: qqgo_1.wgs.sgf 转换成功,已保存为: qqgo_10.wgs.sgf 转换成功,已保存为: qqgo_11.wgs.sgf 转换成功,已保存为: qqgo_12.wgs.sgf 转换成功,已保存为: qqgo_2.wgs.sgf 转换成功,已保存为: qqgo_3.wgs.sgf 转换成功,已保存为: qqgo_4.wgs.sgf 转换成功,已保存为: qqgo_5.wgs.sgf 转换成功,已保存为: qqgo_6.wgs.sgf 转换成功,已保存为: qqgo_7.wgs.sgf 转换成功,已保存为: qqgo_8.wgs.sgf 转换成功,已保存为: qqgo_9.wgs.sgf
下面摘录一个例程,该程序用于取出在argv中的命令行选项。在例子中,将支持下列用法:
program_name [-d] [-h] [-v] [-o output_file] [-l limit_value] file_name [file_name [file_name [...]]]。
加括号的内容是可选的。具体步骤见程序:(2)
//C/C++处理main()函数命令行
#include <iostream>
#include <vector>
#include <string>
#include <ctype.h>//调用atoi函数
#include <cstdlib>
using namespace std;
const char* const prog_name = "prog";
const char* const prog_version = "version 1.0 (2011/8/24)";
//退出函数
inline void usage(int exit_value = 0){
cerr<<prog_name<<" usage!"<<endl;
exit(exit_value);
}
int main(int argc,char* argv[]){
//声明用于记录用户指定选项的变量
bool debug_on = false;
bool ofile_on = false;
bool limit_on = false;
string ofile_name;//记录出现的输出文件名
int limit = -1;//限制值
vector <string> file_names;//记录文件名
cout<<"argc:"<<argc<<endl;
for(int i = 1;i < argc; ++i){//读取argv中的每个选项
//输出第i+1个参量
cout<<"argv["<<i<<"]:"<<argv[i]<<endl;
char *pchar = argv[i];
switch(pchar[0]){//确定选项类型:-h,-d,-v,-l,-o;或者其他
case '-':{
cout<<"case \'-\' found"<<endl;
switch(pchar[1]){//确定用户指定的选项:h,d,v,l,o
case 'd'://处理调试:
cout<<"-d found:debugging turned on!"<<endl;
debug_on = true;
break;
case 'v'://处理版本请求
cout<<"-v found:version info displayed!"<<endl;
cout<<prog_name<<":"<<prog_version<<endl;
return 0;
case 'h'://处理帮助
cout<<"-h found:help info!"<<endl;
usage();
case 'o'://处理输出文件
cout<<"-o found:output file!"<<endl;
ofile_on = true;
break;
case 'l'://处理限制量
cout<<"-l found:resorce limit!"<<endl;
limit_on = true;
break;
default://无法识别的选项
cerr<<prog_name<<":error:unrecognition option -:"<<pchar<<endl;
usage(-1);
}
break;
}
default://不以'-'开头,是文件名
if(ofile_on){//输出文件名
cout<<"file name:"<<pchar<<endl;
ofile_name = pchar;
ofile_on = false;//复位
}
else if(limit_on){//限制值
limit_on = false;
limit = atoi(pchar);
if(limit<0){
cerr<<prog_name<<":error:negative value for limit!"<<endl;
usage(-2);
}
}
else{//文件名
file_names.push_back(pchar);
}
break;
}
}
if(file_names.empty()){
cerr<<prog_name<<":error:no file for processing!"<<endl;
usage(3);
}
else{
cout<<(file_names.size() == 1 ? "File":"Files")<<
" to be processed are the followed:"<<endl;
for(int i = 0;i < file_names.size();++i){
cout<<file_names[i]<<"\t"<<endl;
}
}
if(limit != -1){
cout<<"user-specified limit:"<<limit<<endl;
}
if(!ofile_name.empty()){
cout<<"user-specified ofile:"<<ofile_name<<endl;
}
}
参考资料:
(1).C/C++中命令行参数,http://hi.baidu.com/xun1573/item/76af410956754933a2332a66
(2).C++ main():处理命令行选项,http://www.cnblogs.com/xiajun/archive/2011/08/24/2298651.html
发表回复