【问题标题】:Split a c++ string without boost and not on whitespace [duplicate]拆分没有提升而不是空格的c ++字符串[重复]
【发布时间】:2013-01-15 00:38:12
【问题描述】:

可能重复:
Splitting a string in C++

我有一个字符串:
14332x+32x=10
我想拆分它,使其看起来像:
[14332][+32][10]
到目前为止,我已经尝试过

char c;
std::stringstream ss(equation1);
while (ss >> c) {
    std::cout << c << std::endl;
} 

但是在测试了打印的内容之后,我认为不可能从该信息中进行操作。我知道我需要在 x 和 = 上拆分字符串,但我不确定这是否可行以及是否可行。我用谷歌搜索了它,没有发现任何看起来有帮助的东西,但我也是 C++ 新手,答案可能就在我面前。
我不想使用boost。任何建议都会有所帮助!

【问题讨论】:

  • 我在你最后一个问题中的链接包含了这个问题的答案。
  • 我认为您应该使用std::string 类的功能。请参阅reference 并浏览成员。您应该能够根据.find() 的字符提出一种快速提取子字符串的方法。
  • ...如果你真的喜欢那些stringstreams,只需使用数字类型,然后使用istream::peekistream::ignore,直到你达到下一个数字。不过,其他方法 (boost/string::find) 可能会为您提供更强大的解决方案。
  • 我看了看,并尝试使用以下代码:std::istringstream iss(equation1);复制(std::istream_iterator<:string>(iss), std::istream_iterator<:string>(), std::ostream_iterator<:string>(std::cout, "x")) ;它只是打印出原始字符串(12344x+3x=10),但末尾有一个 x

标签: c++ string split


【解决方案1】:

手动方法是对字符串中的每个字符执行 for 循环,如果字符是 == 则通过将其复制到新字符串来拆分字符(如果 >1 拆分,则使用字符串列表/数组预期)。

我还认为 std 按字符功能划分。如果不是,那么 stringstream::GetLine() 有一个重载,它接受一个字符来分割,它会忽略空格。

GetLine() 很好:)

【讨论】:

  • 我想我会尝试使用这个,谢谢
【解决方案2】:

你可以像这样使用sscanf

sscanf(s.c_str(), "%[^x]x%[^x]x=%s", a, b, c);

其中%[^x] 表示“除x 之外的任何字符”。如果您不关心符号(即+ 等)而只关心数字,您可以执行以下操作:

sscanf(s.c_str(), "%dx%dx=%d", &x, &y, &z);

【讨论】:

  • 只要输入方程的项多于或少于示例中给出的项,就会中断。
  • +1 - "%[^x]x%[^x]x=%s" 在第二个 x 之后缺少一个加号。
  • @us2012:是的,这是特定于他的格式的。但是,如果您知道格式遵循一些预定义的标准,您可以随时更改 sscanf 中的正则表达式来处理它。
  • @TonyD:他的预期输出包括加号 - [+32],这就是我没有添加它的原因。
  • @us2012:恕我直言,这个问题没有具体说明任何一般要求,所以不值得一个一般性的答案。有太多的可能性......数字可以是浮点数吗?消极的? =number 是可选的,或者甚至 =numberx+numberx 是允许的吗?没有大量猜测就无法有意义地回答,因此准确回答并且只回答所问的内容是合理的。
【解决方案3】:

考虑使用将x= 指定为空白字符的构面:

#include <locale>
#include <iostream>
#include <sstream>

struct punct_ctype : std::ctype<char> {
  punct_ctype() : std::ctype<char>(get_table()) {}
  static mask const* get_table()
  {
    static mask rc[table_size];
    rc[' '] = std::ctype_base::space;
    rc['\n'] = std::ctype_base::space;
    rc['x'] = std::ctype_base::space;
    rc['='] = std::ctype_base::space;
    return &rc[0];
  }
};

int main() {
  std::string equation;
  while(std::getline(std::cin, equation)) {
    std::istringstream ss(equation);
    ss.imbue(std::locale(ss.getloc(), new punct_ctype));
    std::string term;
    while(ss >> term) {
      std::cout << "[" << term << "]";
    }
    std::cout << "\n";
  }
}

【讨论】:

  • 一种有趣的方法 - 方面和语言环境似乎是 C++ 中很少使用的方面。
【解决方案4】:

如果你不介意使用 c++11,你可以使用类似这样的东西:

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
#include <unordered_set>

typedef std::vector<std::string> strings;
typedef std::unordered_set<char> tokens;

struct tokenize
{
    tokenize(strings& output,const tokens& t) : 
    v_(output),
    t_(t)
    {}        
    ~tokenize()
    {
        if(!s.empty())
            v_.push_back(s);
    }
    void operator()(const char &c)
    {
        if(t_.find(c)!=t_.end())
        {
            if(!s.empty())
                v_.push_back(s);
            s="";
        }
        else
        {
            s = s + c;
        }
    }
    private:
    std::string s;
    strings& v_;
    const tokens& t_;
};

void split(const std::string& input, strings& output, const tokens& t )
{
    tokenize tokenizer(output,t);
    for( auto i : input )
    {
        tokenizer(i);
    }
}

int main()
{
    strings tokenized;
    tokens t;
    t.insert('x');
    t.insert('=');
    std::string input = "14332x+32x=10";
    split(input,tokenized,t);
    for( auto i : tokenized )
    {
        std::cout<<"["<<i<<"]";
    }
    return 0;
}

上述代码的Ideone链接:http://ideone.com/17g75F

【讨论】:

    【解决方案5】:

    请参阅 this SO answer for a getline_until() function,它提供了一个简单的基本标记化功能,应该可以让您执行以下操作:

    #include <string>
    #include <stringstream>
    
    #include "getline_until.h"
    
    int main()
    {
        std::string equation1("14332x+32x=10");
        std::stringstream ss(equation1);
    
        std::string token;
        while (getline_until(ss, token, "x=")) {
            if (!token.empty()) std::cout << "[" << token << "]";
        } 
    
        std::cout << std::endl;
    }
    

    getline_until() 函数允许您指定类似于strtok() 的分隔符列表(尽管getline_until() 将返回空标记,而不是跳过一系列分隔符,例如strtok())。或者,您可以提供一个谓词,让您使用函数来决定何时分隔标记。

    它不会让你做的一件事(再次 - 类似于 strtok() 或标准 getline())是仅在上下文中拆分标记 - 必须有一个分隔符被丢弃。例如,使用以下输入:

    42+24
    

    getline_until()(如strtok()getline())无法将上述内容拆分为标记42+24

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-11
      • 2011-01-17
      • 2011-11-15
      • 2018-05-10
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      相关资源
      最近更新 更多