函数指针浅谈 -----表与函数指针完成命令行参数解析
个人认为C语言的精妙在于宏,指针。这使的C语言既可以与底层硬件打交道,又可以完成上层复杂的构架设计。而函数指针又是指针的一朵绚烂绽放的花。
所谓函数指针,就是一个指向函数地址的指针变量,虽然这只是一个变量,但是在C语言中,这个变量可以做很多事情。
下面是一个函数指针的声明:
void (* param_handler) (char *value);
大家可以看到
param_handler变量是指向下面函数类型的指针变量,这样,只要函数式满足下列条件,那么param_handler就可以指向它,执行指向的函数
void func (char *value);
在命令行参数解析和执行中,我们常常要对不同的参数和参数带的value进行解析,通常我们用if-elseif-else语句来处理,但是这样会使判断条件很长,代码的可读性很差,而且当我们需要加新功能时,会使代码更加乱。
我们可以分析一下,对不同参数的处理函数是不是大致长的差不多?可不可以抽象出来,提取一个公共的函数模板,然后让实现放在后面?
这个时候,函数指针就派上用场了。在C++中便是虚函数了。
当然,光函数指针是不够的,不然还是要在main函数中if-elseif-else,我们需要和参数绑定,这样我们可以循环地枚举,当匹配参数时,执行相应的函数。
下面是这个表元素的声明:
typedef struct
{
char short_param[2];
char full_param[64];
void (* param_handler) (char *value);
bool_t need_value;
} parameter_t;
下面是main函数中的枚举:
int main(int argc, char **argv)
{
int i, j;
for(j=1; j<argc; j++)
{
for(i=0; i<array_max_len(parameter_t); i++)
{
if(str_equal(param_array[i].short_param, argv[j]) ||
str_equal(param_array[i].full_param, argv[j]))
{
if(param_array[i].need_value)
{
param_array[i].param_handler(argv[++j]);
}
else
{
param_array[i].param_handler("");
}
}
}
}
return 0;
}
现在,在main函数的逻辑中,我们并知道有什么参数,相应的逻辑是什么?这样低耦合就满足,下面就是面向功能的实现了。
我们有如下需求:打印程序的版本,提供程序的帮助。以下我们可以轻松实现
void show_version(char *value)
{
printf("This is a test version 1.0-*T*\n");
}
void show_help(char *value)
{
printf("==============================\n");
printf("-v --version: show version of this\n");
printf("-h --help: show help of this\n");
printf("==============================\n");
}
现在我们需要绑定参数和参数的执行函数,我们可以在下面数据结构表的定义中定义。
下面是参数结构表:
#define parameter_t_max_c 2
parameter_t param_array[parameter_t_max_c] = {
{.short_param = "-v",
.param_handler = show_version,
.full_param = "--version",
.need_value = FALSE,
},
{
"-h", "--help", show_help, FALSE
},
};
^_^,我们可以执行了
neilhhw@neilhhw-laptop:/tmp$ ./test -v
This is a test version 1.0-*T*
neilhhw@neilhhw-laptop:/tmp$ ./test -v -h
This is a test version 1.0-*T*
==============================
-v --version: show version of this
-h --help: show help of this
-p --print: print the param value you input
==============================
根据需求我们需要一个打印用户输入的功能,那么我们只需要加一个针对这个功能的函数,然后新加一个绑定。完全不用动main函数的代码~~
void print_value(char *value)
{
printf("The value you input is: %s\n", value);
}
#define parameter_t_max_c 3
parameter_t param_array[parameter_t_max_c] = {
{.short_param = "-v",
.param_handler = show_version,
.full_param = "--version",
.need_value = FALSE,
},
{
"-h", "--help", show_help, FALSE
},
{
"-p", "--print", print_value, TRUE
},
};
附上全部代码:
#include <stdio.h>
typedef unsigned char bool_t;
#define TRUE 1
#define FALSE 0
typedef struct
{
char short_param[2];
char full_param[64];
void (* param_handler) (char *value);
bool_t need_value;
} parameter_t;
#include <stdlib.h>
#define str_equal(x, y) (strncmp(x, y, strlen(y)) == 0 ? 1 : 0)
#define array_max_len(x) x##_max_c
void show_version(char *value)
{
printf("This is a test version 1.0-*T*\n");
}
void show_help(char *value)
{
printf("==============================\n");
printf("-v --version: show version of this\n");
printf("-h --help: show help of this\n");
printf("-p --print: print the param value you input\n");
printf("==============================\n");
}
void print_value(char *value)
{
printf("The value you input is: %s\n", value);
}
#define parameter_t_max_c 3
parameter_t param_array[parameter_t_max_c] = {
{.short_param = "-v",
.param_handler = show_version,
.full_param = "--version",
.need_value = FALSE,
},
{
"-h", "--help", show_help, FALSE
},
{
"-p", "--print", print_value, TRUE
},
};
int main(int argc, char **argv)
{
int i, j;
for(j=1; j<argc; j++)
{
for(i=0; i<array_max_len(parameter_t); i++)
{
if(str_equal(param_array[i].short_param, argv[j]) ||
str_equal(param_array[i].full_param, argv[j]))
{
if(param_array[i].need_value)
{
param_array[i].param_handler(argv[++j]);
}
else
{
param_array[i].param_handler("");
}
}
}
}
return 0;
}
分享到:
相关推荐
`getopt()`函数是C语言中用于解析命令行参数的标准函数,主要应用于Unix/Linux系统,也可以在其他支持C语言的环境中使用。它简化了对带有选项和参数的命令行输入的处理,使得程序能够优雅地解析和理解用户提供的...
在本章中,我们将深入探讨一个实际应用案例:如何使用指针数组来处理命令行参数。命令行参数是用户在运行程序时通过操作系统命令行界面传递给程序的额外信息。 首先,理解什么是命令行参数。在图形用户界面(GUI)...
在讨论如何使MFC(Microsoft Foundation Classes)应用程序支持命令行参数之前,首先需要了解Windows命令行参数的基础知识。命令行参数是当用户通过命令提示符或通过其他程序启动应用程序时,传递给程序执行的参数。...
`getopt`函数是Linux系统中用于解析命令行参数的一个标准工具,它允许开发者处理带有选项和参数的命令行输入。本文将详细讲解`getopt`函数在C语言中的使用,同时也会提及bash脚本、Python和Go语言中的类似方法。 在...
在上述代码中,`CmdParaParser` 类的实例处理命令行参数,并且使用成员函数指针来解析特定参数。下面我们将详细探讨如何使用成员函数指针以及在给定的代码片段中它们是如何应用的。 首先,成员函数指针的声明和使用...
其中,`argc` 是命令行参数的个数,`argv` 是一个指向指针的指针,指向一个字符串数组。 在 `main` 函数中,可以通过循环遍历 `argv` 数组来访问每个命令行参数。例如: ```c void main(int argc, char argv) { ...
这一机制主要通过`CCommandLineInfo`类实现,该类定义了一系列成员变量和成员函数来支持命令行参数的解析与处理。 ##### `CCommandLineInfo`类成员介绍 - **`ParseParam`**: 成员函数,可以被重载以实现自定义的...
命令行参数简介与功能 命令行参数是计算机编程中的一种基本概念,它允许用户在命令行方式下输入参数,以控制程序的行为。在本文中,我们将深入探讨命令行参数的概念、功能和实现机理。 命令行参数的定义 命令行...
在`CWinApp`的派生类中,你可以重写`ParseCommandLine`函数来解析命令行参数。默认情况下,MFC会自动调用这个函数。如果你需要自定义参数解析逻辑,可以在该函数内进行。此外,你可以使用`GetCommandLine`函数获取...
- 引入了命令行参数的概念,以及如何通过指针来接收这些参数。 - 最后讨论了指向函数的指针以及复杂声明的用法。 ##### 第六章 - 结构体 - **章节内容:** - 6.1 结构体基础知识 - **解析:** - 本章初步介绍了...
- `void main(int argc, char *argv[])`是带参数的main函数形式,argc表示命令行参数的总数(包括命令本身),argv是一个字符指针数组,存储这些参数的字符串。 10. 常量定义: - 使用`const`关键字定义常量,如`...
在C语言中,命令行参数通常通过`main`函数的两个特殊参数来接收:`int argc` 和 `char *argv[]`。 - **`int argc`**:表示命令行参数的个数,包括程序本身的名字。 - **`char *argv[]`**:是一个字符指针数组,存储...
- 函数指针的声明与使用; - 回调函数的应用。 - **复杂的声明** - 混合使用指针与数组; - 指针数组与指向数组的指针的区别。 **第6章:结构体** - **结构体基础** - 结构体的定义与声明; - 结构体成员的...
`argc`表示命令行参数的总数(包括程序名本身),而`argv`是一个指向字符串(即每个参数)的指针数组。 在本例中,程序可能期望用户输入两个二进制数字作为参数,例如`./binary_adder 1010 1101`,其中`1010`和`...
本文将深入探讨MFC程序中接收并解析命令行参数的多种方法,以及如何利用MFC提供的`CCommandLineInfo`类来增强对命令行参数的支持。 ### 一、获取命令行参数的基本方法 #### 方法一:`GetCommandLine()` `...
指针数组与命令行参数 - **指针数组**:一个数组的元素为指针类型。 - **命令行参数**:通过命令行传递给程序的参数通常存储在一个字符指针数组中,可以通过指针进行访问。 - **二级指针**:指针的指针,可以用来...
10.6 main函数的形参:main函数可以接受命令行参数,这些参数作为字符串指针数组传递。 10.7 变步长梯形求积法中的指针变量:这可能涉及到使用指针在计算过程中动态改变步长或者处理复杂的数值计算。 总结来说,...
题目涵盖了指针的基础知识,包括指针变量的声明、指针的运算、数组和指针的关系、指针数组、函数指针等方面。 知识点 1:指针变量的声明 题目 1 和 2 涉及到指针变量的声明和初始化。指针变量的声明格式为 `type *...
- 学习`main`函数带参数的使用方法,了解命令行参数的处理方式。 - 熟悉不同类型的指针在实际编程中的应用场景。 #### 实验内容解析 实验中包含了三个具体的示例程序,分别针对不同层次的指针应用进行了演示: ...
进程用户空间的最高位置用于存放程序运行时的命令行参数及环境变量,在这段地址空间的下方和 bss 段的上方留有一个很大的空洞,其中堆栈和堆栈帧栖身其中。 现在,让我们来看一看堆栈帧的结构。典型的堆栈帧结构如...