高级指针话题习题精讲

要求:

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;
}

效果:

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值