拆分 c++ 字符串而不使用增强,也不在空格上

Split a c++ string without boost and not on whitespace

本文关键字:空格 增强 c++ 字符串 拆分      更新时间:2023-10-16

可能的重复项:
拆分C++字符串

我有一个字符串:

14332x+32x=10我想拆分它,使其看起来像:

[14332][+32][10]到目前为止,我已经尝试过做

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

但是在测试了打印的内容后,我认为不可能从该信息中做到这一点。 我知道我需要在 x 和 = 上拆分字符串,但我不确定这是否可能以及是否可能。 我已经用谷歌搜索了一下,没有找到任何看起来有用的东西,但我也是 c++ 新手,答案可能就在我面前。
我不想使用提升。 任何建议都会有所帮助!

考虑使用指定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";
  }
}

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

另外,我认为std已按字符功能拆分。如果不是,则 stringstream::GetLine() 有一个重载,它接受一个字符进行拆分,它将忽略空格。

GetLine() 是非常好的:)

你可以

像这样使用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);

如果你不介意使用 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

请参阅此 SO 答案,了解提供简单、基本的标记化功能的 getline_until() 函数,该功能应允许您执行以下操作:

#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的令牌。