删除标点查询
Posted
技术标签:
【中文标题】删除标点查询【英文标题】:Removing punctuation query 【发布时间】:2013-04-12 09:20:00 【问题描述】:我一直在更新我大约两年前编写的一个程序,我遇到了一个从字符串中删除所有标点符号和空格的调用。
调用正常,但我不确定这是最有效的方法。
代码行如下:
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
的一个参数版本,不会导致 undefined
行为。
至于演员表的原因:标准定义了两者
单个参数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 ) );
;
使用locale
的ctype
facet 的版本有点
更复杂(你可能希望它保留一份
locale
,以及对方面的引用,只是为了确定
引用的构面不会消失)。
【讨论】:
当时我似乎正在寻找一个快速的解决方案,而这确实起到了作用。您能否再解释一下您在答案中定义的结构?如果 char 是一个 punct 字符,它看起来会返回 true,但我不明白 ispunct 调用之前的两个分号。我对 bool operator() const 实现也不是很熟悉。你也可以扩展一下吗?很抱歉给您带来麻烦。 没问题。::
是范围解析运算符。它只是确保我们从<ctype.h>
获得ispunct
,而不是另一个。 (这里应该没有必要。)bool operator()(...)
是一个函数调用运算符:这意味着编译器可以像调用函数一样“调用”对象。此类对象称为函数对象或函子,在 C++ 中广泛使用。
只是为了我自己的清楚。如何将char
传递给int ispunct( int ch )
未定义行为,但传递unsigned char
是不是?标准(4.5/4.7)积分提升的结果是否没有涵盖前者,如果没有,后者如何?
@WhozCraig 你不能将任何int
传递给ispunct
。它必须在[0...UCHAR_MAX]
或EOF
范围内。除非普通的 char
是无符号的(由于各种历史原因,它通常不是),转换为 int
将导致值超出此范围。
@JamesKanze 好的。我觉得我懂了。我知道 C99 7.4.1 中定义的表示,只是不清楚它在 C++11 中的位置。谢谢。以上是关于删除标点查询的主要内容,如果未能解决你的问题,请参考以下文章