删除标点查询

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 ) );
    
;

使用localectype facet 的版本有点 更复杂(你可能希望它保留一份 locale,以及对方面的引用,只是为了确定 引用的构面不会消失)。

【讨论】:

当时我似乎正在寻找一个快速的解决方案,而这确实起到了作用。您能否再解释一下您在答案中定义的结构?如果 char 是一个 punct 字符,它看起来会返回 true,但我不明白 ispunct 调用之前的两个分号。我对 bool operator() const 实现也不是很熟悉。你也可以扩展一下吗?很抱歉给您带来麻烦。 没问题。 :: 是范围解析运算符。它只是确保我们从&lt;ctype.h&gt; 获得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 中的位置。谢谢。

以上是关于删除标点查询的主要内容,如果未能解决你的问题,请参考以下文章

删除快速字符串的最后一个标点符号

SQL Server:如何从字段中删除标点符号?

C ++从字符串中删除标点符号

删除 R 中除撇号外的所有标点符号

除了文本,如何从文本中删除数字、标点、空格和特殊字符? [复制]

从数据框中删除所有标点符号,除了一些字符[重复]