• [译]C++如何切分字符串


    声明:

    • 翻译仅以技术学习和交流为目的,如需转载请务必标明原帖链接。
    • http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c

    水平有限,如有翻译不当,欢迎探讨、批评与指正。

    帖子内容:

    C++ 切分字符串的最优雅的方式是什么?我们假定字符串中每个单词分隔符是空格。(备注:我对C的字符串函数或者那种字符处理/存取方式不是很感兴趣。因此,请优先选择优雅而不是效率)


    我现在能想到的最好的方式是:

    #include <iostream>
    #include <sstream>
    #include <string>
    using namespace std;
    
    int main()
    {
        string s("Somewhere down the road");
        istringstream iss(s);
    
        do
        {
            string sub;
            iss >> sub;
            cout << "Substring: " << sub << endl;
        } while (iss);
    
        return 0;
    }

    另一种方式去萃取输入字符串的分隔符,使用标准库函数很容易实现。下面是使用 STL 的设计方案(健壮并且优雅):

    #include <iostream>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <iterator>
    
    int main() {
        using namespace std;
        string sentence = "Something in the way she moves...";
        istringstream iss(sentence);
        copy(istream_iterator<string>(iss),
                 istream_iterator<string>(),
                 ostream_iterator<string>(cout, "
    "));
    }

    如果想要把分割后的字符串放到一个容器中,而不是控制台的话,使用相同的泛型算法即可。

    vector tokens;
        copy(istream_iterator(iss),
             istream_iterator(),
             back_inserter >(tokens));[/c]

    评:这种方案只能分割空格,没有伸缩性。


    使用 boost 库:

    std::vector strs;
    boost::split(strs, "string to split", boost::is_any_of("	 "));

    我打赌这个要比使用 stringstream 快的多。并且这是一个泛型模板方法,它可以用来分割任意类型的字符串(wchar,etc. or UTF-8),使用任意的分隔符。具体请看文档

    评:不是每个人都用 boost 的。


    把 delim 作为作为分隔符,第一个函数把结果放到一个已经存在构造好了的 vector 中,第二个函数返回一个新的 vector。

    std::vector &split(const std::string &s, char delim, std::vector &elems) {
        std::stringstream ss(s);
        std::string item;
        while(std::getline(ss, item, delim)) {
            elems.push_back(item);
        }
        return elems;
    }
    
    std::vector split(const std::string &s, char delim) {
        std::vector elems;
        return split(s, delim, elems);
    
    }

    注意:这种方法不能跳过空的符号,比如下面有四个数据项,其中的一个是空的。

    std::vector x = split("one:two::three", ':');
    template < class ContainerT >
    void tokenize(const std::string& str, ContainerT& tokens,
                  const std::string& delimiters = " ", const bool trimEmpty = false)
    {
       std::string::size_type pos, lastPos = 0;
       while(true)
       {
          pos = str.find_first_of(delimiters, lastPos);
          if(pos == std::string::npos)
          {
             pos = str.length();
    
             if(pos != lastPos || !trimEmpty)
                tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                      (ContainerT::value_type::size_type)pos-lastPos ));
    
             break;
          }
          else
          {
             if(pos != lastPos || !trimEmpty)
                tokens.push_back(ContainerT::value_type(str.data()+lastPos,
                      (ContainerT::value_type::size_type)pos-lastPos ));
          }
    
          lastPos = pos + 1;
       }
    };
    #include <vector>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    int main()
    {
        string str("Split me by whitespaces");
        string buf; // Have a buffer string
        stringstream ss(str); // Insert the string into a stream
    
        vector<string> tokens; // Create vector to hold our words
    
        while (ss >> buf)
            tokens.push_back(buf);
    
    }

    笔者注:

    • 文中的优雅也就是我们平时所说的代码美感。
    • 本来打算把所有的英文都翻译过来的,后来发现很多实在是难以拿捏。所以后面就直接贴了代码,其实对于我们经常看代码的人,代码也许要比文字直观的多。上文代码我在 vs2010 上验证无误。
  • 相关阅读:
    mongodb群集
    AtoS查看iOS Crash log中的16进制代码日志
    Info.plist 的字段解释
    IOS --关于粘贴板 ,剪切板 ,UILabel的复制
    UItableView 所有内容保存为图片
    ios 工程图片清理shell
    检查项目图片是否被使用
    ios 联网 在mac机器上进行抓包
    还在为不停build 烦恼么?看这里~~
    修复OS X的Finder中文档 打开方式中重复程序的问题
  • 原文地址:https://www.cnblogs.com/wuchanming/p/4110022.html
Copyright © 2020-2023  润新知