Скопировать фиксированное количество байтов в std::deque

#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));
}