大家做程序是不是都有图形界面, 我是极少做图形界面的, 因为在linux下写一个图形界面, 我还真不行!没办法,字符界面更酷,就用字符界面吧! 既然用字符界面,总得让基于字符界面的程序用起来也比较灵活与方便吧! 要想方便用户, 最好的方法是让程序接受灵活的参数或都良好的默认配置。最普通的方法有下面两种:
一、命令行参数解析
二、简单配置文件解析
在一个好的程序中,这两种方法应该都可用,下面我们这两种方案做一个大体上的论述。
一、命令行参数解析
1、基本方法
当程序运行时,传递参数使程序按用户的想法运行。
2、总体框架
传递参数是通过void main(int argc, char *argv[]),我们写一个专们处理参数的代码块,比如一个函数int parseCmdLine( int argc, char *argv[]),这样,将所有的命令行参数由该函数块处理。接下来程序应该对每一个参数及其参数值做分析,这一过程序可以用一个while与一个switch来完成.下面我们用一个简单事例来说明.
3、 简单示例
#define ALERT_NONE
#define ALERT_FULL
#define ALERT_FAST
// .......struct
globleVariable_T{
int alertMode;
int alertCmdOverride;
int deamonFlag;
int quiteFlag;
char *chrootDir;
char *groupName;
};
// ............
struct globleVariable GV;
char *progname;
char** progargs;
void DisplayBanner(void);
void ShowUsage(char *progname);
int ParseCmdLine(int argc, char* argv[]);
FaltalError();
void main(int argc, char *argv[])
{
//.......
progname=argv[0];
progargs=argv;
ParseCmdLine(argc,argv);
//.......
}
//......
extern char optarg; // for getopt,string option
extern char optind; // for getopt,current position
int ParseCmdLine(int argc, char* argv[])
{
int ch; // storage var for getopt info
while((ch=getopt(argc, argv, "AdC:t:vV?"))!=-1)
{
switch(ch)
{
case 'A':
// do it
if(!strncasecmp(optarg, "none", 4)
{
GV.alertMode=ALERT_NONE;
}
else if(!strncasecmp(optarg, "full",4)
{
GV.alertMode=ALERT_FULL;
}
else if(!strncasecmp(optarg "fast",4)
{
GV.alertMode=ALERT_FAST;
}
else
{
FatalError("Error=>Unknown command line alert option:%s\n",optarg);
}
Gv.alertCmdOverride=1;
break;
case 'd':
// do it
GV.deamonFlag=1;
GV.quiteFlag=1;
break;
case 'C':
// do it
if((GV.chrootDir=calloc(strlen(optarg)+1,1))==NULL)
{
FatalError("Error=>chroot directory variable calloc failed!\n",);
}
bcopy(optarg,GV.chrootDir,strlen(optarg));
break;
case 't':
//do it
break;
case 'v':
// do it
break;
case 'V':
// do it
DispalyBanner();
ShowUsage(progname);
exit(0);
case '?':
// do it
DisplayBanner();
exit(0);
default:
// do it;
}
}
}
//......
-------------------------------------------------------------------------
二、简单配置文件解析
1、基本方法
编写一系列专门用于读写配置文件的函数,这些函数可以读取配置文件中的选项的值,也应该能够修改选项的值。当然你可以用专用的一些语言来处理复杂的配置文件,比如说,grep,awk,perl,PBEST,N-CODE。
步骤1、既然程序中用了文件,那么文件放在哪儿好呢?
一般来讲应放在用户目录下面,那么首先让我们找到用户目录的绝对路径吧!
char* home = getenv("HOME");
if (!home) {
fprintf(stderr, "Environment variable "HOME" not defined!\n");
exit(1);
}
现在home指向用户目录的全路径。
步骤2、程序如何识别配置文件中,那些是选项,那些是选项的值呢?
就像磁盘被格式化后,才能使用一样,配置文件有一定的格式才能被程序识别。为了解决这个问题,在编写程序配置文件时,一定要遵守一些规则。常见的配置文件编写规则如下:
(1)、每一行一个选择项,每一个选择项只对应一个选项(一般而言)。
(2)、注释行以”#”号开头,不被解释。
(3)、空行没有意义,应当被忽略。
(4)、每一行的格式为:name = value
(5)、行首与行尾的空格、Tab应当被忽略。
(6)、当value不存在时,表示空字符串。
(7)、配置文件中出现两个相同的变量(name)时,应当打印出错误所在行与行的内容。
(8)、假如某一行中,行首无”#”,行中无”=”,则应该打印出配置文件语法错误的消息,同时打印出错误所在行与内容.
2、最常用的API
(1)、struct config_data* parse_config(char* file_name){
File *fd;
if(fd=fopen(file_name,"r")=NULL)
{
printf("error:can't open the parse config file in %d",__line__);
}
else
{
// do it
// like command line
}
打开配置文件(在用户根目录下),分析配置文件的内容,假如成功,返回一个struct config_data的指针.假如文件不能被打开,则返回NULL并且假如有任何错误则返回,并且打印出错误所在位置及其内容。
(2)、char* get_config_variable(struct config_data* conf_data, char* name);
返回要求的选项(char* name)的值,假如没有给出,则返回NULL,并报错。
(3)、void delete_config_data(struct config_data* conf_data);
删除给出的数据结构中所给出的选项的值,释放它所占据的内存。
(4)、int update_config_variable(struct config_data* conf_data, char* name, char* value);
更新给出的数据结构中选项名(char* name)的值(char* value)。假如成功则返回1,假如失败返回0。
(5)、int add_config_variable(struct config_data* conf_data, char* name, char* value);
向配置文件中加入给出的选择项,并赋给它值。假如成功则返回1,假如失败返回0。
(6)、int delete_config_variable(struct config_data* conf_data, char* name);
给出的选项从配置文件中删除。假如增加成功,则返回1,失败则返回0。
(7)、int write_config(struct config_data* conf_data, char* file_name);
将给出的配置信息写入到指定的配置文件中。假如文件不存在,则创建,并且编辑其内容,假如文件存在,则更新、修改、删除变量,保留注释行,保持行的顺序。假如选项是新的,就应该附加到文档未尾。
2、简单示例
比如说make ,所使用的Makefile文件之类,都是很好的例子.
Word教程网 | Excel教程网 | Dreamweaver教程网 | Fireworks教程网 | PPT教程网 | FLASH教程网 | PS教程网 |
HTML教程网 | DIV CSS教程网 | FLASH AS教程网 | ACCESS教程网 | SQL SERVER教程网 | C语言教程网 | JAVASCRIPT教程网 |
ASP教程网 | ASP.NET教程网 | CorelDraw教程网 |