2013-04-12 77 views
0

我一直在更新我几乎两年前写过的程序,并且遇到了一个调用来从字符串中删除所有标点符号和空格。删除标点符号查询

该调用工作正常,但我不确定它是否是最有效的方法。

的代码行低于:

tempMessage.erase(remove_if(tempMessage.begin(), tempMessage.end(), (int(*)(int))ispunct), tempMessage.end()); 

我没有,我想出了这个或它是如何放在一起回味,但我希望能够充分理解这一呼吁。

我得到的std :: string.erase摆脱了第一个参数,直到第二个参数。我还可以看到remove_if是如何定义开始点和结束点的,但任何人都可以告诉我remove_if调用的第三个参数来自哪里?

我不记得为什么我的生活需要(int(*)(int))。

在查看代码时,任何人都可以改进它,或使其更高效吗?

谢谢

回答

1

首先,这一般不起作用;它似乎(并且它可能与一些编译器一起工作)。您无法将char传递给 一个参数版本ispunct,而不会产生未定义的 行为。

至于用于铸造的原因:标准同时定义了 一个参数ispunct功能两参数 ispunct函数模板。为了正确 实例化模板函数erase,编译器需要 来知道ispunct的确切类型。要知道 ispunct的确切类型,编译器需要能够在函数模板上进行类型推演 。为了进行类型推导,编译器需要知道预期的类型。在 中有一个循环依赖关系,其中明确的投射(或者看起来像 明确投射)解决。

,因为使用的ispunct结果的一个参数版本 未定义的行为,并使用两个参数版本不会 编译除非你提供额外的参数(使用 std::bind,例如),任何人做任何字符串处理 C++将已经写在他的工具箱 来处理这个功能对象,而且会写类似:

tempMessage.erase(
    std::remove_if(tempMessage.begin(), tempMessage.end(), IsPunct()), 
    tempMessage.end()); 

如何实现IsPunct要看你的需求与问候 进行本地化。最简单的版本就是:

struct IsPunct 
{ 
    bool operator()(char ch) const 
    { 
     return ::ispunct(static_cast<unsigned char>(ch)); 
    } 
}; 

使用ctype方面的locale版本是有点 更复杂(你可能希望它的 locale的副本,以及参考保持到面,只是为了确保 参考面不会消失)。

+0

看来我当时正在寻找一个快速解决方案,而且这样做的确如此。你能解释一下你在答案中定义的结构吗?它看起来像是返回true,如果char是一个punct字符,但我不明白ispunct调用之前的两个分号。我也不是很熟悉bool操作符()const的实现。你还可以扩展这个吗?麻烦抱歉。 – Matthew

+0

没问题。 '::'是一个范围解析运算符。它只是确保我们从''得到'ispunct',而不是另一个。 (这里不需要)'bool operator()(...)'是一个函数调用操作符:它意味着编译器可以像调用函数一样“调用”对象。这样的对象被称为功能对象或函子,并且广泛用于C++。 –

+0

只是为了我自己的清晰。如何将一个'char'传递给'int ispunct(int ch)'未定义的行为,但传递一个'unsigned char'是* not *?前者是否不在标准(4.5/4.7)中整体促销的结果范围内,如果不是,后者又如何? – WhozCraig