在C

时间:2016-07-12 01:05:16

标签: c string pointers recursion

我正在经历implementation! C中的 strcat 函数 我无法理解他们如何使用递归指针

以下是该来源的代码段。

char dest[100] = "I love";
char *src = "food";`

/* my_strcat(dest, src) copies data of src to dest. */
void my_strcat(char *dest, char *src)
{
  (*dest)? my_strcat(++dest, src): (*dest++ = *src++)? my_strcat(dest, src): 0 ;
}

2 个答案:

答案 0 :(得分:2)

这是一个非常差的实现,但我猜它 工作。如果目标字符串结束,则第一个?:测试。如果不是,它会碰撞目标指针,然后递归调用自身。如果目的地已经在结尾,则它会复制一个字符,使两个指针和测试都为零。如果那不是来自src的尾随NUL,那么它会使用更新的指针递归调用自己。

哦,等等,有一个错误(或者可能是“功能”)。它假定dest结束后的所有字符最初都填充了NUL s。我想你实际上可以利用它,如果你可以依赖实现继续拥有这个属性并且有一个带有NUL字符的文本的dest字符串,它将填充NUL中的src个{ {1}},一次一个字符。

这并不是说过度使用递归,这意味着堆栈中的调用帧数与结果字符串中的字符数一样多。你从哪里得到这个愚蠢的strcat实现?当然,没有真正的库可以使用这种实现,迭代变体更容易理解,也更快。

答案 1 :(得分:2)

将其分解成碎片:

(*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没有评论(也许它更具可读性):

if (*dest != '\0') {
  my_strcat(++dest, src);
} else {
  if ((*dest = *src) != '\0') {
    my_strcat(++ dest, ++ src);
  } else {
    return; 
  }
}