【问题标题】:C++ split stringC++ 拆分字符串
【发布时间】:2011-02-13 05:45:28
【问题描述】:

我正在尝试使用空格作为分隔符来拆分字符串。我想将每个标记存储在一个数组或向量中。

我试过了。

    string tempInput;
    cin >> tempInput;
    string input[5];

    stringstream ss(tempInput); // Insert the string into a stream
    int i=0;
    while (ss >> tempInput){
        input[i] = tempInput;
        i++;
    }

问题是,如果我输入“这是一个测试”,数组似乎只存储 input[0] = “this”。它不包含 input[2] 到 input[4] 的值。

我也尝试过使用向量,但结果相同。

【问题讨论】:

  • 不是真正的骗子。这是“我在哪里犯了错误”与“最好的方法是什么”?
  • 虽然问题完全相同:如何拆分字符串,但我相信@pmr 提到的问题涉及一般问题,而在这个问题中,问题不在实际拆分中
  • @David @SF 是的,你是对的。不幸的是,大多数答案都没有这样处理这个问题。

标签: c++ string split


【解决方案1】:

去重复问题学习如何将字符串拆分为单词,但您的方法实际上是正确的。实际问题在于您在尝试拆分输入之前 是如何读取它的:

string tempInput;
cin >> tempInput; // !!!

当您使用cin >> tempInput 时,您只会从输入中获取第一个单词,而不是整个文本。有两种可能的解决方法,其中最简单的是忘记stringstream 并直接迭代输入:

std::string tempInput;
std::vector< std::string > tokens;
while ( std::cin >> tempInput ) {
   tokens.push_back( tempInput );
}
// alternatively, including algorithm and iterator headers:
std::vector< std::string > tokens;
std::copy( std::istream_iterator<std::string>( std::cin ),
           std::istream_iterator<std::string>(),
           std::back_inserter(tokens) );

这种方法将在单个向量中为您提供输入中的所有标记。如果您需要分别处理每一行,那么您应该使用 &lt;string&gt; 标头中的 getline 而不是 cin &gt;&gt; tempInput

std::string tempInput;
while ( getline( std::cin, tempInput ) ) { // read line
   // tokenize the line, possibly with your own code or 
   // any answer in the 'duplicate' question
}

【讨论】:

    【解决方案2】:

    请注意,使用copy 会更容易:

    vector<string> tokens;
    copy(istream_iterator<string>(cin),
         istream_iterator<string>(),
         back_inserter(tokens));
    

    至于为什么你的代码不起作用:你在重用tempInput。不要那样做。此外,您首先从 cin 读取一个单词,不是整个字符串。这就是为什么在stringstream 中只输入一个单词。

    【讨论】:

      【解决方案3】:

      最简单的方法:Boost.Tokenizer

      std::vector<std::string> tokens;
      
      std::string s = "This is,  a test";
      boost::tokenizer<> tok(s);
      for(boost::tokenizer<>::iterator it=tok.begin(); it != tok.end(); ++it)
      {
        tokens.push_back(*it);
      }
      
      // tokens is ["This", "is", "a", "test"]
      

      如果您愿意,您可以对分隔符和转义序列进行参数化以仅使用空格,默认情况下,它会同时标记空格和标点符号。

      【讨论】:

      • 我希望人们停止立即将 Boost 作为解决方案。许多地方,包括我目前(和以前工作过)的地方,必须花费数月的时间来审查 任何 开源项目的许可证和审核,然后才能使用它,而且通常不值得付出痛苦和努力(更不用说等待)在你得到绿(或红)灯之前。此外,如果这是一个家庭作业问题,那么如果学生交出 Boost 谜题代码,导师也不会留下深刻印象。
      • @graham.reeds:很遗憾听到这个消息,但是——虽然很幸运。 Boost 是一种——而且通常是最合适的——解决方案。你可以使用标准库吗?毕竟,它是一个开放标准,它的实现通常是开源的。无论如何,责怪你的公司,而不是 Boost 或有用的答案。 :-(
      • @graham.reeds: 另一种方法是隐藏可以在其他环境中使用的完全有效的答案?如果有人问如何在 C++ 中解析 XML 怎么办?您想提供 XML 解析器的实现吗?或者宁愿被推荐到一个图书馆?在这种简单的情况下,这个问题可能会同时得到纯 c++ 和基于库的解决方案,我相信这会增加价值而不是拿走它。 (注意:我没有投票,因为我相信@Mike 面临的真正问题不是标记字符串,而是他如何读取输入)
      • @David:很好,我一味的跟着“分裂”的问题,没有注意到他实际阅读的问题。
      【解决方案4】:

      这里有一个小算法,它像 python 一样将字符串拆分成一个列表。

      std::list<std::string> split(std::string text, std::string split_word) {
          std::list<std::string> list;
          std::string word = "";
          int is_word_over = 0;
      
          for (int i = 0; i <= text.length(); i++) { 
              if (i <= text.length() - split_word.length()) {
                  if (text.substr(i, split_word.length()) == split_word) {
                      list.insert(list.end(), word);
                      word = "";
                      is_word_over = 1;
                  }
                  //now we want that it jumps the rest of the split character
                  else if (is_word_over >= 1) {
                      if (is_word_over != split_word.length()) {
                          is_word_over += 1;
                          continue;
                      }
                      else {
                          word += text[i];
                          is_word_over = 0;
                      }
                  }
                  else {
                      word += text[i];
                  }
              }
              else {
                  word += text[i];
              }
          }
          list.insert(list.end(), word);
          return list;
      }
      

      可能存在一种更优化的编写方式。

      【讨论】:

      • 如果能解释一下代码就更好了。
      猜你喜欢
      • 2017-06-16
      • 2011-11-25
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      相关资源
      最近更新 更多