std::istream



  • Was sind denn das für Daten?

    Wieso hast Du die als String vorliegen? Benutzt Du eine Bibliothek, die Dir einen string zurückgibt?
    Wahrscheinlich hast Du doch eher eine Datei o.ä.?


  • Mod

    lapdancer schrieb:

    gibt es einen standardkonformen weg, einen unsigned char in einen signed char umzuwandeln, ohne dass daten verloren gehen? (und dann entsprechend auch umgekehrt, also sc -> uc)

    Daten können nur verloren gehen wenn der Zieltyp kleiner ist als der Quelltyp; das ist hier nicht der Fall. Das Bitmuster wird völlig gleich bleiben; nur wird es anders interpretiert. e.g.

    unsigned char uc = 254;
    signed char sc = uc; // sc ist jetzt negativ (Zweierkomplement)
    uc = sc; // uc hat immer noch den Wert 254
    

    wie kann man einen modifizierten istream schreiben

    Ich glaube zu wissen was du suchst. Es gibt eine Methode Namens pubsetbuf :

    #include <sstream>
    #include <iostream>
    
    int main()
    {
    	std::string str = "54 5 658";
    	std::istringstream stream;
    	stream.rdbuf()->pubsetbuf(&str[0], str.size());
    
    	for (int i; stream >> i;)
    		std::cout << i << ' ';
    }
    

  • Mod

    Da gibt es noch was nettes in Boost;

    #include <boost/iostreams/stream.hpp>
    #include <iostream>
    
    int main()
    {
    	std::string str = "54 5 658";
    	boost::iostreams::stream<boost::iostreams::array_source> stream( str.data(), str.size() ); // Funktioniert selbstverständlich auch mit deque
    
    	for (int i; stream >> i;)
    		std::cout << i << ' ';
    }
    

    Und falls es aus einer Datei kommt - warum eigentlich der Umweg über den String?



  • lapdancer schrieb:

    hi, es gibt eine funktion die daten aus einem istream liest und verarbeitet, ich habe diese daten als string vorliegen. es sind jedoch sehr viele daten, sodass ein kopieren in einen istringstream langsam ist oder sogar fehlschlägt (wenn nicht genügend speicher vorhanden ist). wie kann man einen modifizierten istream schreiben, der direkt auf dem stream operiert, oder noch allgemeiner (falls ich mal zu deque oder so umschwenken möchte) auf iteratoren?

    Beschreibe doch bitte, was genau in der Datei steht; bzw. poste hier am besten die ersten Dutzend Zeilen aus dieser Datei, und sage an, was Du damit wirklich vor hast.

    Arcoth schrieb:

    Und falls es aus einer Datei kommt - warum eigentlich der Umweg über den String?

    ja - warum eigentlich!



  • Ja, so etwas sieht man leider öfters (bei Anfängern): file -> string -> stream
    Bedauerlich!

    Werner Salomon: warum hast du nicht schon vor Jahren ein Standardbuch darüber geschrieben? 😉



  • lapdancer schrieb:

    wie kann man einen modifizierten istream schreiben, der direkt auf dem stream string operiert, [...]

    ein kleiner tippfehler meinerseits von vorhin.

    @Furble Wurble
    ich habe die daten in einem container weil ich sie generiere um damit dann die funktion zu füttern, die jedoch einen istream erwartet. ebenso brauche ich während dem generieren wahlfreien zugriff auf den speicher.

    @Arcoth
    ist es nicht ub wenn man z.b. 254 in einem signed char abspeichert? dieser wert liegt ja ausserhalb des wertebereiches dieses typs.

    @rest
    wo hab ich geschrieben dass die daten aus einer datei kommen? sonst würde ich ja einfach einen ifstream aufmachen und den übergeben...



  • lapdancer schrieb:

    ist es nicht ub wenn man z.b. 254 in einem signed char abspeichert? dieser wert liegt ja ausserhalb des wertebereiches dieses typs.

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf schrieb:

    If the destination type is signed, the value is unchanged if it can be represented in the destination type (and
    bit-field width); otherwise, the value is implementation-defined.


  • Mod

    ist es nicht ub wenn man z.b. 254 in einem signed char abspeichert? dieser wert liegt ja ausserhalb des wertebereiches dieses typs.

    Nein; siehe ProfiProgrammierers Zitat, das existiert schon lange unverändert als §4.7/3.
    @ProfiProgrammierer: Künftig bitte in Final Drafts schaun, für C++11 wäre das N3797.

    wo hab ich geschrieben dass die daten aus einer datei kommen?

    Natürlich nirgends. Wo haben wir geschrieben dass wir wissen woher die Daten kommen? Ich schrieb falls...

    Wo kommen denn soviele Daten in einem Pack her? Da denkt man einfach an eine Datei.

    ich habe die daten in einem container weil ich sie generiere um damit dann die funktion zu füttern, die jedoch einen istream erwartet.

    ... funktioniert denn dann die von mir vorgeschlagene Lösung oder nicht?



  • ok, danke, das mit dem signed / unsigned war mir nicht bewusst.

    Arcoth schrieb:

    Wo haben wir geschrieben dass wir wissen woher die Daten kommen?

    Th69's post hat sich sehr danach angehört, dich hab ich ja mit dem "@rest" eigentlich ausgeschlossen, da ich auf deinen post schon im spezifischen eingegangen bin.

    Arcoth schrieb:

    ... funktioniert denn dann die von mir vorgeschlagene Lösung oder nicht?

    sie funktionieren ganz gut (ich habe nur die erste getestet da ich spontan kein boost zur hand habe), leider eben nur für container mit zusammenhängendem speicher.

    wenn ich das richtig sehe muss ich nur einen streambuf schreiben, der von streambuf erbt und der zwei iteratoren speichert und mit diesen arbeitet. und dann kann ich einen istream erstellen diesen mit meinem eigenen streambuf konstruieren.


  • Mod

    Arcoth schrieb:

    @ProfiProgrammierer: Künftig bitte in Final Drafts schaun, für C++11 wäre das N3797.

    Das wäre genau genommen N3291 welches geschützt ist, und die beste Annäherung dafür ist zweifellos N3337 (nur textliche Änderungen gegenüber dem Standard, siehe N3338).

    Für C++14 ist es N3936 - ebenfalls geschützt. Dafür wäre gegenwärtig N3797 zusammen mit N3938 zu Rate zu ziehen.


  • Mod

    camper schrieb:

    Arcoth schrieb:

    @ProfiProgrammierer: Künftig bitte in Final Drafts schaun, für C++11 wäre das N3797.

    Das wäre genau genommen N3291 welches geschützt ist, und die beste Annäherung dafür ist zweifellos N3337 (nur textliche Änderungen gegenüber dem Standard, siehe N3338).

    Für C++14 ist es N3936 - ebenfalls geschützt. Dafür wäre gegenwärtig N3797 zusammen mit N3938 zu Rate zu ziehen.

    Ich dachte es wäre lediglich ein älterer Draft, danke für die Aufklärung.

    N3797 war natürlich ein Tippfehler, ich meine N3337. Das ist meines Wissens nach (wie du ja bestätigt hast) die beste Annäherung, "the latest publicly available draft".

    leider eben nur für container mit zusammenhängendem speicher.

    Willst du etwa mehrere Gigabyte in einer verketteten Liste speichern?

    Ganz grob heruntergetippt:

    #include <streambuf>
    #include <iterator>
    #include <type_traits>
    
    template <typename Iterator,
              typename CharT,
              typename Traits = std::char_traits<CharT>>
    class basic_iterator_streambuf : public std::basic_streambuf<CharT, Traits>
    {
    	Iterator first, current, last;
    
    	using char_type = CharT;
    	using traits_type = Traits;
    
    	using int_type = typename traits_type::int_type;
    
    	virtual int_type underflow() override
    	{
    		if (current != last)
    			return *current;
    
    		return traits_type::eof();
    	}
    
    	virtual int_type uflow() override
    	{
    		auto c = underflow();
    		if (traits_type::eq_int_type(c, traits_type::eof()))
    			return c;
    
    		++current;
    		return c;
    	}
    
    	int_type pbackfail_noneof_impl( char_type c, std::true_type )
    	{
    		traits_type::assign(*current, c);
    		return traits_type::not_eof( traits_type::eof() );
    	}
    
    	int_type pbackfail_noneof_impl( char_type, std::false_type )
    	{
    		return traits_type::eof();
    	}
    
    	int_type pbackfail_impl( std::true_type, int_type c )
    	{
    		if (first == current)
    			return traits_type::eof();
    
    		--current;
    
    		if (not traits_type::eq_int_type(c, traits_type::eof()))
    			return pbackfail_noneof_impl( traits_type::to_char_type(c),
    			                              std::integral_constant<bool,  std::is_convertible<char_type, typename std::iterator_traits<Iterator>::value_type>::value // Grober Indikator!
    			                                                       &&  !std::is_const<typename std::remove_reference<decltype(*current)>::type>::value>{} );
    
    		return traits_type::not_eof( traits_type::eof() );
    	}
    
    	int_type pbackfail_impl( std::false_type, int_type )
    	{
    		return traits_type::eof();
    	}
    
    	virtual int_type pbackfail( int_type c = traits_type::eof() ) override
    	{
    		return pbackfail_impl(std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<Iterator>::iterator_category>{}, c);
    	}
    
    	virtual std::streamsize showmanyc() override
    	{
    		return std::distance(current, last);
    	}
    
    public:
    
    	basic_iterator_streambuf( Iterator first, Iterator last ) :
    		first(first), current(first), last(last) {}
    };
    
    template <typename I>
    using iterator_streambuf = basic_iterator_streambuf<I, char>;
    
    #include <iostream>
    
    int main()
    {
    	std::string const str = "Hallo Welt!";
    	iterator_streambuf<std::string::const_iterator> buf(str.begin(), str.end());
    	std::istream stream(&buf);
    	std::string outstr;
    	stream >> outstr;
    	std::cout << outstr;
    }
    

    Werner kann das sicher vollständig und richtig machen.


Anmelden zum Antworten