- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
关键是只说w c,因为我对C更满意。
我不希望有一个示例说明它是如何工作的……我希望是为什么我们应该使用Call back函数或有人将其用作函数指针。
我也关注了许多博客和堆栈溢出问题,但对这些答案都不满意。
比方说(我在这里建议一种情况,例如排序),我们应该使用回调方法,其中方法/函数将花费更多时间进行处理。
假设一个进程只有一个线程,并且程序正在执行排序,这将花费大量时间(假设> 1分钟)。根据众多博客作者的说法,我们应该使用函数指针。但是,它将如何有用呢?
不管我们如何只有一个程序计数器,我们都会从CPU中获得一些时间来处理该进程,那么它将如何有用呢?
如果您认为还有其他示例可以解释函数指针的概念,请提供示例。
我看到一些提示,例如,如果您将使用函数指针,则可以稍后收集结果,但这听起来确实很尴尬!即使有可能怎么办?从函数返回后,如何从函数中收集内容?该功能将被销毁!
实时人们可以使用它来进行事件的任何更改,以便他们可以收到通知...(只需添加一个点)
我已经看到一些优秀的程序员使用此函数指针,我很想知道我为什么要使用它,当然这里有些我想念的东西...
请回复,在此先感谢。
最佳答案
由于您的上一则评论仍有一些不真实之处,因此也许有一个具体的例子来说明这些要点会有所帮助。让我们从一个简单的示例开始,该示例从命令行使用字符串作为用户输入(您也可以提示用户输入)。现在,我们要给用户提供选项,以告诉我们他们如何存储输入。就本示例而言,假设选项为(1)正常存储字符串,以使其水平打印在一行上;(2)存储与之相反的字符串,该字符串也将打印在一行上,(3)存储在每个字符后带有换行符的字符串,以便垂直打印;(4)将字符串与嵌入的换行符反向存储。
在解决此问题的常规方法中,您可能会编写一个switch
语句或一系列else if
语句,然后将字符串传递给4个不同的例程来处理不同的情况。函数指针使您可以稍微不同地解决问题。而不是使用4个不同的输入例程来处理每种情况,为什么不使用1个以函数指针作为参数并根据作为参数传递的函数来更改其处理字符串的方式的输入例程。输入例程可以很简单,例如复制字符串(防止修改argv[1]
等),然后将字符串作为参数传递给指针表示的函数:
/* make copy of original string, pass to callback function */
char *input (char *d, char *s, char *(*cbf)(char *))
{
strcpy (d, s);
return (*cbf) (d);
}
input
函数将目标字符串
d
,源字符串
s
和指向函数
cbf
的指针作为参数(回调函数的缩写)。让我们快速看一下函数指针的语法,并了解它告诉我们的内容:
char *(*cbf)(char *)
| | \
return | argument
type | list
|
function pointer
name/label
cbf
的函数指针的返回类型为
char *
,并接受类型为
char *
的单个参数。 (注意:在函子指针参数列表中仅指定类型,而不是在类型和参数名称中都指定-例如,不
char *str
,仅
char *
)现在每次传递时似乎要键入很多该类型的函数作为参数或在赋值中使用。它是。有一个简单的解决方案可以减少所需的键入。您可以将
typedef
用作函数指针,类似于将
typedef
与结构等一起使用的方法。创建
typedef
类型的
cbf
同样容易:
typedef char *(*cbf)(char *);
cbf
类型,该类型可以在需要函数指针类型的任何地方代替
char *(*cbf)(char *)
使用。使用typedef时,无需指定返回类型和参数列表,而且不必将函数指针放在括号内。这样可以将原始函数声明减少为:
char *input (char *d, char *s, cbf fname)
{
strcpy (d, s);
return fname (d);
}
typedef
不仅简化了将函数作为参数进行传递,而且还简化了函数指针数组的创建。可以根据需要使用函数指针数组简化选择和传递给定数量的函数中的任何一个。对于我们的
input
函数,我们创建一个函数指针数组,每个函数指针指向一个不同的函数,这些函数可用于将输入字符串设置为所需的格式。例如,假设上述4个函数具有如下声明:
/* input processing callback functions */
char *hfwd (char *s);
char *hrev (char *s);
char *vfwd (char *s);
char *vrev (char *s);
char *
类型的指针定义匹配,并接受
char *
类型的单个参数。使用我们的
cbf
typedef,我们可以轻松地创建一个称为
fnames
的函数指针数组,如下所示:
cbf fnames[] = { &hfwd, &hrev, &vfwd, &vrev };
fnames
数组通过数组索引选择我们的任何函数。 (例如
fnames[0]
是我们的函数
hfwd
)现在,这使我们能够从用户那里输入第二个数字,即数字,以选择输入字符串的格式。通过简单地将所需函数的数组索引作为命令行的第二个参数,就可以使用我们的任何回调函数。例如,可以通过调用以下程序来指定任何一种功能:
./progname my_string 1 /* to process the input with the hrev */
typedef
的情况下的全功能指针语法,但已注释,因此您可以比较/对比
typedef
的使用)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXS 128
/* typedef for function pointer */
typedef char *(*cbf)(char *);
/* simple string reverse function */
char *strrevstr (char *str);
/* input processing callback functions */
char *hfwd (char *s);
char *hrev (char *s);
char *vfwd (char *s);
char *vrev (char *s);
/* input function, pointer to function will determine behavior */
// char *input (char *d, char *s, char *(*cbf)(char *));
char *input (char *d, char *s, cbf fn);
int main (int argc, char **argv) {
if (argc < 3 ) {
fprintf (stderr, "error: insufficient input, usage: %s string int\n", argv[0]);
return 1;
}
int idx = atoi(argv[2]);
if (idx > 3 || idx < 0) {
fprintf (stderr, "error: invalid input -- out of range, (0 !< %d !< 3)\n", idx);
return 1;
}
cbf fnames[] = { &hfwd, &hrev, &vfwd, &vrev };
// char *(*fnames[])(char *) = { &hfwd, &hrev, &vfwd, &vrev };
char string[MAXS] = {0};
input (string, argv[1], fnames[idx]);
printf ("\nProcessed input ('%s' '%s'):\n\n%s\n\n", argv[1], argv[2], string);
return 0;
}
/* strrevstr - reverse string, original is not preserved. */
char *strrevstr (char *str)
{
if (!str) {
printf ("%s() error: invalid string\n", __func__);
return NULL;
}
char *begin = str;
char *end = str + strlen (str) - 1;
char tmp;
while (end > begin)
{
tmp = *end;
*end-- = *begin;
*begin++ = tmp;
}
return str;
}
/* string unchanged - print horizontal */
char *hfwd (char *s)
{ return s; }
/* string reversed - print horizontal */
char *hrev (char *s)
{ return strrevstr (s); }
/* string unchanged - print vertical */
char *vfwd (char *s)
{
char *p = s;
static char buf[MAXS] = {0};
char *b = buf;
while (*p)
{
*b++ = *p++;
*b++ = '\n';
}
*b = 0;
b = buf;
while (*b)
*s++ = *b++;
*b = 0;
return buf;
}
/* string reversed - print vertical */
char *vrev (char *s)
{
char *p = strrevstr (s);
static char buf[MAXS] = {0};
char *b = buf;
while (*p)
{
*b++ = *p++;
*b++ = '\n';
}
*b = 0;
b = buf;
while (*b)
*s++ = *b++;
*b = 0;
return buf;
}
/* make copy of original string, pass to callback function */
char *input (char *d, char *s, cbf fn)
// char *input (char *d, char *s, char *(*cbf)(char *))
{
strcpy (d, s);
return fn (d);
// return (*cbf) (d);
}
$ ( for i in {0..3}; do ./bin/fnc_pointer my_string $i; done )
Processed input ('my_string' '0'):
my_string
Processed input ('my_string' '1'):
gnirts_ym
Processed input ('my_string' '2'):
m
y
_
s
t
r
i
n
g
Processed input ('my_string' '3'):
g
n
i
r
t
s
_
y
m
关于c - 仅回叫w'r't编程,为什么要使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29729093/
我正在从 Stata 迁移到 R(plm 包),以便进行面板模型计量经济学。在 Stata 中,面板模型(例如随机效应)通常报告组内、组间和整体 R 平方。 I have found plm 随机效应
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我想要求用户输入整数值列表。用户可以输入单个值或一组多个值,如 1 2 3(spcae 或逗号分隔)然后使用输入的数据进行进一步计算。 我正在使用下面的代码 EXP <- as.integer(rea
当 R 使用分类变量执行回归时,它实际上是虚拟编码。也就是说,省略了一个级别作为基础或引用,并且回归公式包括所有其他级别的虚拟变量。但是,R 选择了哪一个作为引用,以及我如何影响这个选择? 具有四个级
这个问题基本上是我之前问过的问题的延伸:How to only print (adjusted) R-squared of regression model? 我想建立一个线性回归模型来预测具有 15
我在一台安装了多个软件包的 Linux 计算机上安装了 R。现在我正在另一台 Linux 计算机上设置 R。从他们的存储库安装 R 很容易,但我将不得不使用 安装许多包 install.package
我正在阅读 Hadley 的高级 R 编程,当它讨论字符的内存大小时,它说: R has a global string pool. This means that each unique strin
我们可以将 Shiny 代码写在两个单独的文件中,"ui.R"和 "server.R" , 或者我们可以将两个模块写入一个文件 "app.R"并调用函数shinyApp() 这两种方法中的任何一种在性
我正在使用 R 通过 RGP 包进行遗传编程。环境创造了解决问题的功能。我想将这些函数保存在它们自己的 .R 源文件中。我这辈子都想不通怎么办。我尝试过的一种方法是: bf_str = print(b
假设我创建了一个函数“function.r”,在编辑该函数后我必须通过 source('function.r') 重新加载到我的全局环境中。无论如何,每次我进行编辑时,我是否可以避免将其重新加载到我的
例如,test.R 是一个单行文件: $ cat test.R # print('Hello, world!') 我们可以通过Rscript test.R 或R CMD BATCH test.R 来
我知道我可以使用 Rmd 来构建包插图,但想知道是否可以更具体地使用 R Notebooks 来制作包插图。如果是这样,我需要将 R Notebooks 编写为包小插图有什么不同吗?我正在使用最新版本
我正在考虑使用 R 包的共享库进行 R 的站点安装。 多台计算机将访问该库,以便每个人共享相同的设置。 问题是我注意到有时您无法更新包,因为另一个 R 实例正在锁定库。我不能要求每个人都关闭它的 R
我知道如何从命令行启动 R 并执行表达式(例如, R -e 'print("hello")' )或从文件中获取输入(例如, R -f filename.r )。但是,在这两种情况下,R 都会运行文件中
我正在尝试使我当前的项目可重现,因此我正在创建一个主文档(最终是一个 .rmd 文件),用于调用和执行其他几个文档。这样我自己和其他调查员只需要打开和运行一个文件。 当前设置分为三层:主文件、2 个读
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 5年前关闭。 Improve this qu
我的 R 包中有以下描述文件 Package: blah Title: What the Package Does (one line, title case) Version: 0.0.0.9000
有没有办法更有效地编写以下语句?accel 是一个数据框。 accel[[2]]<- accel[[2]]-weighted.mean(accel[[2]]) accel[[3]]<- accel[[
例如,在尝试安装 R 包时 curl作为 usethis 的依赖项: * installing *source* package ‘curl’ ... ** package ‘curl’ succes
我想将一些软件作为一个包共享,但我的一些脚本似乎并不能很自然地作为函数运行。例如,考虑以下代码块,其中“raw.df”是一个包含离散和连续类型变量的数据框。函数“count.unique”和“squa
我是一名优秀的程序员,十分优秀!