Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
strcat函数在C语言中的递归实现_C_String_Pointers_Recursion - Fatal编程技术网

strcat函数在C语言中的递归实现

strcat函数在C语言中的递归实现,c,string,pointers,recursion,C,String,Pointers,Recursion,我正在经历一场灾难!strcat函数在C语言中的应用。 我无法理解他们是如何使用递归和指针的 下面是该源代码的代码片段。 这是一个相当糟糕的实现,但我想它确实有效。第一个?:测试目标字符串是否在末尾。如果没有,它会碰撞目标指针,然后递归地调用自身。如果目标已经在末尾,那么它将复制一个字符,使指针和测试都为零。如果这不是src的尾随NUL,那么它会使用更新的指针递归地调用自己 哦,等等,有一个bug(或者可能是一个“特性”)。它假定dest结束后的所有字符最初都用NULs填充。我想您实际上可以利用

我正在经历一场灾难!strcat函数在C语言中的应用。 我无法理解他们是如何使用递归和指针的

下面是该源代码的代码片段。


这是一个相当糟糕的实现,但我想它确实有效。第一个
?:
测试目标字符串是否在末尾。如果没有,它会碰撞目标指针,然后递归地调用自身。如果目标已经在末尾,那么它将复制一个字符,使指针和测试都为零。如果这不是src的尾随
NUL
,那么它会使用更新的指针递归地调用自己

哦,等等,有一个bug(或者可能是一个“特性”)。它假定dest结束后的所有字符最初都用
NUL
s填充。我想您实际上可以利用这一点,如果您可以依赖于实现继续具有此属性,并且有一个dest字符串,其中文本穿插着
NUL
字符,它将填充
src
中的
NUL
,一次一个字符


更不用说过度使用递归了,这意味着堆栈上的调用帧数量与结果字符串中的字符数量相同。你从哪里得到这个愚蠢的strcat实现的?当然,没有真正的库会使用这种实现,迭代变体更容易理解,而且速度更快。

这是一个非常糟糕的实现,但我想它确实可以工作。第一个
?:
测试目标字符串是否在末尾。如果没有,它会碰撞目标指针,然后递归地调用自身。如果目标已经在末尾,那么它将复制一个字符,使指针和测试都为零。如果这不是src的尾随
NUL
,那么它会使用更新的指针递归地调用自己

哦,等等,有一个bug(或者可能是一个“特性”)。它假定dest结束后的所有字符最初都用
NUL
s填充。我想您实际上可以利用这一点,如果您可以依赖于实现继续具有此属性,并且有一个dest字符串,其中文本穿插着
NUL
字符,它将填充
src
中的
NUL
,一次一个字符


更不用说过度使用递归了,这意味着堆栈上的调用帧数量与结果字符串中的字符数量相同。你从哪里得到这个愚蠢的strcat实现的?当然,没有真正的库会使用此实现,迭代变体更容易理解,而且速度更快。

将其分解为若干部分:

(*dest) /* Is *dest different than '\0' ? */
   ? my_strcat(++dest, src) /* *dest is different than '\0', so increment dest pointer so it'll point to the next character and call my_strcat() again. Here we're searching for the end of the string dest. */

   : (*dest++ = *src++) /* *dest is equal to '\0', so we're at the end of *dest... We start to assign *src to *dest and increment both pointers to point to the next character. The lvalue of this assignment is also a comparison (is it different than '\0' ?). */

     ? my_strcat(dest, src) /* The previous comparison is different than '\0', so we'll call my_strcat() again (pointers have already been incremented and they now point to the next character) */

     : 0; /* The previous comparison is '\0', so we've reached the end of the src, so we're done. */
用if/else替换三元运算符:

/* Is *dest different than '\0' ? */
if (*dest != '\0') {
  /* *dest is different than '\0', so increment dest pointer so it'll point to the next character and call my_strcat() again. Here we're searching for the end of the string dest. */
  my_strcat(++dest, src);
} else {
  /* *dest is equal to '\0', so we're at the end of *dest... We start to assign *src to *dest and increment both pointers to point to the next character. The lvalue of this assignment is also a comparison (is it different than '\0' ?). */
  if ((*dest = *src) != '\0') {
    /* The previous comparison is different than '\0', so we'll call my_strcat() again (pointers have already been incremented and they now point to the next character) */
    my_strcat(++ dest, ++ src); /* Moved increments down for readability */
  } else {
     /* The previous comparison is '\0', so we've reached the end of the src, so we're done. */
    return; 
  }
}
If/else无注释(可能更具可读性):


把它打碎:

(*dest) /* Is *dest different than '\0' ? */
   ? my_strcat(++dest, src) /* *dest is different than '\0', so increment dest pointer so it'll point to the next character and call my_strcat() again. Here we're searching for the end of the string dest. */

   : (*dest++ = *src++) /* *dest is equal to '\0', so we're at the end of *dest... We start to assign *src to *dest and increment both pointers to point to the next character. The lvalue of this assignment is also a comparison (is it different than '\0' ?). */

     ? my_strcat(dest, src) /* The previous comparison is different than '\0', so we'll call my_strcat() again (pointers have already been incremented and they now point to the next character) */

     : 0; /* The previous comparison is '\0', so we've reached the end of the src, so we're done. */
用if/else替换三元运算符:

/* Is *dest different than '\0' ? */
if (*dest != '\0') {
  /* *dest is different than '\0', so increment dest pointer so it'll point to the next character and call my_strcat() again. Here we're searching for the end of the string dest. */
  my_strcat(++dest, src);
} else {
  /* *dest is equal to '\0', so we're at the end of *dest... We start to assign *src to *dest and increment both pointers to point to the next character. The lvalue of this assignment is also a comparison (is it different than '\0' ?). */
  if ((*dest = *src) != '\0') {
    /* The previous comparison is different than '\0', so we'll call my_strcat() again (pointers have already been incremented and they now point to the next character) */
    my_strcat(++ dest, ++ src); /* Moved increments down for readability */
  } else {
     /* The previous comparison is '\0', so we've reached the end of the src, so we're done. */
    return; 
  }
}
If/else无注释(可能更具可读性):



你不明白的地方是什么?你考虑过发布一些关于好奇而不是实用性的帖子,因为他们想这样做是为了好玩看看你链接的页面标题,“为strcat()编写单行函数”。本页的重点是以一种不同寻常的方式为客户做事情fun@MAP虽然函数本身可能并不完美,但代码段作为一个整体是正确的。也就是说,
dest[100]
将用字符串后面的所有NUL填充。您不了解的是哪一位?考虑发布到哪个位置,它处理的是好奇而不是实用性,因为他们想这样做是为了好玩。请参阅您链接的页面标题,“为strcat()编写单行函数”。本页的重点是以一种不同寻常的方式为客户做事情fun@MAP虽然函数本身可能并不完美,但代码段作为一个整体是正确的。也就是说,
dest[100]
将用字符串后面的所有NUL填充。我提到了源代码的链接。是的,这是一个反问句。我想你是对的,有一个错误,因为所有字符都不能为空,它们将为零。但是如果它们是零,那么也没关系,不是吗?字符不能是空的,只有指针可以。字符是
NUL
,并且保证最后只有一个字符,数组的其余部分可以填充任何内容。顺便说一句,在几乎所有的实现中,
NULL
NUL
实际上都是零。@MAP
NUL
被ASCII规范定义为
0
。C规范只讨论值为零的字符,而不是NUL。我提到了源代码的链接。是的,这是一个反问句。我想你是对的,这是一个错误,因为所有字符都不能为零,它们将为零。但是如果它们是零,那么也没关系,不是吗?字符不能是空的,只有指针可以。字符是
NUL
,并且保证最后只有一个字符,数组的其余部分可以填充任何内容。顺便说一句,在几乎所有的实现中,
NULL
NUL
实际上都是零。@MAP
NUL
被ASCII规范定义为
0
。C规范只讨论值为零的字符,而不是NUL。