У меня есть входной поток со следующими строками:
# <int> <int>
<some_data_type> <some_data_type> <some_data_type> ..... <some_data_type>
<some_data_type_1> <some_data_type_2> <some_data_type_3> <some_data_type_1> <some_data_type_2> <some_data_type_3> .... <some_data_type_1> <some_data_type_2> <some_data_type_3>
В приведенном выше потоке все три строки различны и должны быть проанализированы по-разному. В настоящее время я использую метод чтения следующим образом:
void reader( std::istream & is, DataStructure & d ){
std::string line;
getline(is,line);
std::stringstream s(line);
//parse line 1
getline(is,line);
std::stringstream line2(line);
//parse line 2
getline(is,line);
std::stringstream line3(line);
//parse line 3
}
Теперь идея не в том, чтобы использовать std::stringstream
вообще, поскольку строка может быть произвольно большой, и мы не хотим загружать все в память дважды. Таким образом, было бы лучше, если бы можно было читать из входного потока непосредственно в заданную пользователем структуру данных d.
Идея состоит в том, чтобы использовать std::istream_iterator
но, к сожалению, разные строки имеют разные потребности в разборе. Например, в последней строке три элемента из потока вместе составляют один элемент данных.
Единственная идея, которая кажется мне правдоподобной на данный момент, — это непосредственная обработка буфера потока. Было бы здорово, если бы кто-нибудь мог порекомендовать лучший способ сделать это.
НОТА: Не могу использовать третичную структуру данных, как std::stringstream
, Важно читать из потока непосредственно в предоставленную пользователем структуру данных.
РЕДАКТИРОВАТЬ: Обратите внимание, что нам разрешено только один проход по файлу.
Теперь идея вовсе не в том, чтобы использовать std :: stringstream как строку
может быть сколь угодно большим, и мы не хотим загружать все в память
дважды. Так что было бы лучше, если бы можно было читать с
входной поток непосредственно в заданную пользователем структуру данных d.
Olaf объяснил оператор извлечения выше, но тогда у нас есть новое требование:
Это будет работать только для первой строки, где известно, что есть
фиксированное количество элементов.
а также
(2) К сожалению, у меня нет никакого дискриминатора вне моих знаний о том, что каждый экземпляр данных
структура должна быть создана с информацией, хранящейся в трех
разные линии. Все три линии имеют разную длину и разные
элементы данных. Кроме того, я не могу изменить формат.
плюс
(3) Вся информация рассматривается как целое число без знака.
Теперь следующая проблема заключается в том, что мы не знаем, какова структура данных на самом деле, поэтому, учитывая то, что произошло до того, как она каким-то образом окажется динамичной. Поскольку мы можем обрабатывать данные как unsigned int, тогда мы можем использовать оператор извлечения, но читать в динамический член:
vector<unsigned int> myUInts;
...
inFile >> currentUInt;
myUInts.push_back(currentUInt);
Но тогда возникает вопрос, где остановиться. Это в конце первой строки, третьей? Если вам нужно прочитать произвольное количество целых чисел без знака, при этом проверяя новую строку, вам также потребуется обработать пробел:
inFile.unsetf(ios_base::skipws);
То, как вы на самом деле справляетесь с этим, выходит за рамки того, что я могу сказать сейчас, без каких-либо более четких требований. Но я думаю, это будет в форме:
inFile >> myMember;
char next = infile.peek()
//skip whitespace and check for new line
//Repeat until data structure filled, and repeat for each data structure.
Тогда не используйте std::getline()
совсем. Определите оператор istream для ваших типов и используйте их напрямую
std::istream &operator >>(std::istream &f, DataStructure &d)
{
f >> d.member1 >> d.member2 >> ...;
return f;
}
void reader(std::istream & is, DataStructure &d)
{
is >> d;
}
Там нет необходимости возиться с std::istream_iterator
или непосредственно манипулируя потоковым буфером.