The easiest way to read formatted input in C++?

2020-04-02 04:25发布

Is there any way to read a formatted string like this, for example :48754+7812=Abcs.

Let's say I have three stringz X,Y and Z, and I want

X = 48754 
Y = 7812
Z = Abcs

The size of the two numbers and the length of the string may vary, so I dont want to use substring() or anything like that.

Is it possible to give C++ a parameter like this

":#####..+####..=SSS.."

so it knows directly what's going on?

4条回答
太酷不给撩
2楼-- · 2020-04-02 04:53

for example.

#include <boost/regex.hpp>
#include <iostream>

int main()
{
   boost::regex re("\":(\\d+)\\+(\\d+)=(.+)\"");
   std::string example = "\":48754+7812=Abcs\"";
   boost::smatch match;
   if (boost::regex_match(example, match, re))
   {
      std::cout << "f number: " << match[1] << " s number: " << match[2] << " string: " << match[3]
      << std::endl;
   }
   else
   {
      std::cout << "not match" << std::endl;
   }
}

and second variant, work only with string.

#include <string>
#include <iostream>

int main()
{
   std::string s = "\":48754+7812=Abcs\"";
   std::string::size_type idx = s.find(":");
   std::string::size_type end_first = s.find("+", idx + 1);
   std::string f_number = s.substr(idx + 1, end_first - (idx + 1));
   std::cout << f_number << std::endl;
   std::string::size_type end_second = s.find("=", end_first + 1);
   std::string s_number = s.substr(end_first + 1, end_second - (end_first + 1));
   std::cout << s_number << std::endl;
   std::string::size_type string_end = s.find("\"", end_second);
   std::string str = s.substr(end_second + 1, string_end - (end_second + 1));
   std::cout << str << std::endl;
}
查看更多
劫难
3楼-- · 2020-04-02 04:59

You can use scanf. It is not overly C++ - ish, but it does the trick with remarkably few lines of code:

char a[101], b[111], c[121];
sscanf(":48754+7812=Abcs", ":%100[^+]+%110[^=]=%120s", a, b, c);
string sa(a), sb(b), sc(c);
cout << sa << "-" << sb  << "-" << sc << endl;

The idea is to specify the characters accepted by the strings that you read using a very limited regular expression syntax. In this case, the first string is read up to the plus, and the second string is read up to the equals sign.

查看更多
叼着烟拽天下
4楼-- · 2020-04-02 05:08

A possibility is boost::split(), which allows the specification of multiple delimiters and does not require prior knowledge of the size of the input:

#include <iostream>
#include <vector>
#include <string>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>

int main()
{
    std::vector<std::string> tokens;
    std::string s(":48754+7812=Abcs");
    boost::split(tokens, s, boost::is_any_of(":+="));

    // "48754" == tokens[0]
    // "7812"  == tokens[1]
    // "Abcs"  == tokens[2]

    return 0;
}

Or, using sscanf():

#include <iostream>
#include <cstdio>

int main()
{
    const char* s = ":48754+7812=Abcs";
    int X, Y;
    char Z[100];

    if (3 == std::sscanf(s, ":%d+%d=%99s", &X, &Y, Z))
    {
        std::cout << "X=" << X << "\n";
        std::cout << "Y=" << Y << "\n";
        std::cout << "Z=" << Z << "\n";
    }

    return 0;
}

However, the limitiation here is that the maximum length of the string (Z) must be decided before parsing the input.

查看更多
ゆ 、 Hurt°
5楼-- · 2020-04-02 05:08
#include <iostream>
#include <sstream>

int main(int argc, char **argv) {
  std::string str = ":12341+414112=absca";
  std::stringstream ss(str);
  int v1, v2; 
  char col, op, eq; 
  std::string var;
  ss >> col >> v1 >> op >> v2 >> eq >> var;
  std::cout << v1 << " " << v2 << " " << var << std::endl;
  return 0;
}
查看更多
登录 后发表回答