要求:
5.编写代码处理命令行参数是十分乏味的,所以最好有一个标准函数来完成这项工作。但是不同的程序以不同的方式处理它们的参数,所以,这个函数必须非常灵活,以便使它能用于更多的程序。在本题中,你将编写这样一个函数。你的函数通过寻找和提取参数来提供灵活性。用户所提供的回调函数将执行实际的处理工作。下面是函数的原型。注意它的第四个参数和第五个参数是回调函数的原型。
char ** do_args(int argc, char **argv, char *control,
void (*do_arg)(int ch, char *value),
void (*illegal_arg)(int ch));
头两个参数就是main函数的参数,main函数对它们不做修改,直接传递给do_args,第三个参数是个字符串,用于标志程序期望接受的命令行参数。最后两个参数都是函数指针,它们是由用户提供的。do_args函数按照下面这样的方式处理命令行参数:
跳过程序名参数
while 下一次参数以一个横杆开头
对于参数横杠后面的每个字符
处理字符
返回一个指针,指向下一个参数指针
为了“处理字符”,你首先必须观察该字符是否位于control字符串内,如果它并不位于那里,调用illegal_arg指向函数,把这个字符作为参数传递过去。如果它位于control字符串内,但它的后面并不是跟一个+号,那么就调用do_arg所指向的函数,把这个字符和一个NULL指针作为参数传递过去。
如果该字符位于control字符串内并跟一个+号,那么就应该有一个值与这个字符相联系。如果当前参数还有其他字符,它们就是我们需要的值。否则,下一个参数才是这个值。在任何一种情况下,你应该调用do_arg所指向的函数,把这个字符和指向这个值的指针传递过去。如果不存在这个值(当前参数没有其他字符,且后面不再有参数),那么你应该调用Illegal_arg函数。注意:你必须保证这个值中的字符以后不会被处理。
当所有以一个横杆开头的参数被处理完毕后,你应该返回一个指向下一个命令行参数的指针的指针(也就是一个诸如&argv[4]或argv+4的值)。如果所有的命令行参数都以一个横杆开头,你就返回一个指向“命令行参数列表中结尾的NULL指针”的指针。
这个函数必须不能修改命令行参数指针,也不能修改参数本身,为了说明这一点,假定程序prog调用这个函数:下面的例子显示了几个不同集合的参数的执行结果。
预期效果:
代码编写:
#include <stdio.h>
#include <stdlib.h>
char a = 48;//用字符串0代表NULL指针
/*
FLAG处理这种情况:
你首先必须观察该字符是否位于control字符串内,如果它并不位于那里
调用illegal_arg指向函数,把这个字符把这个字符作为参数传递过去。
如果它位于control字符串内,但它的后面并不是跟一个+号,那么就调
用do_arg所指向的函数,把这个字符和一个NULL指针作为参数传递过去。
ARG处理这种情况:
如果该字符位于control字符串内并跟一个+号,那么就应该有一个值与这
个字符相联系。如果当前参数还有其他字符,它们就是我们需要的值。否则
下一个参数(指的是命令行参数)才是这个值。在任何一种情况下,你应该调
用do_arg所指向的函数,把这个字符和指向这个值,的指针传递过去。如果不存在这个值
(当前参数没有其他字符,且后面不再有参数),那么你应该调用Illegal_arg函数传入这个字符
NODE处理这种情况:
当所有以一个横杆开头的参数被处理完毕后,你应该返回一个指向下一个命令
行参数的指针的指针如果所有的命令行参数都以一个横杆开头,你就返回一个指向
“命令行参数列表中结尾的NULL指针”的指针
*/
enum {NONE, FLAG, ARG};
void do_arg(int ch, char* k)
{
}
void illegal_arg(int ch)
{
}
/* 处理control字符串,如果control字符匹配到命令行参数的字符,那
么就在检测当前字符是否有+,如果有就执行ARG这种情况,否则执行FLAG
例如命令行参数输入“ -x -y z”,control存在字符串“x”,先在control里面
匹配到x,接着检查x后面没有+,执行FLAG
*/
int argtype(register int ch, register char *control)
{
while(*control != '\0')
if(ch == *control++)
return *control == '+' ? ARG : FLAG;
return NONE;
}
/* argv指向的是各个命令行参数,例如命令行有“ -abcd -ef ghi jkl”
每次执行*++argv,就往下跳一个。比如第一个是-acd,执行*++argv,
就跳到-ef;执行*++argv,跳到ghi。执行*++argv就是跳到里面,比如使用
*++argv之后到-abcd,在执行*++argv,就得到a;执行*++argv就得到b
*/
char **do_args(int argc, char **argv, char *control,
void (*do_arg)(int ch, char *value),
void (*illegal_arg)(int ch))
{
register char *argp;
register int ch;
register int skip_arg;
while((argp = *++argv) != NULL && *argp == '-')
{
skip_arg = 0;
while(!skip_arg && (ch = *++执行*++argv) != '\0')
{
switch(argtype(ch, control))
{
case FLAG:
printf( "FLAG,ch:%c,value:%c\n",ch,a);
(*do_arg) (ch, &a);
break;
case ARG:
printf( "ARG," );
if(*++argp != '\0' || (argp = *++argv) != NULL)
{
printf("ch:%c,argp:%s\n", ch,argp);
(*do_arg)(ch, argp);
skip_arg = 1;
break;
}
printf( "illegal:%c\n", ch );
(*illegal_arg)(ch);
return argv;
case NONE:
printf( "NODE,illegal:%c\n", ch );
(*illegal_arg)(ch);
break;
}
}
}
return argv;
}
int main( int argc, char** argv )
{
*do_args( argc, argv, "x", do_arg, illegal_arg);
return 0;
}
效果: