Vector i funktor + pętla while

0

Natknąłem się na głupi błąd i nie wiem za bardzo jak go rozwiązać -> może i trywialny ale poproszę o dokładne wytłumaczenie jeżeli ktoś mógłby mi pomóc :)

I z góry zaznaczam, tak można to napisać za pomocą lambdy, ale przykład musi wykorzystywać funktory. Koniec kropka...

Mamy więc vector z liczbami i musimy wskazać które z nich są parzyste.

#include <iostream> 
#include <vector> 
#include <algorithm> 

bool czyParzysta(int i) 
{
   return i%2==0; 
} 


int main() 
{
   int tab[10]={1,2,3,4,5,6,7,8,9,10}; 
   std::vector<int> vs(tab, tab + sizeof(tab)/sizeof(tab[0])); 

   std::vector<int>::iterator it = find_if(vs.begin(), vs.end(), czyParzysta); 

  // pętla while i tu chyba jest jakiś błąd, wykonuje się do momentu w którym nic w pętli nie będzie i iteruje iterator it 

   while(vs.empty()==false) 
   {
      std::cout << *it << " "; 
      it++; 
    } 
  
   return 0; 
}

 

Jakieś wytłumaczenie błędu logiczne mile widziane :)

Dzięki z góry

1
#include <iostream> 
#include <vector> 
#include <algorithm> 
 
bool czyParzysta(int i) 
{
   return i%2==0; 
} 
 
 
int main() 
{
   int tab[10]={1,2,3,4,5,6,7,8,9,10}; 
   std::vector<int> vs(tab, tab + sizeof(tab)/sizeof(tab[0])); 
 
   std::vector<int>::iterator it = find_if(vs.begin(), vs.end(), czyParzysta); //to Ci znajdzie pierwszą parzystą liczbę. Czyli 2. I na nią będzie wskazywał iterator. Potem jak w pętli while iterujesz to będzie iterować też po liczbach nieparzystych, które są za 2.
 
  // pętla while i tu chyba jest jakiś błąd, wykonuje się do momentu w którym nic w pętli nie będzie i iteruje iterator it 
 
   while(vs.empty()==false) // dla tego kodu ta pętla będzie się wykonywać w nieskończoność. W sumie, aż Ci wywali program.
   {
      std::cout << *it << " "; 
      it++; //używaj ++it tam gdzie możesz
    } 
 
   return 0; 
} 
ond3 napisał(a):

Mamy więc vector z liczbami i musimy wskazać które z nich są parzyste.

Zamiast find_if mozesz użyć copy_if do jakiegoś innego wektora.
Jeżeli chcesz koniecznie find_if to mniej więcej coś takiego

 #include <iostream> 
#include <vector> 
#include <algorithm> 
 
bool czyParzysta(int i) 
{
   return i%2==0; 
} 
 
 
int main() 
{
   int tab[10]={1,2,3,4,5,6,7,8,9,10}; 
   std::vector<int> vs(tab, tab + sizeof(tab)/sizeof(tab[0])); 
 
   std::vector<int>::iterator it = find_if(vs.begin(), vs.end(), czyParzysta); 
 
  // pętla while i tu chyba jest jakiś błąd, wykonuje się do momentu w którym nic w pętli nie będzie i iteruje iterator it 
 
   while(it != vs.end()) 
   {
      std::cout << *it << " "; 
      it = find_if(++it, vs.end(), czyParzysta);
    } 
 
   return 0; 
}
2

Brakujące elementy to:

  • ostream_iterator: przekazuje dane do strumienia wyjściowego
  • copy_if: dostępne od C++11

Dodatkowo - algorytmy C++ można stosować bezpośrednio na tablicach - dzięki temu unika się kopiowania.
Chociaż same tablice są mniej wygodne / bezpieczne od struktur STL (lepiej używać std::array lub std::vector).

Przykład:

#include <iostream>
#include <algorithm>
#include <iterator>

using namespace std;

// dostepne od C++11 w std::
template<typename InputIterator,
	typename OutputIterator,
	typename Predicate>
OutputIterator copy_if(InputIterator begin,
		InputIterator end,
		OutputIterator destBegin,
		Predicate p)
{
	while (begin != end) {
		if (p(*begin)) *destBegin++ = *begin;
		++begin;
	}
	return destBegin;
}

bool czyParzysta(int i) 
{
   return i%2==0; 
} 

int main() {
	int tab[10]={1,2,3,4,5,6,7,8,9,10}; 

        copy_if(tab, tab + sizeof(tab)/sizeof(tab[0]),
           ostream_iterator<int>(cout, "\n"),
           czyParzysta);    
        
	return 0;
}

http://ideone.com/jo9GIu

2
ond3 napisał(a):

I z góry zaznaczam, tak można to napisać za pomocą lambdy, ale przykład musi wykorzystywać funktory. Koniec kropka...

Niestety ale twój przykład nie korzysta z funktora, tylko zwykłej funkcji. Funktor do klasa (lub struktura), która zachowuje się jak zwykła funkcja. W tym celu taka klasa definiuje operator().

0

Funktorowo "pełną gębą" :-)

#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
#include <functional>

int main() {
	std::array<int, 5> arr {0, 1, 2, 3, 4};
	auto predicate = std::bind(std::equal_to<int>(), 0, 
		std::bind(std::modulus<int>(), std::placeholders::_1, 2)
	);
	std::copy_if(
		arr.cbegin(),
		arr.cend(),
		std::ostream_iterator<int>(std::cout, "\n"),
		predicate
	);
	return 0;
}
2

@n0name_l
tak dla jaj: wersja z Boost.Phoenix

#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
#include <boost/phoenix.hpp>

int main() {
    using boost::phoenix::arg_names::arg1;

    std::tr1::array<int, 5> arr = {0, 1, 2, 3, 4};    // tr1 dla kompatybilności z VS2010

    std::copy_if(
        arr.cbegin(),
        arr.cend(),
        std::ostream_iterator<int>(std::cout, "\n"),
        arg1 % 2 == 0
    );
    return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1