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

通话正常,但我不确定这是执行此操作的最有效方法。

代码行如下:

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


我不记得我在哪里提出这个问题或如何将其组合在一起,但是我希望能够完全理解这个电话。

我知道std :: string.erase摆脱了第一个参数,直到第二个参数。我还可以看到remove_if如何定义起点和终点,但是谁能告诉我remove_if调用中的第三个参数从何而来?

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

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

谢谢

最佳答案

首先,这通常不起作用;它似乎(并且它
可能适用于某些编译器)。您不能将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 ) );
    }
};


使用ctypelocale构面的版本有些不同
比较复杂(您可能希望它保留一份
locale以及对构面的引用,只是为了确保
所引用的构面不会消失)。

关于c++ - 删除标点查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15967516/

10-10 08:02