Если вы хотите использовать форматированный ввод, вы должны заранее знать, какие данные ожидать, и прочитать их в переменные соответствующего типа данных. Например, если вы знаете, что число всегда является пятым токеном, как в вашем примере, вы можете сделать это:
std::string s1, s2, s3, s4;
int n;
std::ifstream in("outdummy.txt");
if (in >> s1 >> s2 >> s3 >> s4 >> n)
{
std::cout << "We read the number " << n << std::endl;
}
С другой стороны, если вы знаете, что число всегда находится в третьей строке, само по себе:
std::string line;
std::getline(in, line); // have line 1
std::getline(in, line); // have line 2
std::getline(in, line); // have line 3
std::istringstream iss(line);
if (iss >> n)
{
std::cout << "We read the number " << n << std::endl;
}
Как видите, чтобы прочитать токен как строку, вы просто передаете его в std::string
. Важно помнить, что отформатированный оператор ввода работает с токеном по токену, а токены разделены пробелами (пробелы, табуляции, новые строки). Обычный фундаментальный выбор - обработка файла полностью токенами (первая версия) или построчно (вторая версия). Для построчной обработки вы сначала используете getline
для чтения одной строки в строку, а затем используете поток строк для токенизации строки.
Слово о проверке: вы не можете знать, будет ли форматированное извлечение действительно успешным, потому что это зависит от входных данных. Следовательно, вы должны всегда проверять, успешно ли выполнена операция ввода, и прервать анализ, если это не так, потому что в случае сбоя ваши переменные не будут содержать правильные данные, но у вас нет возможности узнать что позже. Поэтому всегда говорите так:
if (in >> v) { /* ... */ } // v is some suitable variable
else { /* could not read into v */ }
if (std::getline(in, line)) { /* process line */ }
else { /* error, no line! */ }
Последняя конструкция обычно используется в цикле while
, чтобы читать весь файл построчно:
while (std::getline(in, line)) { /* process line */ }