Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <memory>
- #include <algorithm>
- /*
- * Напишите класс StdInputStream, который является оберткой над классом std::istream и позволяет читать заданное
- * количество байт из входного потока по данному указателю с помощью метода Read. Метод Read выглядит следующим образом:
- * `std::streamsize Read(char* buffer, std::streamsize numBytes)`, тут
- * - buffer -- указатель, по адресу которого будут записаны прочитанные из потока байты
- * - numBytes -- максимальное количество байтов, которое мы хотим прочитать
- * - возвращаемое значение -- сколько байтов было прочитано на самом деле.
- *
- * Также необходимо написать класс BufferedStdInputStream, который реализует такой же интерфейс, буферизует прочитанные
- * из потока данные. Если при вызове метода Read в буфере еще остались непрочитанные данные от предыдущего вызова,
- * то нужно сначала использовать их, а только потом читать из входного потока, если данных в буфере не хватило.
- *
- * Для того чтобы абстрагировать вызывающий код от нюансов реализации этих классов, предусмотрите класс StdInputStreamBuilder,
- * с помощью которого можно получить объект типа StdInputStream или BufferedStdInputStream в зависимости от того,
- * нужна буферизация или нет (см функцию main)
- */
- class IInputStream {
- public:
- virtual ~IInputStream() = default;
- virtual std::streamsize Read(char* buffer, std::streamsize numBytes) = 0;
- };
- class StdInputStream : public IInputStream {
- public:
- StdInputStream(std::istream& stream) : stream_(stream) {}
- std::streamsize Read(char* buffer, std::streamsize numBytes) override {
- stream_.read(buffer, numBytes);
- return stream_.gcount();
- }
- private:
- std::istream& stream_;
- };
- class BufferedStdInputStream : public IInputStream {
- public:
- BufferedStdInputStream(std::istream& stream, size_t bufferSize) : stream_(stream), bufferSize_(bufferSize) {
- buffer_ = new char[bufferSize_];
- FillBuffer();
- }
- std::streamsize Read(char* buffer, std::streamsize numBytes) override {
- std::streamsize readBytes = 0;
- while (readBytes < numBytes) {
- if (bufferPos_ == bufferSize_) {
- FillBuffer();
- }
- buffer[readBytes++] = buffer_[bufferPos_++];
- }
- return readBytes;
- }
- private:
- void FillBuffer() {
- stream_.read(buffer_, bufferSize_);
- bufferPos_ = 0;
- }
- std::istream& stream_;
- size_t bufferSize_;
- char* buffer_;
- size_t bufferPos_ = 0;
- };
- class StdInputStreamBuilder {
- public:
- StdInputStreamBuilder& Source(std::istream& stdStream) {
- stdStream_ = &stdStream;
- return *this;
- }
- StdInputStreamBuilder& Buffered(size_t bufferSize) {
- bufferSize_ = bufferSize;
- return *this;
- }
- std::shared_ptr<IInputStream> Build() const {
- if (bufferSize_ > 0) {
- return std::make_shared<BufferedStdInputStream>(*stdStream_, bufferSize_);
- }
- return std::make_shared<StdInputStream>(*stdStream_);
- }
- private:
- std::istream* stdStream_ = nullptr;
- size_t bufferSize_ = 0;
- };
- int main() {
- std::shared_ptr<IInputStream> unbufferedStream = StdInputStreamBuilder().Source(std::cin).Build();
- std::shared_ptr<IInputStream> bufferedStream = StdInputStreamBuilder().Source(std::cin).Buffered(10).Build();
- std::string s(10, '\0');
- std::cout << unbufferedStream->Read(s.data(), (std::streamsize)s.size()) << " bytes\n";
- std::cout << s << std::endl;
- std::fill(s.begin(), s.end(), '\0');
- std::cout << bufferedStream->Read(s.data(), (std::streamsize)s.size()) << " bytes\n";
- std::cout << s << std::endl;
- std::fill(s.begin(), s.end(), '\0');
- std::cout << bufferedStream->Read(s.data(), (std::streamsize)s.size()) << " bytes\n";
- std::cout << s << std::endl;
- std::fill(s.begin(), s.end(), '\0');
- std::cout << bufferedStream->Read(s.data(), (std::streamsize)s.size()) << " bytes\n";
- std::cout << s << std::endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment