Вопрос по input, formatted, c++ – Самый простой способ прочитать форматированный ввод в C ++?

15

Есть ли способ прочитать отформатированную строку, как это, например,:48754+7812=Abcs.

Допустим, у меня есть три строки Z, Y и Z, и я хочу

X = 48754 
Y = 7812
Z = Abcs

Размер двух чисел и длина строки могут отличаться, поэтому я не хочу использоватьsubstring() или что-нибудь в этом роде.

Можно ли дать C ++ такой параметр

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

так что он точно знает, что происходит?

Ваш Ответ

4   ответа
11

boost::split(), который позволяет задавать несколько разделителей и не требует предварительного знания размера входных данных:

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

Или, используя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;
}

Тем не менее, ограничение здесь заключается в том, что максимальная длина строки (Z) должно быть решено до разбора ввода.

@LoersAntario, обновленный ответ.
большое спасибо за ответ, но есть ли что-то еще, кроме boost или каких-либо внешних библиотек ... это можно сделать в стандартном c ++ или по крайней мере в stl Loers Antario
Может ли downvoter объяснить, пожалуйста?
14
#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;
}
+1, потому что это единственный ответ, который точно учитывает актуальный вопрос. Другие ответы не имеют, потому что1. using boost is not the simplest way (Я признаю, что это может быть самый изящный способ) и2. scanf is not C++ style (как указано автором соответствующего ответа).
2


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

и второй вариант, работа только со строкой.

#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;
}
@jogojapan не сейчас = (liveworkspace.org/code/b66dcfa19ce7620fb7b9e4c203c42f43
+1 за предложение регулярных выражений
Регулярные выражения являются хорошим предложением во многих таких случаях, +1 за это. Обратите внимание, что поддержка регулярных выражений доступна как часть C ++ в C ++ 11 - больше нет необходимости использовать Boost regex.
@ForEveR Верно. Я должен был проверить, но на самом деле поддержка регулярных выражений в GCC все еще не там, где она должна быть, особенно. группы захвата не работают. Кроме того, существуют различия в синтаксисе регулярных выражений. Например. стандартный способ сделать[\d] в С ++ 11 есть[[:digit:]], В любом случае, в качестве последнего комментария, поддержка регулярного выражения в C ++ 11 лучше, если вы используете Clang. При правильной настройке синтаксиса ваш пример кода должен работать там.
3

scanf, Это не слишком C ++ - иш, но он справляется с замечательно небольшим количеством строк кода:

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;

Идея состоит в том, чтобы указать символы, принимаемые строками, которые вы читаете, используя очень ограниченный синтаксис регулярного выражения. В этом случае первая строка читается до плюса, а вторая строка читается до знака равенства.

Похожие вопросы