c ++在非字母字符上拆分字符串
Posted
技术标签:
【中文标题】c ++在非字母字符上拆分字符串【英文标题】:c++ splitting string on non alphabetic characters 【发布时间】:2014-11-13 23:11:44 【问题描述】:我正在逐行读取文件,我想将其拆分为非字母字符,如果可能的话,同时删除所有非字母字符,这样我以后就不必这样做了。
我想使用isalpha
,但不知道如何将它与 str.find() 或类似函数一起使用,因为这些函数通常将单个分隔符作为字符串。
while(getline(fileToOpen,str))
unsigned int pos= 0;
string token;
//transform(str.begin(),str.end(),str.begin(),::tolower);
while (pos = str.find_first_not_of("abcdefghijklmnopqrstuvwxyzQWERTYUIOPASDFGHJKLZXCVBNM"))
token = str.substr(0, pos);
//transform(str.begin(),str.end(),str.begin(),::tolower);
Node<t>* ptr=search(token,root);
if (ptr!=NULL)
ptr->count++;
cout<<token<<" already in tree.Count "<<ptr->count<<"\n";
else
insert(token,root);
cout<<token<<" added to tree.\n";
ptr=NULL;
str.erase(0, pos);
我最近一次失败的尝试……我能找到的所有例子都是基于str.find("single delimiter")
这对我没有好处。
找到了使用isalpha
的方法
template<typename t>
void Tree<t>::readFromFile(string filename)
string str;
ifstream fileToOpen(filename.c_str());
if (fileToOpen.is_open())
while(getline(fileToOpen,str))
unsigned int pos= 0;
string token;
//transform(str.begin(),str.end(),str.begin(),::tolower);
while (pos = find_if(str.begin(),str.end(),aZCheck)!=str.end()!=string::npos)
token = str.substr(0, pos);
transform(token.begin(),token.end(),token.begin(),::tolower);
Node<t>* ptr=search(token,root);
if (ptr!=NULL)
ptr->count++;
// cout<<token<<" already in tree.Count "<<ptr->count<<"\n";
else
insert(token,root);
cout<<token<<" added to tree.\n";
ptr=NULL;
str.erase(0, pos);
fileToOpen.close();
else
cout<<"Unable to open file!\n";
template<typename t>
inline bool Tree<t>::aZCheck(char c)
return !isalpha(c);
但问题仍然存在,字符串被拆分为单个字符而不是单词,并且 isalpha 认为空格有效吗?
【问题讨论】:
我从未使用过它,但find_first_not_of()
是如何工作的?应该只将指针存储为拆分位置。在传递给函数的字符串中包含大写和小写字符。
应该返回字符串中字符的位置,该位置不是指定的字符之一,但在我的情况下,它只是分成单个字符
你应该检查while( (pos=...) != npos )
是的,已经添加了,没有它不会拆分,它会拆分成单个字符。像这样的事情可以用 Java 中的单个 3 字语句来完成 .... C++ 并不容易
啊,就像我说的我从未使用过它,也做了很多 C++。但是,如果我要击败 C++ 联盟(或女士),我会首先尝试单一、简单的用例。 pos
返回的断点/
【参考方案1】:
#include <algorithm>
#include <cctype>
...
template<typename t>
void Tree<t>::readFromFile(std::string filename)
std::string str;
std::ifstream fileToOpen(filename.c_str());
if (fileToOpen.is_open())
for (std::string::iterator pos, prev; std::getline(fileToOpen, str); )
for (pos = std::find_if(str.begin(), str.end(), isalpha); pos != str.end();
pos = std::find_if(prev, str.end(), isalpha))
prev = std::find_if_not(pos, str.end(), isalpha);
std::string token(pos, prev);
std::transform(token.begin(), token.end(), token.begin(), ::tolower);
Node<t>* ptr = search(token, root);
if (ptr != NULL)
ptr->count++;
// cout<< token << " already in tree.Count "<<ptr->count<<"\n";
else
insert(token, root);
cout << token << " added to tree.\n";
fileToOpen.close();
else
cout<<"Unable to open file!\n";
Online demo
另外,既然你说你想节省时间,那么如果你的插入函数做一些额外的事情,你会受益匪浅。即如果在树中找不到值,则插入该值,并将该位置的计数器设置为 1。如果该值在树中,只需递增计数器。这将使您免于执行 2 次迭代,因为您的树可能不平衡
【讨论】:
这正是我在做什么,我的插入函数将计数设置为 1。我只调用一次搜索函数,它使用该指针返回指向节点的指针,我要么将计数加一,要么添加如果指针为空,则新节点 您的解决方案正在运行,但如果行尾没有分隔符,则不会计算最后一个单词,请删除行尾的最后一个点以了解我的意思。如果一行只有一个单词也是如此,它将被忽略。 好的,我想现在应该修复了 所以我对这两种解决方案都运行了完成时间,而这个解决方案大约快 0.003 秒或 30~ 毫秒。处理 570k 个字符的文件时,总时间约为 340-345~ ms,@sln 解决方案为 370~。【参考方案2】:试试这个测试用例。两个问题。
1 - 当在截断(或开始)后的字符串开始处找到分隔符时,Pos 为 0
这导致它突然爆发。请改用npos
作为条件检查。
2 - 擦除时您必须将位置推进到分隔符之外,否则 它一遍又一遍地找到同一个。
int pos= 0;
string token;
string str = "Thisis(asdfasdfasdf)and!this)))";
while ((pos=str.find_first_not_of("abcdefghijklmnopqrstuvwxyzQWERTYUIOPASDFGHJKLZXCVBNM"))!= string::npos )
if ( pos != 0 )
// Found a token
token = str.substr(0, pos);
cout << "Found: " << token << endl;
else
// Found another delimiter
// Just move on to next one
str.erase(0, pos+1); // Always remove pos+1 to get rid of delimiter
// Cover the last (or only) token
if ( str.length() > 0 )
token = str;
cout << "Found: " << token << endl;
输出 >>
Found: Thisis
Found: asdfasdfasdf
Found: and
Found: this
Press any key to continue . . .
【讨论】:
嘿,即时拆分()!! int k 是做什么用的? 我认为使用 find_if_not 和 isalpha 作为谓词会加快速度,并且无需写出整个字母表 @Smac89 如果你有机会展示如何使用它,find_if 返回一个插入器而不是字符串中的位置, @AistisTaraskevicius,看看我的回答以上是关于c ++在非字母字符上拆分字符串的主要内容,如果未能解决你的问题,请参考以下文章
使用 UTF-8 在非 ASCII 字符上运行 Ascii 正则表达式
在 Web 上显示 iOS emoji unicode 字符