Včera jsem s kamarádem řešil, zda a jak lze v C++ načíst celý obsah vstupu do std::string
v jediném příkazu. Pokud by to někoho zajímalo, tak odpověď dává následující krátký příspěvek.
Řešení
Ano, je to možné, a to následovně:
#include <iostream> #include <iterator> #include <string> using namespace std; int main() { string s((istreambuf_iterator<char>(cin)), istreambuf_iterator<char>()); }
Je použit dvouparametrový konstruktor string(input_iterator start, input_iterator end)
, kde start
je iterátor ukazující na začátek vstupu a end
je iterátor ukazující těsně za konec vstupu (já vím, zní to zajímavě, že u vstupu, u kterého nevíte, jak bude dlouhý, vytváříte iterátor ukazující za jeho konec :)). Jsou použity iterátory istreambuf_iterator<char>
, které postupují znak po znaku, a to nezávisle na jeho hodnotě (viz dále). Jelikož chceme číst ze vstupu, tak prvnímu iterátoru předáme standardní proud cin
. Volání istreambuf_iterator<char>()
nám vytvoří onen iterátor ukazující znak za konec vstupu.
Na co si dát pozor
Je třeba si dát pozor na dvě věci. Za prvé, nelze použít iterátor istream_iterator
, protože ten by způsobil, že by došlo k zahození všech bílých znaků ze vstupu (což ve většině případů nechcete).
string s((istream_iterator<char>(cin)), istream_iterator<char>()); // Zahodí bílé znaky na vstupu
Za druhé, zdánlivě nadbytečné závorky jsou opravdu nutné, jinak bychom místo objektu typu string
deklarovali funkci (zájemce o bližší vysvětlení odkazuji zde). Schválně si můžete zkusit přeložit následující kód:
string s(istreambuf_iterator<char>(cin), istreambuf_iterator<char>()); // Deklarace funkce!
Pokud bychom nepoužili direktivu/deklaraci using
a kvalifikovali bychom istreambuf_iterator
jmenným prostorem std::
explicitně, problém by nenastal (jména formálních parametrů funkcí nemohou mít v názvu dvojtečky).