在恒定时间内修剪 C++ 字符串

Posted

技术标签:

【中文标题】在恒定时间内修剪 C++ 字符串【英文标题】:Trimming C++ string in constant time 【发布时间】:2019-12-07 02:10:48 【问题描述】:

是否有一种 STL/库方法可以在恒定时间内减小字符串大小(修剪它)。

在 C 中,这可以通过在最后一个索引后面添加 '\0' 来在恒定时间内完成。

C++ 调整大小的复杂性未定义,很可能是 O(N)

http://www.cplusplus.com/reference/string/string/resize/

【问题讨论】:

您从哪里获得这些信息?你有什么证据表明 C 可以在恒定时间内调整字符串的大小? std::string::resize 的复杂度在形式上是O(n)。然而,如果您在减小字符串大小时实际检查 C++ 库的实现,您会对该特定操作的实际复杂性感到非常惊讶。 是的,它是 O(n)。但它必须是,因为如果新的大小超过容量,它必须重新分配和复制。而且即使只是扩大了字符串,也必须初始化新的部分。当然,如果它没有变得更大,那么工作量是恒定的。顺便说一句:在 C++11 之前的 COW 字符串中,它必须是 O(n),在任何情况下都会由于修改而发生不共享。 【参考方案1】:

@SamVarshavchik 在 cmets 中很腼腆,但值得一提的是:在包括 libstdc++ 在内的许多实现中,std::string::resize() 将通过减少字符串的长度而不是重新分配 / 在恒定时间内减小字符串的大小/复制数据: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/basic_string.tcc 。 O(n) 的估计是如果你增加大小,强制重新分配和复制字符串。

另外,在 C++17 中,std::string_view 是粗略的不可变对应物,相当于通过敲击空字节来“修剪”C 字符串。它需要一个字符串的切片(指针 + 大小)而不复制其内容,然后您可以将它传递给各种 STL 函数或从流中打印它。

std::string hello_world = "hello world";
auto hello = std::string_view(hello_world.data(), 5);
std::cout << hello; // prints hello

需要注意的是 string_view 不拥有数据,因此一旦原始字符串超出范围,您将无法使用它,并且您不想以可能导致它的方式修改原始字符串重新分配。

【讨论】:

【参考方案2】:

C++17的方式,我们可以在O(1)内实现substr操作。

https://www.modernescpp.com/index.php/c-17-avoid-copying-with-std-string-view

std::string_view 也不要为大字符串分配堆内存。 std::string 在堆上分配内存,但 std::string 的例外情况是,MSVC 和 GCC 的大小为 15,Clang 的大小为 23。 std::string 上述大小未在堆上分配内存。

【讨论】:

以上是关于在恒定时间内修剪 C++ 字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何在恒定时间内替换字符串中的单个字符并且不使用额外空间?

如何在 C++ 中优雅地格式化字符串,使其四舍五入到小数点后 6 位,并修剪额外的 '0' 或 '9'

在恒定时间和线性空间中找到两个字符串的 LCP

在恒定时间内“拆分”矩阵

如何在oracle中删除部分字符串

UICollectionView 项目间距不是恒定的