C++|6种方法分割或分行处理string存储到STL vector

[复制链接]

下载APP可以快速和圈友联系

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
我们晓得,ASCII编码的13暗示回车('\\r')、10暗示换行('\\n'),在一些库的文本框中能够需要两个标记“\\r\\n“写在一路来暗示换行,在C++中,可以只用'\\n'来暗示换行。

对于字符串按行或按某个字符停止朋分,C++标准库里面并没有供给字符朋分函数split()(cstring中有strtok()函数,但较底层),需要自行界说。
1 string+vector逐字节处置

在一个多行文本(有多个'\\n')中,假如想要分行处置,可以逐一字符分析,将其叠加写入一个姑且的string,直到碰到'\\n',然后push_back入一vector,再套一个循环即可:
vector split0(string str,char deli) // string+vector逐字节处置
{
    vector vec;
    string tmp;
    string::iterator it=str.begin();
    for(; it != str.end();it++)
    {
        if (*it != deli)
            tmp += *it;
        else
        {
            vec.push_back(tmp);
            tmp = "";
        }
    }
    return vec;
}2 操纵strtok()朋分

先看strtok()的函数原型:
char * strtok ( char * str, const char * delimiters );
对此函数的一系列挪用将str拆分为标志(tokens),这些标志是由作为分隔符一部分的任何字符分隔的持续字符序列。

在第一次挪用时,函数需要一个C字符串作为str的参数,str的第一个字符用作扫描标志的肇端位置。在随后的挪用中,函数需要一个空指针,并利用最初一个标志竣事后的位置作为新的扫描肇端位置。

要肯定标志的起头和竣事,函数首先从起头位置扫描分隔符中未包括的第一个字符(它将成为标志的起头)。然后从标志的开首起头扫描分隔符中包括的第一个字符,该字符将成为标志的结尾。假如找到停止的空字符,扫描也会停止。

标志的结尾替换为空字符,而且该函数返回标志的开首。

一旦在对strtok的挪用中找到str的停止空字符,对该函数的一切后续挪用(以空指针作为第一个参数)都将返回空指针。

找到最初一个标志的点由下一次挪用时利用的函数内部保存(不需要特定的库实现来避免数据合作)。

请留意的是,第一个参数是要截断的C字符串,由因而址传递,所以存在副感化,这个字符串是经过度成更小的字符串(标志)来点窜的。

别的,可以指定空指针,在这类情况下,函数继续扫描先前对函数的成功挪用竣事的位置。

返回值:

假如找到标志,则指向标志开首的指针。否则,为空指针。

当扫描的字符串到达字符串的末端(即空字符)时,总是返回空指针。
vector split1(char* src,const char* separator)  // 操纵strtok()朋分   // 分隔符可以指定多个
{
\tif (strlen(src) ==  0)
\t\texit(0);
\tvector vec;
\tchar *pNext = (char *)strtok(src,separator);
\twhile(pNext != NULL)
\t{
\t\tvec.push_back(pNext);
\t\tpNext = (char *)strtok(NULL,separator);
\t}  
\treturn vec;
}
完全用C写更烦琐:
int splitc(char *src,const char *separator,char **dest)  // 完全按C代码写
{
     char *pNext;
     int count = 0;
     if (src == NULL || strlen(src) == 0)
        return 0;
     if (separator == NULL || strlen(separator) == 0)
        return 0;
     pNext = (char *)strtok(src,separator);
     while(pNext != NULL) {
          *dest++ = pNext;
          ++count;
         pNext = (char *)strtok(NULL,separator);
    }  
    return count;
}
void Print(char **ppstr, int num)
{
\tfor(int i = 0;i < num; i ++) {
\t\tprintf("%s\\n",ppstr);
\t}
}
void test()
{
\tchar *buf[3] = {0};
\tchar str2[] = "知善知恶\\n为善去恶\\n知行合一";
\tsplitc(str2,"\\n",buf);
\tPrint(buf,3);
}3 .find_first_of()+substr()逐段处置

find_first_of()方式的函数原型:
size_t find_first_of (const string& str, size_t pos = 0) const;
size_t find_first_of (const char* s, size_t pos = 0) const;
size_t find_first_of (const char* s, size_t pos, size_t n) const;
size_t find_first_of (char c, size_t pos = 0) const;
用于在字符串中搜索与参数中指定的任何字符婚配的第一个字符。

当指定pos时,搜索仅包括pos位置处或以后的字符,疏忽pos之前能够出现的任何字符。

Notice that it is enough for one single character of the sequence to match (not all of them). See string::find for a function that matches entire sequences.

需要留意的是,序列中的一个字符(不是一切字符)就充足婚配了。有关婚配全部序列的函数,请拜见string::find。
vector split2(string str, string delis) // .find_first_of()+substr()
{
\tvector vec;
\tsize_t current;
\tsize_t next = -1;
\tdo{
\t\tcurrent = next + 1;
\t\tnext = str.find_first_of(delis, current);
\t\tvec.push_back(str.substr(current, next - current));
\t}while(next != string::npos);
\treturn vec;
}4 string+vector逐段处置

可以操纵string的find()、substr()、erase()来处置:
vector split3(string str,char del) // string+vector逐段处置
{
    vector vec;
    string line;
\tint pos = str.find(del);
\twhile(pos != string::npos)
\t{
\t    line = str.substr(0,pos);
\t\tvec.push_back(line);
\t    str.erase(0,pos+1);
\t\tpos = str.find(del);
\t}
    return vec;
}5 操纵getline()函数朋分

也可以操纵getline()函数,其原型(操纵重载有两个版本):
istream& getline ( istream &is , string &str , char delim ); // ①
istream& getline (istream& is, string& str);                        // ②
从输入流is中逐一提取字符直到分隔符delim出现(上述②为'\\n')为止,保存到str,流指针自移动。

每个提取的字符都被追加到字符串str中,就似乎它的成员push_back被挪用一样。

假如在is中到达文件结尾或在输入操纵时代发生其他毛病,则提取也将停止。

假如找到分隔符,则提取并抛弃它(即它未被存储,下一个输入操纵将在它以后起头,由于输入流指针的自移动)。

需要留意的是,在挪用之前str中的任何内容都将被新提取的序列替换。

getline可返回eofbit、failbit、badbit,用于判定字符串提取状态。

上述的输入流可所以cin,如
\tstring str;
\twhile (getline(cin, str, '#'))
\t    cout
温馨提示:
好向圈www.kuaixunai.com是一个专业经验分享交流平台,你可以在这里发布专业经验,也可以发布需求与服务,禁止带推广链接、联系方式、违法词等,违规将封禁账号。 下载好向圈客户端可以随时随地交流经验,也可以和圈友发起聊天成为好友哦!
回复

使用道具 举报

已有(4)人评论

跳转到指定楼层
神官祭司神o 发表于 2020-4-24 19:51:40
感觉用字符串流+getline最舒服
回复

使用道具 举报

翱翔飞飞i 发表于 2020-4-24 19:56:46
boost split直接分割成vector
回复

使用道具 举报

添衣广场讯 发表于 2020-4-24 19:58:59
++it的效率会比较高
回复

使用道具 举报

一两半烟 发表于 2020-4-24 20:03:57
转发了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本圈子积分规则