gpt4 book ai didi

c - 仅回叫w'r't编程,为什么要使用?

转载 作者:行者123 更新时间:2023-11-30 20:38:17 24 4
gpt4 key购买 nike

关键是只说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 *);


上面的函数指针typedef创建一个 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com