对大字符串的操作更快

时间:2013-04-01 08:06:25

标签: c++ string algorithm

假设我有一个很大的随机字符串......

_W:,aLH#J&A4=IY;    ?RVUc?W+</59JG4WSGW6G6$QEHQ:>,*b60$BYR=D=-^8-4(0    "??YaI0Y    SD9 FJ;MZ,V+'S]0:9L%;#a23cO%bMY[O6^S;ULRV2XA    8&  6_5W21E+Y$RYY$K"Q.0J+:cJC301M3H![7
L%K
Q5(4I9/9DAFR,-8<BJ=4H>9M,OX!.A4aQ:
BK<a"1ID.=U-US`R_])>GG)UL\!G?U$RRG_
HcW 3;<U5`X.?:6K@H*ZD3[M!ZU#KJXbE<Y*VV#ZYU#=]?Q
5:a^]#T

XRT.V]>57#W"U1=K$X]&JIY)::AE :K'7!_DV1B>SJ9D_`]>aC"N'US$;CaHK<N#-
"cJ,%RT)!J0DLFUb[[FOCQX(/.E3#
U
L$("+$) ;TDZ
;T#XS-'6U4`UKZ0a85D&+a]I.C/-7LDM_#/aS9OYA!#^G1II*XKL`;c
ES62Wa^=BQHK6E&A .X+4FDZ:   3UOaJ
#1<BY:;@D:`^`8E\-[9&7PXPH

... a lot more

我想对整个字符串进行操作,比如在冒号后插入换行符。

#include <iostream>
#include <cmath>
#include <algorithm>

int main()
{
    std::string buffer = "";
    std::string line = "";
    while (std::getline(std::cin, line))
        buffer += line + std::string("\n");

    auto it = std::find(buffer.begin(), buffer.end(), ';');
    while (it != buffer.end())
    {
        buffer.insert(it, '\n');
        it = std::find(it+1, buffer.end(), ';');
    }
    std::cout << buffer << std::endl;
    return 0;
}

这显然需要太长时间。我该怎么办?如果我把它们分成更小的字符串会更好吗?如果没有,我怎样才能让它更快?

修改

我是个白痴。我在这条线上有一个无限循环

- it = std::find(buffer.begin(), buffer.end(), ';');
+ it = std::find(it+1, buffer.end(), ';');

虽然我仍然赞扬那个提供了很好答案的人。

2 个答案:

答案 0 :(得分:1)

虽然我通常更喜欢使用C ++标准库,但在这种特殊情况下,我认为好的C风格的代码可能是更好的选择。

如果您要进行的处理只取决于一次解释一个字符(例如,在分号后插入换行符),则一次读取一个字符,然后写出一个(或两个,如果字符是如果输入和输出都被缓冲,则分号并且必须跟随另外的换行符将非常快。

如果字符n的处理仅取决于字符1n,那么类似的方法也可行 - 只需要预先决定处理操作基于到目前为止看到的字符或存储所有前面的字符,以便可以根据所有字符1n来决定操作。

在这两种情况下,都不需要在字符串的中间插入字符,因此必须移动大块的内存。

只有对字符n进行处理(例如,是否在该字符后插入字符)取决于字符n后面的字符,才有必要在处理之前读入所有文本它。即便如此,对于所有插入的字符,必须移动的内存量可以减少到不超过N个字符,其中N是已处理字符串的总长度(附加如果需要,可以使用如下函数:

void copyWithProcessing (char *from, char *to) {
    while (*from) {
        // do any pre-processing
        *to++ = *from++;
        // do any post-processing
     }
 }

这假设我们可以为to指向的字符数组预先分配足够的空间,因为我们事先知道由于即将发生的处理需要多少额外的字符。或者,如果我们不需要将结果字符串存储在内存中,我们可以在每个字符的处理完成后逐个字符地写出来,这意味着我们根本不需要为它分配任何空间。

答案 1 :(得分:1)

您不需要为此采用C风格的编程,在C ++中,您可以使用std::ostringstream作为结果,并在您阅读的每一行上立即插入换行符:

#include <iostream>
#include <string>
#include <sstream>

int main()
{
    std::ostringstream buffer;
    std::string line;
    while (std::getline(std::cin, line))
    {
        auto prev = 0;
        auto pos = line.find(';');
        while (pos != std::string::npos)
        {
            ++pos;
            buffer.write(&line[prev],pos-prev);
            buffer.put('\n');
            prev = pos;
            pos = line.find(';',pos);
        }
        buffer.write(&line[prev],line.size()-prev);
        buffer.put('\n');
    }

    std::cout << buffer.str() << std::endl;
    return 0;
 }