如何strcpy并返回复制的字符数?
Posted
技术标签:
【中文标题】如何strcpy并返回复制的字符数?【英文标题】:How to strcpy and return number of copied characters? 【发布时间】:2016-03-27 22:37:34 【问题描述】:我想将一个以 null 结尾的字符串复制到另一个位置,并想知道复制的字符串有多长。效率是最重要的。有strcpy
函数可以实现,但它不返回实际复制了多少个字符。
当然,我可以通过简单地调用strlen
来检测复制字符串的长度来发现这一点,但这意味着再次遍历字符串中的字符,尽管strcpy
必须跟踪如何无论如何它复制了许多字符。出于性能原因,我不想要这样的第二次遍历。
我知道用简单的逐字符复制编写自己的strcpy
很容易,但我认为标准库可能会应用魔法,这使得strcpy
比简单的逐字符实现更快。
那么,strcpy
并接收复制的字符数而不再次遍历字符串的最佳方法是什么?
【问题讨论】:
strcpy
并不复杂,你可以自己写...
不明白如何使用 strcpy。如果您知道要复制的字符串的长度,请使用它,因为 strcpy 将始终从源字符串中复制所有字符(包括 null,因此它确实复制了 strlen(src)+1 个字符)。因为它是 C++,你可以使用 std::string。
你冷使用std::string
s,不用担心这个。
你为什么这么担心遍历字符串两次?这真的会导致您的代码出现性能问题,还是您过早地进行优化>?
@Barmar:我在主存数据库管理系统实现的核心中使用了这段代码。它很可能处于要执行的大量查询的热循环中。
【参考方案1】:
许多系统支持stpcpy
,它返回指向目标末尾的指针。您可以减去原始目标指针,这样您就可以得到长度。
【讨论】:
Here 表示返回的 char* 与 dest ... @Ben 您链接到strcpy
文档,但@Zbynek 指的是stpcpy
。
这确实很有用,但我想独立于平台。标准库中是否存在这样的函数?
@gexicide:不幸的是,没有扩展的基本 C 库非常有限。我相信我在 Windows 上也看到过类似的东西,但忘记了名字。【参考方案2】:
我会使用sprintf
来完成这项工作:
size_t len_strcpy(char *dest, char const *src)
return sprintf("%s", dest, src);
很难猜测这是否真的会比使用strcpy
后跟strlen
更慢或更快。以微软编译器为例,他们最近在sprintf
的实现上做了一些工作,所以(在英特尔上)它使用向量指令并且运行得非常快。使用旧版本的编译器,strcpy
/strlen
获胜的机会会更大。
【讨论】:
我想解析格式字符串可能不是最快的解决方案。 @gexicide:但是,正如答案中所指出的,实际上,至少使用一种广泛使用的实现,使用sprintf
(等等)进行一些字符串操作实际上比使用看起来应该更快的功能(在某些情况下有相当大的差距)。我目前找不到链接,但 STL 最近在一篇博客文章中提到了它。在任何情况下,它都会解析两个字符的格式字符串,因此除非解析器真的很慢(或者被复制的字符串非常短),否则它并不难获胜。【参考方案3】:
如果你真的需要这个,你自己写会很容易:
unsigned int lenstrcpy(char dest[], const char source[])
unsigned int i = 0;
while ((dest[i] = source[i]) != '\0')
i++;
return i;
Here is a live example.
【讨论】:
目前尚不清楚这是否会比使用strcpy()
然后strlen()
更快,因为这些功能针对目标平台进行了优化。
@Slava OP担心遍历字符串两次?这样就解决了这个问题?
@Ben 他担心速度,两次遍历可能会减慢速度,而不是不惜一切代价避免双重遍历
Slava 是对的,速度是我的目标。我知道编写自己的 strcpy
很容易,但我认为标准库可能会应用魔法,这使得 strcpy
比简单的逐字符实现更快。
@Slava 好的,看起来肯定会发生一些神奇的事情:ideone.com/PZTQu5【参考方案4】:
我会尝试这个 - 使用 strlen()
然后 memcpy()
但像往常一样,当您的目标是速度时,您最好在目标平台上测试它,因为理论上可能有很多因素难以计算。
已将 memcpy()
添加到 Ben 的 speed test
在 gcc 5.1.0 上,-O1 结果是:
第 1 部分:62181 - 手动复制 第 2 部分:195093 - strcpy/strlen 第 3 部分:45568 - strlen/memcpy第 1 部分和第 3 部分的 -O2 结果几乎没有变化,但第 2 部分发生了巨大变化:
第 1 部分:62234 第 2 部分:12129 第 3 部分:45565看起来 -O2 优化编译器消除了对 strlen()
的额外调用并使用了缓存值。
【讨论】:
【参考方案5】:标准 C 库不提供满足您需求的函数,因此您需要编写自己的函数。幸运的是,它并不太复杂:
size_t StrCpyLen(char *dest, const char *src)
const char *s = src;
while ((*dest++ = *s++))
;
return s - src - 1;
Demo.
上面的实现是从K&R中提炼出来的,做了一点小改动:不是直接使用src
,而是在运行循环之前进行复制,这样循环一次就可以通过减去原来的src
来确定长度完成。
【讨论】:
这种幼稚的逐字符实现是否与strcpy
一样有效,它可能会应用一些依赖于平台的魔法?
@gexicide 好吧,实现不应该与strcpy
本身进行比较,而是与strcpy
+strlen
背靠背进行比较。尽管它与strcpy
一样慢或更慢,但它胜过strcpy
+strlen
的可能性相当高,尤其是对于长字符串,当缓存开始发挥主要作用时。
迟到了,但这只是因为该示例中的字符串是编译时常量。只要您将str1
更改为动态字符串,strcpy
+ strlen
版本就会变得几乎慢一倍。 ideone.com/arie8e以上是关于如何strcpy并返回复制的字符数?的主要内容,如果未能解决你的问题,请参考以下文章