2016-08-18 3 views
3

Чтобы понять, как входные потоки работы я разработал 2 из следующих классов:Пользовательский поток ввода. буфер потока и сгущенного метод

#include <iostream> 

class my_streambuf: public std::streambuf 
{ 
private: 
    std::streambuf* buffer; 

    char ch; 

protected: 

    virtual std::streambuf::int_type underflow() 
    { 
    std::streambuf::int_type result = buffer->sbumpc(); 

    if (result != traits_type::eof()) 
    { 
     ch = traits_type::to_char_type(result); 

     setg(&ch, &ch, &ch + 1); 
    } 

    return result; 
    } 

public: 
    my_streambuf(std::streambuf* buffer) : buffer(buffer) {}; 

    virtual ~my_streambuf() {}; 
}; 

class my_istream: public std::istream 
{ 
public: 
    my_istream(std::istream& stream) : std::istream(new my_streambuf(stream.rdbuf())) {}; 

    virtual ~my_istream() 
    { 
    delete rdbuf(); 
    } 
}; 

int main() 
{ 
    char s[32]; 
    my_istream is(std::cin); 

    is >> s; 
    std::cout << s; 
    return 0; 
} 

, которые работают нормально, пока я не изменить логику underflow метода. Основная цель состоит в том, чтобы сохранить данные в c-string valiable s, который отличается от пользовательского ввода. Для того, чтобы сделать простой тест, я изменил метод underflow быть следующим:

virtual std::streambuf::int_type underflow() 
{ 
    std::streambuf::int_type result = buffer->sbumpc(); 

    if (result != traits_type::eof()) 
    { 
    result = traits_type::to_int_type('+'); // <-- this was added 

    ch = traits_type::to_char_type(result); 

    setg(&ch, &ch, &ch + 1); 
    } 

    return result; 
} 

С идеей заключается в том, чтобы вернуть метод только + символов вместо пользовательского ввода символов. Так, например, если вход 123, я ожидаю, что +++ будет храниться в переменной s. И это не работает. Консоль висит, как будто она ждет больше ввода. Помогает только определенное нажатие клавиши (или отправка EOF).

Что мне здесь не хватает?


Как указывали @ferosekhanj, проблема была недостающий символ новой строки, который не был возвращен модифицированной версией underflow к абоненту. Поэтому, чтобы код работал правильно, он должен быть возвращен. Эта версия метода работает нормально.

virtual std::streambuf::int_type underflow() 
{ 
    std::streambuf::int_type result = buffer->sbumpc(); 

    if ((result != traits_type::eof()) && !traits_type::eq(traits_type::to_char_type(result), '\n')) 
    { 
    result = traits_type::to_int_type('+'); 

    ch = traits_type::to_char_type(result); 

    setg(&ch, &ch, &ch + 1); 
    } 

    return result; 
} 

ответ

2

Из моего старого опыта на С ++ поток buf является базовым буфером для потока. Когда потоку требуется больше данных, он вызывает переполнение. Внутри этого метода вы можете читать из своего источника и setg. Когда поток данных записывается обратно в источник, он вызывает переполнение. Внутри этого метода вы читаете из потока, пишите обратно в свой источник и setp. Например, если вы читаете данные из сокета в вашем streambuf

socketbuf::int_type socketbuf::underflow(){ 
    int bytesRead = 0; 
    try{ 
    bytesRead = soc->read(inbuffer,BUFFER_SIZE-1,0); 
    if(bytesRead <= 0){ 
     return traits_type::eof(); 
    } 
    }catch(IOException ioe){ 
    cout<<"Unable to read data"<<endl; 
    return traits_type::eof(); 
    } 
    setg(inbuffer,inbuffer,inbuffer+bytesRead); 
    return traits_type::to_int_type(inbuffer[0]); 
} 

socketbuf::int_type socketbuf::overflow(socketbuf::int_type c){ 
    int bytesWritten = 0; 
    try{ 
    if(pptr() - pbase() > 0){ 
     bytesWritten = soc->write(pbase(),(pptr() - pbase()),0); 
     if(bytesWritten <= 0) return traits_type::not_eof(c); 
    } 
    }catch(IOException ioe){ 
    cout<<"Unable to write data"<<endl; 
    return traits_type::eof(); 
    } 
    outbuffer[0] = traits_type::to_char_type(c); 
    setp(outbuffer,outbuffer+1,outbuffer+BUFFER_SIZE); 
    return traits_type::not_eof(c); 
} 

Сейчас подходит к коду, вы добавили

result = traits_type::to_int_type('+'); // <-- this was added 

поток считывает строку, пока она не видит LF (перевод строки) , Поэтому, когда придет символ LF, вы закончите писать это с помощью «+», поэтому поток будет ждать (для LF) навсегда. При добавлении этой проверки ваш код должен делать то, что вы ожидаете. output '+++', если вы вводите 'abc'

if (result != 10)// <-- add this in addition 
    result = traits_type::to_int_type('+'); // <-- this was added 

Надеюсь, это поможет вам.

+0

Если я не ошибаюсь, только 'cin' читает строку, пока не увидит линию. Другие потоки делают это до 'EOF'. – HighPredator

+0

Что вы подразумеваете под другими потоками? cin - всего лишь экземпляр std: istream – ferosekhanj

+0

Я имею в виду, что, насколько мне известно, это реализовано 'in' cin, а не класс потока. – HighPredator

Смежные вопросы