क्या डेटा को कॉपी किए बिना string_view से एक स्ट्रिंग बनाने का एक तरीका है?


10

मुझे लगता है कि यह एक बहुत कठिन सवाल है। मैं विशेष रूप से उपयोग करना चाहता हूं std::get_time, लेकिन इसके साथ किसी प्रकार की धारा का उपयोग करने की आवश्यकता है। मैं डेटा को एक में पास कर रहा हूं string_viewऔर इसे केवल दिनांक को पार्स करने के लिए कॉपी करने से बचना चाहूंगा।


1
मैं इसे अभी देख सकता हूं, C ++ 23 पर आ रहा हूं; std::basic_string_view_stream;-) यकीन नहीं होता कि आप नकल से बच सकते हैं। शायद हॉवर्ड को एक तरकीब पता होगी।
नाथनऑलिवर

2
लंबे समय से पदावनत std::strstreamकर सकते हैं।
इगोर टांडेटनिक

मैंने इस C ++ 14 को गलत तरीके से टैग किया है क्योंकि हम इस परियोजना में हैं। मैं वास्तव में भूल गया कि हम उपयोग कर रहे हैं boost::string_view। सवाल अभी भी वैध है, हालांकि।
बार्टेक बैनवाक्विज़

जवाबों:


5

आप Boost.Iostreams पुस्तकालय के साथ आसानी से कर सकते हैं:

#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

#include <iostream>
#include <string>

int main() {
    std::string_view buf{"hello\n"};
    boost::iostreams::stream<boost::iostreams::basic_array_source<char>> stream(buf.begin(), buf.size());

    std::string s;
    stream >> s;
    std::cout << s << '\n';
}

आप ऐसा करने के साथ सक्षम होना चाहिए std::stringstreamऔर std::basic_stringbuf<CharT,Traits,Allocator>::setbufलेकिन सी ++ मानक अपनी आवश्यकताओं को असफल:

प्रभाव [ setbuf] का कार्यान्वयन-परिभाषित है: कुछ कार्यान्वयन कुछ भी नहीं करते हैं, जबकि कुछ कार्यान्वयन स्पष्ट std::stringसदस्य को वर्तमान में बफर के रूप में उपयोग करते हैं और उपयोगकर्ता द्वारा आपूर्ति किए गए वर्ण सरणी का उपयोग करना शुरू करते हैं n, जिसका पहला तत्व sबफर और इनपुट / आउटपुट चरित्र अनुक्रम।


1

एक वैकल्पिक समाधान, Boost.IOstream के बिना (जब आप इसका उपयोग नहीं कर सकते हैं)। यह विस्तारित करने वाले std पर आधारित है :: basic_streambuf और std :: basic_istream।

#include <cstring>
#include <iostream>
#include <istream>
#include <string_view>

template<typename __char_type, class __traits_type >
class view_streambuf final: public std::basic_streambuf<__char_type, __traits_type > {
private:
    typedef std::basic_streambuf<__char_type, __traits_type > super_type;
    typedef view_streambuf<__char_type, __traits_type> self_type;
public:

    /**
    *  These are standard types.  They permit a standardized way of
    *  referring to names of (or names dependent on) the template
    *  parameters, which are specific to the implementation.
    */
    typedef typename super_type::char_type char_type;
    typedef typename super_type::traits_type traits_type;
    typedef typename traits_type::int_type int_type;
    typedef typename traits_type::pos_type pos_type;
    typedef typename traits_type::off_type off_type;

    typedef typename std::basic_string_view<char_type, traits_type> source_view;

    view_streambuf(const source_view& src) noexcept:
      super_type(),
      src_( src )
    {
        char_type *buff = const_cast<char_type*>( src_.data() );
        this->setg( buff , buff, buff + src_.length() );
    }

    virtual std::streamsize xsgetn(char_type* __s, std::streamsize __n) override
    {
        if(0 == __n)
            return 0;
        if( (this->gptr() + __n) >= this->egptr() ) {
            __n =  this->egptr() - this->gptr();
            if(0 == __n && !traits_type::not_eof( this->underflow() ) )
                return -1;
        }
        std::memmove( static_cast<void*>(__s), this->gptr(), __n);
        this->gbump( static_cast<int>(__n) );
        return __n;
    }

    virtual int_type pbackfail(int_type __c) override
    {
        char_type *pos = this->gptr() - 1;
        *pos = traits_type::to_char_type( __c );
        this->pbump(-1);
        return 1;
    }

    virtual int_type underflow() override
    {
        return traits_type::eof();
    }

    virtual std::streamsize showmanyc() override
    {
        return static_cast<std::streamsize>( this->egptr() - this->gptr() );
    }

    virtual ~view_streambuf() override
    {}
private:
    const source_view& src_;
};

template<typename _char_type>
class view_istream final:public std::basic_istream<_char_type, std::char_traits<_char_type> > {
    view_istream(const view_istream&) = delete;
    view_istream& operator=(const view_istream&) = delete;
private:
    typedef std::basic_istream<_char_type, std::char_traits<_char_type> > super_type;
    typedef view_streambuf<_char_type, std::char_traits<_char_type> > streambuf_type;
public:
    typedef _char_type  char_type;
    typedef typename super_type::int_type int_type;
    typedef typename super_type::pos_type pos_type;
    typedef typename super_type::off_type off_type;
    typedef typename super_type::traits_type traits_type;
    typedef typename streambuf_type::source_view source_view;

    view_istream(const source_view& src):
        super_type( nullptr ),
        sb_(nullptr)
    {
        sb_ = new streambuf_type(src);
        this->init( sb_ );
    }


    view_istream(view_istream&& other) noexcept:
        super_type( std::forward<view_istream>(other) ),
        sb_( std::move( other.sb_ ) )
    {}

    view_istream& operator=(view_istream&& rhs) noexcept
    {
        view_istream( std::forward<view_istream>(rhs) ).swap( *this );
        return *this;
    }

    virtual ~view_istream() override {
        delete sb_;
    }

private:
    streambuf_type *sb_;
};


int main(int argc, const char** argv)
{
    std::string_view v("ABDCD\n 123\n FAG\n 456789");

    view_istream<char> in( v );

    std::string s;
    in >> s;
    std::cout << s << std::endl;

    int i;
    in >> i;
    std::cout << i << std::endl;

    in >> s;
    std::cout << s << std::endl;

    in >> i;
    std::cout << i << std::endl;

    return 0;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.