如何在不使用 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;
}
然后终于可以用strcpy
和strcat
了,效果也差不多
#include <cstring>
char* func(char *buff1, char *buff2, char *outbuff)
{
strcpy(outbuff, buff1);
strcat(outbuff, buff2);
return outbuff;
}
这显然完全避免了任何循环和大小计算。但当然它们仍在发生,只是在 strcpy
和 strcat
函数内部。
这个最新版本与之前的两个版本有一处不同。带有 strcpy
和 strcat
的版本还将终止 '[=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;
}
我最近试图找到输入 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;
}
然后终于可以用strcpy
和strcat
了,效果也差不多
#include <cstring>
char* func(char *buff1, char *buff2, char *outbuff)
{
strcpy(outbuff, buff1);
strcat(outbuff, buff2);
return outbuff;
}
这显然完全避免了任何循环和大小计算。但当然它们仍在发生,只是在 strcpy
和 strcat
函数内部。
这个最新版本与之前的两个版本有一处不同。带有 strcpy
和 strcat
的版本还将终止 '[=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;
}