按单个空格拆分字符串

56

可能是重复问题:
如何在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.

如何实现这个?
7个回答

41

你甚至可以开发自己的分割函数(我知道,有点老式):

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<string> 作为参数调用它:

int main()
{
    std::vector<std::string> v;

    split( "This  is a  test", v, ' ' );
    dump( cout, v );

    return 0;
}

在 IDEone 中找到拆分字符串的代码

希望这可以帮助您。


警告! :) 如果您想要没有空格的元素,请将“- initialPos + 1”的两个出现替换为仅“- initialPos”。 - teejay
我建议在posinitialPos中使用size_t而不是unsigned int。否则,您可能会陷入无限循环,就像我刚刚经历的那样。 - CodeMonkey
为了获取最后一个字符串,我不得不将while循环更改为initialPos而不是pos,并使用三元运算符initialPos = pos + 1 != 0 ? pos + 1 : pos; - CodeMonkey

40

如果严格使用一个空格字符作为分隔符,那么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() );
  }
}

3
有人能解释一下以下代码的性能开销吗?string line, word; while (getline(cin, line)) { istringstream ss(line); while (ss >> word) // 解析单词 }具体来说,istringstreamstring构造器是如何实现的?它是否会复制字符串?编译器是否足够聪明以便将ss声明移出while循环之外? - csyangchen
非常简单的实现。谢谢! - Madhurya Gandi

9

你能使用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$ 

这样做可以提高可读性。 - Scott 混合理论

3
如果您不排斥使用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


3

如果你不喜欢使用boost,你可以使用普通的operator>>,以及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


2
你也可以使用旧的方法 '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;
}

1

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

#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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接