#c #std
#c #std
Вопрос:
Я создаю класс, который буферизует некоторые двоичные данные, считываемые из std::cin
; Мне нужна некоторая ограниченная возможность обратного отслеживания потока. Более подробно, когда я read
n
бью байты из потока, я хочу иметь возможность перематывать до n
байтов в потоке.
В настоящее время я добавляю в буфер, добавляя отдельные символы к a std::deque
, но я ожидаю, что есть лучший способ копировать фрагменты данных из an std::istream
в a std::deque
.
В принципе, есть ли способ улучшить (удалить?) цикл while в load
функции ниже?
В настоящее время у меня есть:
#include<algorithm>
#include<deque>
class BufferedStdIn{
public:
BufferedStdIn(): m_buffer(), m_cursor(0){
}
// copy data out from my internal buffer to the client's array
// format dictated by external interface requirement
void read(char* dest, size_t n){
load(n)
std::copy( m_buffer.begin(), m_buffer.begin() n, dest );
m_cursor =n;
}
// Go backwards in the stream; return the number of bytes moved.
// @retval < input arg n indicates that we can't rewind as far as asked for
size_t rewind(size_t n){
int final_pos=m_cursor-n;
if( final_pos < 0 ){
// can't go as far as the client wants, just go back to start of my buffer
size_t moved=m_cursor;
m_cursor=0;
return moved;
}
else{ // can do what client wants
m_cursor=final_pos;
return n;
}
}
void load(n){
m_buffer.erase( m_buffer.begin(), m_buffer.begin() m_cursor);
m_cursor=0;
while( m_buffer.size()<n){
char c;
std::cin.get(c);
m_buffer.push_back(c);
}
}
// SNIP: other functions that let clients look at m_buffer
std::deque<char> m_buffer;
size_t m_cursor;
}
Комментарии:
1. что вы пытаетесь сделать? как насчет использования vector или istream в качестве буфера вместо этого?
2. Я пошел с
deque
этим, поскольку процесс таков: толчок назад, падение спереди — шаблон, который я обычно ассоциирую с deques. Я предполагаю, что я мог бы использоватьvector
и использовать тот факт, чтоvector<T>::iterator == T*
(на практике), и предоставить соответствующий итератор (указатель) для вызоваstd::cin.get()
.3. Если это ваш случай, я бы предложил использовать кольцевой буфер. у boost есть один. по сути, это вектор, который обтекается до начала, как только вы достигнете границ буфера. boost.org/doc/libs/1_55_0/doc/html/circular_buffer.html
Ответ №1:
Может быть, не более эффективно, но короче:
void load(size_t n)
{
m_buffer.erase( m_buffer.begin(), m_buffer.begin() m_cursor);
m_cursor=0;
if(m_buffer.size() < n)
std::copy_n(std::istream_iterator<char>(std::cin), n - m_buffer.size(), std::back_inserter(m_buffer));
}