我一直在更新我将近两年前编写的程序,我遇到了一个要求从字符串中删除所有标点符号和空格的调用。
调用正常,但我不确定这是最有效的方法。
代码行如下:
tempMessage.erase(remove_if(tempMessage.begin(), tempMessage.end(), (int(*)(int))ispunct), tempMessage.end());
我不记得我是从哪里想到这个的,或者它是如何组合在一起的,但我希望能够完全理解这个调用。
我知道 std::string.erase 删除了第一个参数,直到第二个参数。我还可以看到 remove_if 如何定义起点和终点,但谁能告诉我 remove_if 调用中的第三个参数来自哪里?
我不记得为什么我的生活需要 (int(*)(int))。
当您查看代码时,任何人都可以改进它或使其更高效吗?
谢谢
最佳答案
首先,这在一般情况下是行不通的;它似乎(而且它
可能适用于某些编译器)。您不能将 char
传递给
ispunct
的一个参数版本,不会产生 undefined
行为。
至于强制转换的原因:标准定义了两者
单个参数 ispunct
函数 and 两个参数
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 ) );
}
};
使用 locale
的 ctype
方面的版本有点
更复杂(你可能希望它保留一份
locale
,以及对 facet 的引用,只是为了确定
引用的方面不会消失)。
关于c++ - 删除标点查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15967516/