Fill vector with input from cin without loop



  • Hallo zusammen,

    jeder kennt bestimmt die typische input loop:

    while (cin >> foo)
        bar.push_back(foo);
    

    ich habe aber mal irgendwo gesehen, dass man das alles schneller machen kann, irgendwas mit Iteratoren, wenn ich mich recht erinnere.

    Würde mich freuen, wenn jemand das nochmal schnell mir zeigen könnte. Finde es nämlich schöner das Ganze in 1 statt 3-4 zeilen zu machen

    LG



  • my_vector.insert(end(myvector), istream_iterator<bla>(cin), istream_iterator<bla>());
    


  • // implying std::vector<Foo> vec; ...
    std::copy(std::istream_iterator<Foo>(std::cin), std::istream_iterator<Foo>(), std::back_inserter(vec));
    


  • ach ja, vergiss meinen Code, die Variante mit std::back_inserter ist natürlich die richtige...



  • dot schrieb:

    ach ja, vergiss meinen Code, die Variante mit std::back_inserter ist natürlich die richtige...

    Ich find deine aber eleganter. Und die ist kürzer.



  • Nathan schrieb:

    dot schrieb:

    ach ja, vergiss meinen Code, die Variante mit std::back_inserter ist natürlich die richtige...

    Ich find deine aber eleganter. Und die ist kürzer.

    Hach, ich bin noch etwas...unausgeschlafen 🤡 ...dachte für einen Moment, dass bei mir der vector sich doch nicht passend vergrößern würde und man darum den back_inserter benötigt, tut er ja aber eh...



  • Nathan schrieb:

    dot schrieb:

    ach ja, vergiss meinen Code, die Variante mit std::back_inserter ist natürlich die richtige...

    Ich find deine aber eleganter. Und die ist kürzer.

    vec.insert(end(vec), istream_iterator<Foo>(cin), istream_iterator<Foo>());
    copy(istream_iterator<Foo>(cin), istream_iterator<Foo>(), back_inserter(vec));
    
    std::copy(std::istream_iterator<Foo>(std::cin), std::istream_iterator<Foo>(), std::back_inserter(vec));
    vec.insert(std::end(vec), std::istream_iterator<Foo>(std::cin), std::istream_iterator<Foo>());
    

    Nur geringfügig, und insert erweckt den Eindruck, dass man irgendwo innerhalb des Vector einfügen will, dementsprechend ist copy da was aussagekräftiger. Aber jeder wie er mag 🙂



  • Supi beide Lösungen funktionieren, danke.

    Gibt es einen einfachen Trick, damit es ähnlich wie hier nur das Drücken der Enter taste bedarf, damit die Eingabe aufhört und nicht einen nicht-int, z.B. ';'.

    string str;
    getline(cin, str);
    stringstream stream(str);
    int temp;
    while (stream >> temp)
        vec.push_back(temp);
    

    Wenn nicht, ist es auch kein großes Thema, ist trotzdem einfacher meiner Meinung nach.


  • Mod

    Warum hat noch keiner die deutlich kürzere Variante gezeigt?

    vec.insert(vec.end(), istream_iterator<Foo>(cin), {});
    


  • Arcoth schrieb:

    Warum hat noch keiner die deutlich kürzere Variante gezeigt?

    vec.insert(vec.end(), istream_iterator<Foo>(cin), {});
    

    oder noch kürzer

    vec.insert(end(vec), istream_iterator<bla>(cin), {});
    

    :p


  • Mod

    Gibt es einen einfachen Trick, damit es ähnlich wie hier nur das Drücken der Enter taste bedarf, damit die Eingabe aufhört und nicht einen nicht-int, z.B. ';'.

    Es gibt einen sexy Trick.

    class newline_sep : public std::ctype<char>
    {
    	mask const* create_table()
    	{
    		static mask table[table_size];
    		if (table[std::size_t(' ')] == 0)
    		{
    			std::copy_n( classic_table(), table_size, table );
    			table[std::size_t('\n')] &= ~space;
    		}
    
    		return table;
    	}
    
    public:
    
    	newline_sep(std::size_t refs = 0) : ctype(create_table(), false, refs) {}
    };
    

    Dann in cin imbuen:

    cin.imbue( locale(cin.getloc(), new newline_sep) );
    

    Und voila:

    vector<int> v( istream_iterator<int>(cin), {} );
    
    	for (auto i : v)
    		std::cout << i << ", ";
    

    Sollte bei Zeilengesteuerten Konsolen beim drücken der Enter-Taste abbrechen.

    Ich kann mich im Übrigen erinnern diese MEthode in irgendeinem cppreference Beispiel gesehen zu haben. Kann das jemand rauskramen?
    Edit: Ich bin wohl blind, das ist ja das Beispiel von ctype<char> selbst. Hab' den Code angepasst.



  • wow... fragt sich, ob der comfort auch gut ist, wenn ich den Trick absolut nicht verstehe, oder ob es dann doch sinnvoller ist, einfach ein ';' etc. einzugeben 😃



  • HarteWare schrieb:

    wow... fragt sich, ob der comfort auch gut ist, wenn ich den Trick absolut nicht verstehe, oder ob es dann doch sinnvoller ist, einfach ein ';' etc. einzugeben 😃

    Simulier EOF: Strg+Z (Win), Strg+D (Linux)
    Ist "sauberer" als Müll einzugeben und funktioniert auch bei Strings.



  • Arcoth schrieb:

    Warum hat noch keiner die deutlich kürzere Variante gezeigt?

    vec.insert(vec.end(), istream_iterator<Foo>(cin), {});
    

    Weil Visual Studio das noch nicht ausreichend gut unterstützt als dass ich es nutze und mich daran gewöhnt hab 😃



  • Gibts es überhaupt nen guten Grund nicht einfach die erste Variante zu nehmen (mit move)? 🤡



  • cooky451 schrieb:

    Gibts es überhaupt nen guten Grund nicht einfach die erste Variante zu nehmen (mit move)? 🤡

    Das wäre zu kurz, nicht ausreichend kryptisch genug und man müsste <iterator> nicht includen.


Log in to reply