C++处理命令行选项

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

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注