2015-06-03 7 views
7

W przykładzie z vector<int> someVectoristringstream someStringStream i można to zrobić:Jak korzystać z operatora wyodrębniania (>>) z wektorem <bool>?

for (int i=0; i < someVector.size(); i++) { 
    someStringStream >> someVector[i]; 
} 

wiem, że vector<bool> jest skuteczne wdrażanie i operator[] zwraca obiekt odniesienia. Dla tego kodu powinienem używać indeksu zamiast iteratora, głównie dla czytelności. Obecnie używam to:

for (int i=0; i < someVector.size(); i++) { 
    bool temp; 
    someStringStream >> temp; 
    someVector[i] = temp; 
} 

Czy istnieje bardziej bezpośredni sposób realizacji tego?

Odpowiedz

0

Jeśli wszystko czego potrzebujesz, to ten sam interfejs dla bool i innych typów, łatwo jest zawijać rzeczy.

template <typename T> 
T read(std::istream& stream) 
{ 
    T value; 
    stream >> value; // TODO: guard against failure of extraction, e.g. throw an exception. 
    return value; 
} 

Jednak użycie tego bezpośrednio wymaga określenia typu.

for (int i=0; i < someIntVector.size(); i++) 
{ 
    someIntVector[i] = read<int>(someStringStream); 
} 

for (int i=0; i < someBoolVector.size(); i++) 
{ 
    someBoolVector[i] = read<bool>(someStringStream); 
} 

Jeśli ponowne że dla kilku różnych wektorów, tylko owinąć go ponownie:

template <typename T, typename A> 
void fillVectorFromStream(std::istream& stream, std::vector<T, A>& vector) 
{ 
    for (int i = 0; i < vector.size(); ++i) 
    { 
     vector[i] = read<T>(stream); 
    } 
} 

Stąd wykorzystanie staje się po prostu

fillVectorFromStream(streamOfBool, vectorOfBooleanValues); 
fillVectorFromStream(streamOfIntegers, vectorOfIntegers); 
+0

To nie jest bezpieczne. Jeśli operator >> zawiedzie, wówczas "wartość" nie zostanie zainicjalizowana. Albo stan strumienia powinien być jawnie sprawdzony, albo std :: ios_base :: failbit powinien być ORed do wyjątków stream(). –

+1

@ArneVogel Zostało to zmienione w C++ 11: jeśli wyodrębnianie nie powiedzie się, zero jest zapisywane do wartości (patrz http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt). Jednakże zgadzam się, że kontrola błędów jest konieczna w kodzie produkcyjnym. Mimo to jest tak wiele sposobów na zrobienie tego. Nie jest to kwestia wyboru, imho. – stefan

5

można użyć std::copy lub konstruktora std::vector zakresie IF chcesz wykorzystać cały strumień:

std::stringstream ss("1 0 1 0"); 
std::vector<bool> vec; 
std::copy(std::istream_iterator<bool>(ss), {}, std::back_inserter(vec)); 

LIVE DEMO

std::stringstream ss("1 0 1 0"); 
std::vector<bool> vec(std::istream_iterator<bool>(ss), {}); 

LIVE DEMO

Teraz patrząc na przykładach, że pisał i jeśli jesteś pewien, że twój std::vector s rozmiar jest właściwy można użyć std::generate jak na poniższym przykładzie:

std::stringstream ss("1 0 1 0"); 
std::vector<bool> vec(4); 
std::generate(std::begin(vec), std::end(vec), [&ss](){ bool val; ss >> val; return val;}); 

LIVE DEMO

Powiązane problemy