在 C++ 中从字符串中删除标点符号的最有效方法

Most efficient way to remove punctuation marks from string in c++

我正在尝试找到从 C++ 中的字符串中删除标点符号的最有效方法,这就是我目前拥有的方法。

#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
#include <algorithm>

using namespace std;

void PARSE(string a);

int main()
{
    string f;
    PARSE(f);
    cout << f;
}

void PARSE(string a)
{
    a = "aBc!d:f'a";

    a.erase(remove_if(a.begin(), a.end(), ispunct), a.end());

    cout << a << endl;
}

有easier/more有效的方法吗?

我在考虑使用 str.len,获取字符串的长度,运行 通过 for 循环并检查 ispunct,如果是则删除。

没有字符串副本。没有堆分配。没有堆释放。

void strip_punct(string& inp)
{
    auto to = begin(inp);   
    for (auto from : inp)
        if (!ispunct(from)) 
            *to++ = from;
    inp.resize(distance(begin(inp), to));
}

比较:

void strip_punct_re(string& inp)
{
    inp.erase(remove_if(begin(inp), end(inp), ispunct), end(inp));
}

我创建了各种工作负载。作为基线输入,我创建了一个包含 32 到 127 之间所有字符值的字符串。我将这个字符串追加 num 次以创建我的测试字符串。我用测试字符串的副本调用了 strip_punctstrip_punct_re iters 次。我执行了这些工作负载 10 次,每次测试都在计时。在删除最低和最高结果后,我对时间进行了平均。我在 Microsoft Surface Book 4 (Skylake) 的 Windows 10 上使用 VS2015 的发布版本(优化)进行了测试。我 SetPriorityClass() 将过程 HIGH_PRIORITY_CLASS 并使用 QueryPerformanceFrequency/QueryPerformanceCounter 对结果进行计时。所有计时均在未连接调试器的情况下执行。

 num        iters      seconds      seconds (re)    improvement
10000        1000        2.812        2.947             4.78%  
 1000       10000        2.786        2.977             6.85%
  100      100000        2.809        2.952             5.09%

通过改变 num 和 iters 同时保持处理的字节数不变,我发现成本主要受处理的字节数的影响,而不是每次调用的开销。阅读反汇编证实了这一点。

所以这个版本快了 ~5% 并生成了 30% 的代码。