2009-06-11 2 views
17

Предположим, у меня есть входной файл в этом формате:Отформатированный вход на C++: как пропустить «токены»?

VAL1 VAL2 VAL3 
VAL1 VAL2 VAL3 

Я пишу программу, которая была бы заинтересована только в VAL1 и val3. В C, если я хотел «пропустить» второе значение, я бы следующим образом:

char VAL1[LENGTH]; char VAL3[LENGTH]; 
FILE * input_file; 
fscanf(input_file, "%s %*s %s", VAL1, VAL3); 

Значение, я бы использовал «% * S» форматировщик сделать fscanf() прочитать этот маркер и пропусти это. Как это сделать с помощью Cin? Есть ли подобная команда? Или мне нужно читать фиктивную переменную?

Заранее спасибо.

+0

Почему бы не просто прочитать маркер в некоторой переменной, но игнорировать его? – Nixuz

+0

@Nixuz: прочитайте мой комментарий к ответу Даниила. –

ответ

13

C++ String Toolkit Library (StrTk) имеет следующее решение проблемы:

#include <string> 
#include <deque> 
#include "strtk.hpp" 

int main() 
{ 
    struct line_type 
    { 
     std::string val1; 
     std::string val3; 
    }; 

    std::deque<line_type> line_list; 

    const std::string file_name = "data.txt"; 

    strtk::for_each_line(file_name, 
         [&line_list](const std::string& line) 
         { 
          strtk::ignore_token ignore; 
          line_type temp_line; 
          const bool result = strtk::parse(line, 
                  " ", 
                  temp_line.val1, 
                  ignore, 
                  temp_line.val3); 
          if (!result) return; 
          line_list.push_back(temp_line); 
         }); 

    return 0; 
} 

Больше примеров можно найти Here

1

Я бы просто прочитал его в фиктивной переменной. Если вам это понадобится в конце концов, оно будет доступно.

+0

Конечно, это мой выбор по умолчанию, но я готов его избежать, так как будет много (около 10) токенов, которых я не хочу. Кроме того, есть также мое собственное любопытство, пытаясь сделать что-то «красивым» способом.Я вроде как отказываюсь верить, что что-то, что уже присутствует в C, не рассматривалось в дизайне C++. –

2

Вы можете сделать это намного проще с помощью getline(). Просто используйте его для захвата всей строки, а затем проанализируйте значения между токенами (используйте strtok?)

Существует целый ряд других проблем с getline(), но он должен работать для вашей проблемы.

0

Вы можете использовать

cin.ignore(256, ' '); 

Это будет игнорировать все до либо 256 символов или пробелом.

Edit (форматирование и ...): альтернативы вы можете сделать:

int a, b; 
cin >> a >> b >> b; 
+0

Ничего себе, не знал этого. Ницца! :) –

+0

Творческий, но фиктивная переменная на самом деле была бы более ясной в этом случае =) –

5

Там в ignore функция доступна:

std::cin << val1; 
std::cin.ignore (9999, ' '); 
std::cin << val3; 

Первый аргумент определяет количество символов пропускаемых, то вторым параметром является разделитель, чтобы остановить пропуск.

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


Вот обычай Манипулятор:

template <class charT, class traits> 
inline std::basic_istream<charT, traits> & 
ignoreToken (std::basic_istream<charT, traits> &strm) 
{ 
    strm.ignore (9999, ' '); 
    return strm; 
} 

И вы могли бы использовать это так:

cin >> val1 >> ignoreToken >> val3 >> ignoreToken >> val5; 

(пс - я не компилировать это, так что, возможно, опечатка).

+0

Это ОЧЕНЬ близко к тому, что я хочу. Но нет ли способа игнорировать любое количество символов (или пробелов) вместо того, чтобы фиксировать действительно большое значение? –

+0

Нет. Вы должны поставить большое количество. Некоторые из документов, которые я прочитал, рекомендуют использовать «std :: numical_limits :: max()», но (IMO) это просто глупо. – eduffy

+0

std :: numeric_limits :: max() PS. Это не глупо, его защитное программирование. –

Смежные вопросы