Что такое cin аналог отформатированного ввода scanf?

С помощью scanf, как правило, есть прямой способ получить отформатированный ввод:

1) строка с действительным числом больше 0 и меньше 1. Оканчивается на "x", например: 0,32432523x

scanf("0.%[0-9]x", &number);

2) строка представляет собой дополнение в формате :30+28=пятьдесят восемь

scanf(":%d+%d=%99s", &number1, &number2, &total);

Что представляет собой решение cin, использующее только стандартную библиотеку?


person Alessandro Stamatto    schedule 15.01.2013    source источник
comment
Нигде почти не так красиво... scanf действительно мощный. Лично я читаю в string, беру указатель через string::c_str() и затем sscanf его. Или я сам токенизирую его из stringstream или чего-то еще.   -  person paddy    schedule 15.01.2013
comment
Для такого форматированного ввода в C++ вы можете рассмотреть что-то вроде Boost Spirit. Это может быть излишним, но это будет чище, чем прямое использование iostreams.   -  person Jerry Coffin    schedule 15.01.2013
comment
scanf побеждает в этом, потому что он одновременно дает вам возвращаемое значение, которое вы можете проверить в одном месте, чтобы убедиться, что все совпадает. В потоке cin вам придется проверить несколько вещей вручную.   -  person doug65536    schedule 15.01.2013


Ответы (2)


Используйте оператор >> для чтения из cin.

  int number1, number2;
  std::string text;
  char plus, equals;
  std::cin >> number1 >> plus >> number2 >> equals >> text;
  if (!std::cin.fail() && plus == '+' && equals == '=' && !text.empty())
    std::cout << "matched";

Это не так хорошо, как scanf, потому что вам придется самостоятельно проверять любые литералы, которые были в строке scanf. Выполнение этого с потоками почти наверняка потребует гораздо больше строк кода, чем scanf.

Я бы использовал сканф.

person doug65536    schedule 15.01.2013
comment
Используйте cin.fail(), а не cin.bad(), или используйте cin непосредственно как условное выражение. - person Ulrich Eckhardt; 15.01.2013
comment
Я изменил его с bad() на fail(). Хороший звонок. - person doug65536; 15.01.2013

Вы можете создать простой класс для проверки ввода.

struct confirm_input {
    char const *str;

    confirm_input( char const *in ) : str( in ) {}

    friend std::istream &operator >>
        ( std::istream &s, confirm_input const &o ) {

        for ( char const *p = o.str; * p; ++ p ) {
            if ( std::isspace( * p ) ) {
                std::istream::sentry k( s ); // discard whitespace
            } else if ( (c = s.get() ) != * p ) {
                s.setstate( std::ios::failbit ); // stop extracting
            }
        }
        return s;
     }
};

использование:

std::cin >> x >> confirm_input( " = " ) >> y;
person Potatoswatter    schedule 15.01.2013
comment
Очень хорошо. Идея очень гибкая, вы можете разобрать прямо в объект таким образом. - person doug65536; 15.01.2013