C++ 使用ispunct()删除标点符号

C++ 使用ispunct()删除标点符号,c++,c,C++,C,ispunt()以这种方式分隔单词时效果很好“一,二;三”。然后它将删除“,;”并替换为给定的字符 但如果字符串是以这种方式给出的“ts='TOK_STORE_ID'”,那么它将把“ts='TOK_STORE_ID'”作为一个令牌,或者 “一,一,二;四$三二”作为三个代币1。“一,一”2。“2美元;4美元3美元”。“两个” 是否有任何一个标记可以将“一,一,二;四$三二”视为“一一二四三二”每个单独的标记 编写手动代码,如: for(i=0;i<str.length();i++) {

ispunt()
以这种方式分隔单词时效果很好
“一,二;三”
。然后它将删除“,;”并替换为给定的字符

但如果字符串是以这种方式给出的
“ts='TOK_STORE_ID'”
,那么它将把
“ts='TOK_STORE_ID'”
作为一个令牌,或者

“一,一,二;四$三二”
作为三个代币
1。“一,一”2。“2美元;4美元3美元”。“两个”

是否有任何一个标记可以将
“一,一,二;四$三二”
视为
“一一二四三二”
每个单独的标记

编写手动代码,如:

for(i=0;i<str.length();i++)
{
  //validating each character
}

在C++中,正确的方法是什么?

< P> <代码>当字符串非常长时,这个操作将变得非常昂贵。< /代码> < / P>
不,不会的。这将是一个有利于解决此问题的
O(n)
操作。对于此操作,您无法获得比此更好的结果,因为无论以何种方式,您都必须查看字符串中的每个字符。如果不查看字符串中的每个字符,就无法执行此操作。

假设您处理的是典型的8位字符集,我将首先构建一个翻译表:

std::vector<char> trans(UCHAR_MAX);

for (int i=0; i<UCHAR_MAX; i++)
    trans[i] = ispunct(i) ? ' ' : i;
对于8位字符集,转换表通常都适合一级缓存,循环只有一个分支是高度可预测的(除非到达字符串末尾,否则始终采用该分支),因此它应该相当快

我想说清楚,当我说“相当快”的时候,我的意思是,这不太可能成为你所描述的过程中的瓶颈。您需要一个慢处理器和快速网络连接的组合,以避免这成为处理通过网络获取的数据的瓶颈

如果您有一个带有10GbE网络连接的Raspberry Pi,您可能需要做更多的优化工作才能跟上进度(但我甚至不确定)。对于任何不太严重的不匹配,网络显然将成为瓶颈

So is there any other function like ispunct()? or anything else?
事实上,有
man ispunt
给了我一个漂亮的列表:

int isalnum(int c);
int isalpha(int c);
int isascii(int c);
int isblank(int c);
int iscntrl(int c);
int isdigit(int c);
int isgraph(int c);
int islower(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isupper(int c);
int isxdigit(int c);

随便取一个。

如果要完全删除标点符号,也可以使用
std::remove\u copy\u:

#include <algorithm>
#include <string>      

  string words = "I,love.punct-uation!";
  string result;  // this will be our final string after it has been purified

  // iterates through each character in the string
  // to remove all punctuation
  std::remove_copy_if(words.begin(), words.end(),            
                    std::back_inserter(result), //Store output           
                    std::ptr_fun<int, int>(&std::ispunct)  
                   );

  // ta-da!
  cout << result << endl;
#包括
#包括
stringwords=“我,爱,点状评价!”;
字符串结果;//这将是净化后的最后一根线
//遍历字符串中的每个字符
//删除所有标点符号
std::remove_copy_if(words.begin(),words.end(),
std::back\u插入器(结果),//存储输出
std::ptr_fun(&std::ispunt)
);
//塔达!

在处理大数据时,比如社交媒体上的数据,或者使用爬虫在网络上浏览多个网页;这不会花很多时间吗?不管花多长时间,关键是你不能做得更快。除非您有预先知道所有标点符号位置的结构化数据,否则您打算如何在不查看字符串中的每个字符的情况下找到所有标点符号?一个程序无法神奇地知道它们都在哪里。@Karimkhan-如果你必须遍历一个字符串,那么你不能得到比O(n)更好的结果。你可以优化其他东西,比如删除标点符号——但你必须至少遍历字符串一次——这是无法绕过的;不应该这样。另外,除非我遗漏了什么,否则,
ispunt()
会对单个字符进行分类,而不是像你在第一段中所建议的那样编辑字符串。@JonathanLeffler:谢谢,但是如果它对每个字符进行分类,那么
“2;4$3”
应该分别被视为两个、四个、三个字符。但在这里,它不这样做!您如何准确地使用
ispunt
?它不会修改字符串或将其标记化。有什么问题吗?@molbdnilo:谢谢,伙计,我是这样使用的:
std::replace_if(input.begin(),input.end(),std::ptr_fun(&std::ispunt),“”)可能不正确。您的代码符合我的要求,但为此,我需要将
std::string输入转换为char数组吗?或者用字符串也可以做同样的事情?你把字符和字符串搞混了。这些语句毫无意义:
str[i]==”、“
str[i]=”
。另外,为什么每次循环迭代时都要重新计算字符串的长度?调用
str.length()
一次,将其分配给一个变量,然后使用该变量。@Karimkhan:No.
ch
是对字符串中单个字符的引用。
for
循环一次遍历字符串一个字符,然后依次转换每个字符
ch
只允许访问给定迭代中正在处理的代码。正在更改的字符串是
str
。感谢您的解释
UCHAR\u MAX
这是什么?它是
无符号字符的最大可能值(理论上你可能应该使用
std::numeric\u limits::MAX()
,但我发现这有点冗长)。“8位字符”是指我正在处理的编程或数据吗?我正在处理各种网页的内容。可以吗?@Karimkhan:你是以
char
s的形式读取数据的吗?如果是的话,没关系。
int isalnum(int c);
int isalpha(int c);
int isascii(int c);
int isblank(int c);
int iscntrl(int c);
int isdigit(int c);
int isgraph(int c);
int islower(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isupper(int c);
int isxdigit(int c);
#include <algorithm>
#include <string>      

  string words = "I,love.punct-uation!";
  string result;  // this will be our final string after it has been purified

  // iterates through each character in the string
  // to remove all punctuation
  std::remove_copy_if(words.begin(), words.end(),            
                    std::back_inserter(result), //Store output           
                    std::ptr_fun<int, int>(&std::ispunct)  
                   );

  // ta-da!
  cout << result << endl;