【问题标题】:String Parse for a specific format [duplicate]特定格式的字符串解析[重复]
【发布时间】:2013-03-18 15:12:25
【问题描述】:

string = std::vector<int>(6,0) 并希望它显示为{ 0 0 0 0 0 0 }

我试过了

#include <iostream>
using namespace std;


int main()
{
    string str = "std::vector<int>(6,0)" ;

    unsigned found = str.find('(');
    char c = str[found+1];
    int i = c - '0'; 
    char ch = str[found+3];
    int j = ch - '0';

    str = "{ ";
    for(int k = 0; k < i ; k++)
    {
        str = str + ch + " " ;
    }

    str = str + " }";

    cout << str << endl; 

    return 0;
}

它可以工作,但看起来效率不高。有更好的主意吗?

【问题讨论】:

  • 这可能有点矫枉过正,但我​​相信pretty printer 可以处理它。
  • 效率高但不够灵活。
  • 如果您正在寻找一种更灵活的方式来解析此类内容,您可能需要使用 std::regex 或 boost::spirit。正则表达式永远不会让人失望
  • 所以您正在解析一个恰好包含 C++ 代码的字符串,并且想要打印您认为它包含的内容?这是用于代码分析工具吗?如果没有,也许有更好的方法。
  • 如果向量的大小是两位数,这将不起作用

标签: c++ string parsing


【解决方案1】:

当前版本的代码仅适用于向量和元素大小的单个数字值。使用std::stringstream 获得更好的解决方案:

#include <iostream>
#include <sstream>

using namespace std;


int main()
{

  string str = "std::vector<int>(6,0)" ;

  unsigned found = str.find('(');
  string arguments = str.substr(found);

  // Replace non-numeric chars with spaces.
  for (unsigned i=0;i<arguments.size(); ++i) {
    if (!isdigit(arguments[i])) {
      arguments[i] = ' ';
    }
  }

  std::istringstream iss(arguments);
  int size;
  // String to avoid having to cast later on
  string value;
  iss >> size >> value;

  string res = "{;

  for (int i = 0; i < size; ++i) {
    res += " " + value;
  }
  res += " }";

  cout << res;
  return 0;
}

【讨论】:

  • size 和 value 都没有任何值 :-(
  • 我很傻很抱歉!将参数作为参数传递给 iss-s 构造函数。我已经解决了。对不起。
  • 这行得通!谢谢
【解决方案2】:

这是(希望)更灵活的代码的另一个版本。它找到“(”,然后是“)”,用逗号分隔它们,去除所有空白字符并将数字转换为整数。然后打印出来。

#include <string>
#include <iostream>
using namespace std;

//these three functions are taken from here: 
//http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring

#include <algorithm> 
#include <functional> 
#include <cctype>
#include <locale>

static inline std::string &ltrim(std::string &s) {
        s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
        return s;
}

// trim from end
static inline std::string &rtrim(std::string &s) {
        s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
        return s;
}

// trim from both ends
static inline std::string &trim(std::string &s) {
        return ltrim(rtrim(s));
}

int main()
{
    string s = "std::vector<int>(612,30)";

    int paren_start = s.find("(")+1;

    string numbers = s.substr(paren_start, s.find(")")-paren_start);
    int comma_pos = numbers.find(",");

    string first_num = numbers.substr(0, comma_pos);
    string second_num = numbers.substr(comma_pos+1, numbers.size()-comma_pos);

    int first = atoi(trim(first_num).c_str());
    int second = atoi(trim(second_num).c_str());

    cout << "{" << endl;
    for(int i=0; i<first; i++)
    {
        cout << second << " ";
    }
    cout << "}" << endl;

    return 0;
}

【讨论】:

  • 这个解决方案在大多数情况下都运行良好,除了第二个数字 if float like std::vector(6,0.0) 我尝试将 atoi 更改为 atof 并将 'second' 变量更改为 float但不起作用。任何想法如何使它工作谢谢
  • 也许您忘记在“第二个”声明中将 int 更改为 double?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-27
  • 2016-08-04
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多