去年写了个小程序,把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
发表回复