如何在不使用 while 循环的情况下查找 C 字符串的大小?

How to find the size of a C string without using a while loop?

我最近试图找到输入 C 字符串缓冲区的大小,以便在 memcpy 中使用它来将输入缓冲区的内容复制到输出缓冲区而不重叠。 以下是代码片段。

char * func(char *buff1, char *buff2, char *outbuff)
{
    int size = 0;
    while(*buff1 != '[=10=]')
     {
       size++;
       buff1++;
     }
   memcpy(outbuff, buff1, sizeof(char)*size);
   memcpy(outbuff + size, buff2, sizeof(char)*size);
   return outbuff; 
}

但是,我发现这是一种非常低效的查找大小的方法。如果你们知道任何其他替代方案,那将对我很有帮助。

编辑: 我不允许将它们的大小作为单独的参数传递。

您的问题没有解决方案。你要求像向量这样的东西,但向量只知道它们的大小,因为它们存储它。由于您似乎不允许更改函数的签名,因此循环是您唯一的选择。无论如何,对我来说它似乎没有那么低效。

你的代码确实有错误,当你计算 buff1 的大小时你调整了 buff1 指针,这样当你复制时它不再指向块的开始.您需要在复制之前减去缓冲区的大小。此外,您似乎假设您的两个输入缓冲区大小相同。

这似乎是您代码的更好版本。

char* func(char *buff1, char *buff2, char *outbuff)
{
    int size1 = 0;
    while (*buff1 != '[=10=]')
    {
        size1++;
        buff1++;
    }
    int size2 = 0;
    while (*buff2 != '[=10=]')
    {
        size2++;
        buff2++;
    }
    memcpy(outbuff, buff1 - size1, sizeof(char)*size1);
    memcpy(outbuff + size1, buff2 - size2, sizeof(char)*size2);
    return outbuff; 
}

您可以使用 strlen 来执行与上述代码相同的操作,但 strlen 也是一个循环。所以使用strlen的好处不是避免循环,只是代码更容易理解。

#include <cstring>

char* func(char *buff1, char *buff2, char *outbuff)
{
    int size1 = strlen(buff1);
    int size2 = strlen(buff2);
    memcpy(outbuff, buff1, sizeof(char)*size1);
    memcpy(outbuff + size1, buff2, sizeof(char)*size2);
    return outbuff; 
}

然后终于可以用strcpystrcat了,效果也差不多

#include <cstring>

char* func(char *buff1, char *buff2, char *outbuff)
{
    strcpy(outbuff, buff1);
    strcat(outbuff, buff2);
    return outbuff; 
}

这显然完全避免了任何循环和大小计算。但当然它们仍在发生,只是在 strcpystrcat 函数内部。

这个最新版本与之前的两个版本有一处不同。带有 strcpystrcat 的版本还将终止 '[=24=]' 字符复制到 outbuff,因此 outbuff 将被空终止,就像您假设 [=13] =] abd buff2 是。这对我来说似乎是一个优势,但你可能不同意。

C 字符串是以 null 结尾的字符数组。如果您的函数处理合法的 C 字符串,那么您应该使用标准字符串库。 例如,strlen(src)strcpy(dst,src)等。由于有时字符串会违反以0结尾的属性,因此标准字符串库提供了类似[=13]的函数=] 其中执行复制直到空终止字符,只要复制的字符数最多为 n

to copy the contents of the input buffers to the output buffer without overlapping.

因为复制是目标,"I found out that this is a very inefficient way of finding size." 被误导了。

效率是 O(n),即使找到大小可以在没有循环的情况下完成,因为副本需要 O(n)。 "very inefficient"属于O()较差的情况


而不是 运行 向下字符串两次,一次就足够了,因为缓冲区是不重叠的。

char * func(const char *buff1, const char *buff2, char *outbuff) {
  char *dest = outbuff;
  while(*buff1) {
    *dest++ = *buff1++;
  }
  while(*buff2) {
    *dest++ = *buff2++;
  }

  // more common to append a [=10=]
  *dest = '[=10=]';

  return outbuff; 
}