【问题标题】:Split string by single spaces [duplicate]用单个空格分割字符串[重复]
【发布时间】:2011-08-18 18:48:40
【问题描述】:

可能重复:
How to split a string in C++?

我需要用单个空格分割一个字符串并将其存储到一个字符串数组中。我可以使用 istringstream 来实现这一点,但我无法实现的是:

我希望每个空格都终止当前单词。所以,如果连续有两个空格,我的数组的一个元素应该是空白的。

例如:

(下划线表示空格)

This_is_a_string.
gets split into:
A[0] = This
A[1] = is
A[2] = a
A[3] = string.

This__is_a_string.
gets split into:
A[0] = This
A[1] = ""
A[2] = is
A[3] = a
A[4] = string.

我该如何实现?

【问题讨论】:

    标签: c++ string


    【解决方案1】:

    您甚至可以开发自己的拆分功能(我知道,有点老式):

    size_t split(const std::string &txt, std::vector<std::string> &strs, char ch)
    {
        size_t pos = txt.find( ch );
        size_t initialPos = 0;
        strs.clear();
    
        // Decompose statement
        while( pos != std::string::npos ) {
            strs.push_back( txt.substr( initialPos, pos - initialPos ) );
            initialPos = pos + 1;
    
            pos = txt.find( ch, initialPos );
        }
    
        // Add the last one
        strs.push_back( txt.substr( initialPos, std::min( pos, txt.size() ) - initialPos + 1 ) );
    
        return strs.size();
    }
    

    然后你只需要用一个vector作为参数来调用它:

    int main()
    {
        std::vector<std::string> v;
    
        split( "This  is a  test", v, ' ' );
        dump( cout, v );
    
        return 0;
    }
    

    找到the code for splitting a string in IDEone

    希望这会有所帮助。

    【讨论】:

    • 警告! :) 如果您想让元素没有空格,请将出现的“-initialPos + 1”都替换为“-initialPos”
    • 对于posinitialPos,我建议使用size_t 而不是unsinged int。否则你可能会陷入无限循环,就像我刚刚经历的那样。
    • 为了获得最后一个字符串,我必须将 while 循环更改为 initialPos 而不是 pos 和三元 initialPos = pos + 1 != 0 ? pos + 1 : pos;
    【解决方案2】:

    如果您不喜欢 boost,可以使用普通的旧 operator&gt;&gt;,以及 std::noskipws

    编辑:测试后更新。

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <iterator>
    #include <sstream>
    
    void split(const std::string& str, std::vector<std::string>& v) {
      std::stringstream ss(str);
      ss >> std::noskipws;
      std::string field;
      char ws_delim;
      while(1) {
        if( ss >> field )
          v.push_back(field);
        else if (ss.eof())
          break;
        else
          v.push_back(std::string());
        ss.clear();
        ss >> ws_delim;
      }
    }
    
    int main() {
      std::vector<std::string> v;
      split("hello world  how are   you", v);
      std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(std::cout, "-"));
      std::cout << "\n";
    }
    

    http://ideone.com/62McC

    【讨论】:

      【解决方案3】:

      如果严格来说只有一个空格字符是分隔符, std::getline 可能是有效的。
      例如:

      int main() {
        using namespace std;
        istringstream iss("This  is a string");
        string s;
        while ( getline( iss, s, ' ' ) ) {
          printf( "`%s'\n", s.c_str() );
        }
      }
      

      【讨论】:

      • 谁能解释一下`string line, word;的性能开销? while (getline(cin, line)) { istringstream ss(line); while (ss >> word) // 解析单词 }` 具体来说,stringstream的构造函数是如何实现的,是不是复制了字符串?编译器是否足够聪明,可以将 ss 声明移出 while 循环?谢谢
      • 非常简单的实现。谢谢!
      【解决方案4】:

      你也可以只使用老式的“strtok”

      http://www.cplusplus.com/reference/clibrary/cstring/strtok/

      它有点不稳定,但不涉及使用 boost(并不是说 boost 是坏事)。

      您基本上使用要拆分的字符串和分隔符(在本例中为空格)调用 strtok,它会返回一个 char*。

      来自链接:

      #include <stdio.h>
      #include <string.h>
      
      int main ()
      {
        char str[] ="- This, a sample string.";
        char * pch;
        printf ("Splitting string \"%s\" into tokens:\n",str);
        pch = strtok (str," ,.-");
        while (pch != NULL)
        {
          printf ("%s\n",pch);
          pch = strtok (NULL, " ,.-");
        }
        return 0;
      }
      

      【讨论】:

        【解决方案5】:

        您可以使用简单的 strtok() 函数 (*)From here。请注意,标记是在分隔符上创建的

        #include <stdio.h>
        #include <string.h>
        
        int main ()
        {
          char str[] ="- This is a string";
          char * pch;
          printf ("Splitting string \"%s\" into tokens:\n",str);
          pch = strtok (str," ,.-");
          while (pch != NULL)
          {
            printf ("%s\n",pch);
            pch = strtok (NULL, " ,.-");
          }
          return 0;
        }
        

        【讨论】:

          【解决方案6】:

          你能用boost吗?

          samm$ cat split.cc
          #include <boost/algorithm/string/classification.hpp>
          #include <boost/algorithm/string/split.hpp>
          
          #include <boost/foreach.hpp>
          
          #include <iostream>
          #include <string>
          #include <vector>
          
          int
          main()
          {
              std::string split_me( "hello world  how are   you" );
          
              typedef std::vector<std::string> Tokens;
              Tokens tokens;
              boost::split( tokens, split_me, boost::is_any_of(" ") );
          
              std::cout << tokens.size() << " tokens" << std::endl;
              BOOST_FOREACH( const std::string& i, tokens ) {
                  std::cout << "'" << i << "'" << std::endl;
              }
          }
          

          示例执行:

          samm$ ./a.out
          8 tokens
          'hello'
          'world'
          ''
          'how'
          'are'
          ''
          ''
          'you'
          samm$ 
          

          【讨论】:

          • 这个可读性更好
          【解决方案7】:

          如果你不反对 boost,boost.tokenizer 足够灵活来解决这个问题

          #include <string>
          #include <iostream>
          #include <boost/tokenizer.hpp>
          
          void split_and_show(const std::string s)
          {
              boost::char_separator<char> sep(" ", "", boost::keep_empty_tokens);
              boost::tokenizer<boost::char_separator<char> > tok(s, sep);
              for(auto i = tok.begin(); i!=tok.end(); ++i)
                      std::cout << '"' << *i << "\"\n";
          }
          int main()
          {
              split_and_show("This is a string");
              split_and_show("This  is a string");
          
          }
          

          测试:https://ideone.com/mN2sR

          【讨论】:

            猜你喜欢
            • 2021-06-16
            • 1970-01-01
            • 1970-01-01
            • 2017-11-10
            • 1970-01-01
            • 2016-12-26
            • 2012-04-22
            • 1970-01-01
            • 2014-12-16
            相关资源
            最近更新 更多