Использование оператора извлечения ifstream в C ++ >> для чтения отформатированных данных из файла - PullRequest
12 голосов
/ 16 сентября 2011

В процессе обучения я пытаюсь использовать c ++ ifstream и его оператор >> для чтения данных из текстового файла с использованием приведенного ниже кода.Текстовый файл outdummy.txt имеет следующее содержимое:

just dummy
Hello ofstream
555

Мои вопросы - как считать данные char, представленные в файле, в массив или строку charКак это сделать, используя ifstream :: operator >> в коде ниже.

#include <iostream>
#include <fstream>

int main()
{
    int a;
    string s;
    char buf[100];
    ifstream in("outdummy.txt",ios_base::in);


    in.operator>>(a); //How to read integer? How to read the string data.??

    cout << a;

    in.close();
    getchar();
    return 0;
}

Ответы [ 4 ]

15 голосов
/ 16 сентября 2011

Если вы хотите использовать форматированный ввод, вы должны заранее знать, какие данные ожидать, и прочитать их в переменные соответствующего типа данных. Например, если вы знаете, что число всегда является пятым токеном, как в вашем примере, вы можете сделать это:

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 */ }
2 голосов
/ 16 сентября 2011
  1. ifstream имеет ios_base::in по умолчанию. Вам не нужно указывать это.
  2. operator>> может быть вызван непосредственно как оператор: in >> a.
  3. Чтение строк такое же: in >> s, но оговорка в том, что он разделен пробелами, поэтому он будет читать «просто» сам по себе, без «фиктивного».
  4. Если вы хотите прочитать полные строки, используйте std::getline(in, s).
1 голос
/ 16 сентября 2011

Поскольку вы решили использовать C-строки, вы можете использовать метод getline вашего ifstream объекта (не std::getline(), который работает с std::string s), что позволит вам укажите C-строку и максимальный размер буфера.

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

char buf[100];
char buf2[100];

in.getline(buf,sizeof(buf));
in.getline(buf2,sizeof(buf2));
in >> a;

Однако, как предложил другой автор, попробуйте использовать std::string и его методы, это облегчит вашу жизнь.

0 голосов
/ 16 сентября 2011

Вы можете прочитать содержимое файла и использовать Finite State Machine для анализа.

Пример:

void Parse(const char* buffer, size_t length);
size_t GetBufferSize();

size_t bufferSize = GetBufferSize();
char* buffer = new char[bufferSize];

std::ifstream in("input.txt");
while(in.getline(buffer, bufferSize)) {
    Parse(buffer, in.gcount());
}

Кроме того, вы можете использовать такой инструмент, как Flex , чтобы написать свой синтаксический анализатор.

...