2012-03-07 21 views
9

Powiel możliwe:
Can I declare variables of different types in the initialization of a for loop?C++ Inicjalizacja 2 różne iteratory w pętli for

chciałbym mieć do pętli w C++, który konstruuje 2 różne rodzaje wektora iterator w inicjalizacja.

Oto z grubsza to, co lubię:

std::vector<double> dubVec; 
std::vector<int> intVec; 
double result = 0; 

dubVec.push_back(3.14); 
intVec.push_back(1); 

typedef std::vector<int>::iterator intIter; 
typedef std::vector<double>::iterator dubIter; 

for (intIter i = intVec.begin(), dubIter j = dubVec.begin(); i != intVec.end(); ++i, ++j) 
{ 
    result += (*i) * (*j); 
} 

ktoś wie co jest standardem zrobić w tej sytuacji? Nie mogę po prostu użyć wektora podwójnego dla intVec, ponieważ szukam ogólnego rozwiązania. [to znaczy. Może mam jakąś funkcję f, który trwa int podwojenia, a następnie obliczyć f (* i) * (* j)]

+5

Proszę używać '++ i, ++ j' zamiast' && ', ponieważ to nie działa dla iteratorów. – Xeo

+2

Inkrementowanie iteratora bez sprawdzania go jest niebezpieczne. – Konrad

+0

zmieniono && na przecinek w pętli for. thx – Derek

Odpowiedz

24

można zadeklarować std::pair z first i second jako typów iterator:

for (std::pair<intIter, dubIter> i(intVec.begin(), dubVec.begin()); 
    i.first != intVec.end() /* && i.second != dubVec.end() */; 
    ++i.first, ++i.second) 
{ 
    result += (*i.first) * (*i.second); 
} 
+0

Jest to szczególnie sprytne rozwiązanie, które myślę. Niszczy także itratory na końcu, co było częścią mojego celu. Myślę, że początkowo pytałem, czy możliwe było zainicjowanie 2 różnych typów w pętli for (co jest niemożliwe). Ale to rozwiązanie jest naprawdę ładne i nieoczekiwane. – Derek

+0

Jak zauważył Alecs w komentarzu poniżej, ten pomysł generalizuje do struktur, jak widać tutaj: http://stackoverflow.com/questions/8644707/can-i-declare-variables-of-different-types-in-the- inicjalizacja pętli – Derek

+0

jak zrobić to krok dalej, jak masz N? z powrotem do struktury, czy jest coś lepszego do wykorzystania? – kdubs

3

Na przykład

intIter i = intVec.begin(); 
dubIter j = dubVec.begin(); 
for (; i != intVec.end(); ++i && ++j) 
{ 
    result += (*i) * (*j); 
} 

można zadeklarować kilka var. tylko tego samego typu w for. I czy na pewno z tą częścią

++i && ++j 

? Wierzę, że chcesz napisać tam

++i, ++j 

Więc oczywiście trzeba odczytać podstawowe informacje na temat pętli w C++

+0

Przepraszam, chciałem powiedzieć ++ i, ++ j. jednak szukałem rozwiązania, które również zniszczyło iteratory na końcu pętli for, więc nie są to zmienne globalne. – Derek

+0

@Derek, jeśli są one różnego typu, nie ma możliwości zrobienia tego w pętli for. W twoim przykładzie naprawdę nie potrzebujesz iteratorów, możesz po prostu użyć indeksów, ale przypuszczam, że pokazałeś nam bardzo uproszczony kawałek kodu – Alecs

+0

@Derek: Jeśli naprawdę potrzebujesz ograniczyć ich zakres, umieść deklaracje i pętlę w swoim własnym bloku. –

7

Nie można deklarować zmienne różnych typów wewnątrz for pętli.

Wystarczy zadeklarować je na zewnątrz:

intIter i = intVec.begin(); 
dubIter j = dubVec.begin(); 
for (; i != intVec.end(); ++i && ++j) 
{ 
} 
+4

co to jest '++ i && ++ j'? Użyj przecinka. – David

+0

@Do tego przyrostowego wyrażenia ma on w pytaniu, to jest to, czego używam w mojej odpowiedzi. –

1

Najłatwiej zrobić, kosztem poszerzenia zakresu iteratorów, byłoby po prostu podnosić je do zawierającym zakresie:

intIter i; 
dubIter j; 
for (i = intVec.begin(), j = dubVec.begin(); i != intVec.end(); ++i && ++j) 
{ 
    result += (*i) * (*j); 
} 
1

Zapoznaj się z zip iterator. Robi dokładnie to, co chcesz: równolegle iteruj przez dwie lub więcej sekwencji jednocześnie. Korzystanie z tym, że piszę to jako:

using namespace boost; 

for (auto i=make_zip_iterator(make_tuple(dubVec.begin(), intVec.begin())), 
      ie=make_zip_iterator(make_tuple(dubVec.end(), intVec.end())); 
      i!=ie; ++i) 
{ 
    // ... 
} 

Trzeba przyznać, że się trochę bardziej skomplikowane, jeśli nie mają wsparcia dla auto lub inny rodzaj wnioskowania w Twoim konkretnym przypadku, ale może być jeszcze całkiem ładny z typedef.

0
intIter i; 
dubIter j; 
for (i = intVec.begin(), j = dubVec.begin(); i != intVec.end() && j != dubIter.end(); ++i, ++j) 
{ 
    result += (*i) * (*j); 
} 
1

Nie kompiluj wszystkiego.

for(size_t i = 0; i < intVec.size(); ++i) 
{ 
    result += intVec[i] * dubVec[i]; 
} 
+0

Używanie iteratorów nie jest nadmierną komplikacją? – Konrad

+0

@Konrad: Jeden indeks jest prawdopodobnie prostszy niż dwa iteratory. Ale OP zażądał ogólnego rozwiązania, a to działa tylko w przypadku kontenerów z dostępem losowym. –

1

Wydaje potrzebujesz inner_product algorithm.

#include <vector> 
#include <functional> 
#include <numeric> 
#include <iostream> 

struct my_plus 
{ 
    double operator()(int i, double d) 
    { 
     return d + i; 
    } 
}; 

struct my_multiplies 
{ 
    double operator()(int i, double d) 
    { 
     return d * i; 
    } 
}; 

int main() 
{ 
    std::vector<double> dubVec; 
    std::vector<int> intVec; 
    double result = 0; 

    dubVec.push_back(3.14); 
    intVec.push_back(1); 

    result = std::inner_product(intVec.begin(), 
           intVec.end(), 
           dubVec.begin(), 
           0.0, 
           my_plus(), 
           my_multiplies()); 
    std::cout << result << std::endl; 
} 

użyłem własnych funktory, bo podejrzewam standardowe mnoży a także oczekiwać oba operandy być z podobnego typu, ale może się mylę.