Чтение / анализ ввода текстового файла c ++ - PullRequest
0 голосов
/ 04 марта 2012

Небольшая предыстория: я работаю над головоломкой со скользящими блоками для школьного проекта, и мы впервые используем C ++ вместо Java.Это первый раз, когда мне пришлось реализовать что-то, что читает данные из файла.

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

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

Первая строка содержит 2 целых числа, которые будут указывать длину и ширину сетки, следующеестроки будут иметь 4 целых числа и символ для использования в качестве аргументов при создании блоков.

Мой вопрос заключается в следующем: если я вместо этого читаю файл символ за символом, есть ли функция, которую я могу использовать, которая обнаружит, еслисимвол является целым числом или символом (и игнорирует пробелы), поэтому я могу сразу же сохранить их и создать объекты блоков при чтении файла?Как бы я имел дело с целыми числами> 10 в этом случае?

РЕДАКТИРОВАТЬ: Просто отмечая, что я использую fstream для чтения файлов, я не знаком с другими методами ввода

Пример ввода:

4  4
3  1  2  1  b
1  1  1  1  a 

Ответы [ 4 ]

2 голосов
/ 04 марта 2012

Чтобы определить, может ли фрагмент строки быть проанализирован как целое число, вам просто нужно проанализировать его и посмотреть, добьетесь ли вы успеха.Лучшая функция для этого, вероятно, будет std::strtoul(), поскольку ее можно указать, сколько символов она потребляет, чтобы вы могли продолжить синтаксический анализ после этого.(Подробнее см. На странице man.)

Однако, если вы уже знаете формат вашего файла, вы можете использовать форматированное извлечение iostream.Это довольно просто:

#include <fstream>


std::ifstream infile("thefile.txt");

int n1, n2, x1, x2, x3, x4;
char c;

if (!(infile >> n1 >> n2)) { /* error, could not read first line! Abort. */ }

while (infile >> x1 >> x2 >> x3 >> x4 >> c)
{
    // successfully extracted one line, data is in x1, ..., x4, c.
}

Другая альтернатива - прочитать каждую строку в строку (используя std::getline), затем создать поток строки из этой строки и проанализировать поток строки с помощью >>.Это дает дополнительное преимущество, заключающееся в том, что вы можете обнаруживать и пропускать неверные строки и восстанавливать данные, в то время как в представленном выше прямом отформатированном извлечении вы не сможете восстановить ни одну ошибку.

1 голос
/ 04 марта 2012

Я бы прочитал каждую строку в строку (как вы это делали).
Затем я бы прочитал токены из этой строки в соответствующие переменные.

Оператор >> применительно кstream преобразует следующее значение в потоке в правильный тип.Если это невозможно, он устанавливает флаги в потоке, указывающие на сбой, который легко проверить.

 int  x;
 stream >> x; // ignores white space then: reads an integer from the stream into x

 char c;
 stream >> c; // ignores white space then: reads an char from the stream into c

 double d;
 stream >> d; // ignores white space then: reads an double from the stream into d

Предполагая ваш ввод:

4  4
3  1  2  1  b
1  1  1  1  a 

Не зная, что означают значениявысказывать свои предположения в комментариях.

// Assume that stream is a std::fstream already opened to you file.

std::string line1;
std::getline(stream, line1);           // reads "4 4" into `line1`

std::stringstream  line1stream(line1); // convert line1 into a stream for reading.
int a;
int b;
line1stream >> a >> b;   // reads "4 4" from 'line1' into a (now 4) b (now 4)
if (!stream || !line1stream)
{
     // failed reading the first line.
     // either reading the line failed (!stream)
     // or     reading 2 integers from line1stream failed (!line1stream)
     throw SomeException("Failed");
}


std::string line2;
std::getline(stream, line2);           // reads "3  1  2  1  b" into line2

std::stringstream line2stream(line2);  // convers line2 into a stream for reading.
int  data[4];
char c;

line2stream >> data[0] >> data[1] >> data[2] >> data[3] >> c;
if (!stream || !line2stream)
{
     // failed reading the second line.
     // either reading the line failed (!stream)
     // or     reading 4 integers and one char from line2stream failed (!line2stream)
     throw SomeException("Failed");
}
1 голос
/ 04 марта 2012

Если вы можете утверждать каждый тип, я предлагаю использовать потоковые операторы, как если бы вы использовали cin .

#include <fstream>

using namespace std;

int main()
{
    fstream fileStream;
    fileStream.open("inputfile.txt");

    int firstNumber;
    fileStream >> firstNumber;

    char firstChar;
    fileStream >> firstChar;
}

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

1 голос
/ 04 марта 2012

ifstreams также являются istreams, поэтому вы можете использовать тот же оператор >>, что и с std :: cin.

int main()
{
    std::ifstream s("test.txt");
    if (s.is_open())
    {
        int i, j, k;
        s >> i >> j >> k;
    }
}

Обратите внимание, что это не самый быстрый способ анализа, но он, вероятно, не имеет к вам отношения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...