Witam,
dostałem takie zadanie, w którym mam m. in. stworzyć funkcję przyjmującą jako argumenty tablicę obiektów i wyszukiwaną wartość. Funkcja powinna zwracać do miejsca wywołania obiekt lub obiekty. Gdy obiekt jest jeden, to wiem, jak to zrobić, ale proszę o podpowiedź, jak zwrócić wiele obiektów?
zwróć tablicę tych obiektów. Daj jeszcze próbkę kodu lub polecenie, bo nie za bardzo wiadomo o co chodzi ze zwracaniem wielu obiektów.
Środowisko to Visual Studio 2019, a język C++.
Funkcja szukająca:
Klasa znajdz(Klasa tabc[], int wyszukane) {
for (int i = 0; i <= 8; i++)
{
if (tabc[i].wartosc == wyszukane)
{
return tabc[i];
}
}
}
Pytając o środowisko bardziej myślałem o jakiejś bibliotece np GUI, posiadającej hierarchię klas od jakiegoś "korzenia" XxxxObject (tak mają Qt albo MFC - co nie oznacza pochwały MFC). Wtedy jest możliwość zrobienia eleganckiego API, bo i tablica (oczywiście ta z frameworka), lista i pojedynczy obiekt jakiejś klasy dziedziczą z głównego XxxxxObjectu (jak jest natywnie w Javie i C#).
Ponieważ C++ nie ma samo w sobie koncepcji takiej klasy "korzenia", zostaje zwracanie kontenera, być może z jednym elementem.
Zamiast zwykłej tablicy, która zmusza do podania licznika, znacznie lepiej jest zwracać jakiś std::vector, std::list czy co sobie wybierzesz.
BTW w tym co zamieszczasz, użycie tablicy[] i szukanie do ósemki jest chore, też użyj kontenera.
Sygnatura funkcji może wyglądać np tak:
std::vector<Klasa> znajdz(const std::vector<Klasa>& tabc, int wyszukane);
W funkcji zbierasz wszystkie obiekty z tabc
spełniające warunek do lokalnego wektora i go na koniec zwracasz.
Ok, a jeszcze, jak mogę po zwróceniu wektora wyświetlić zawartość obiektów w nim zawartych(wywołać metodę "przedstaw się" na każdym)? Mam pętle for, tylko nie wiem, jak odwołać się do zwróconego wektora, czy muszę go zapisać do nowego w funkcji main?
W funkcji znajdz zwracam wektor, a w main mam taką pętlę:
for (int i = 0; i <= znajdz(tabc,wartosc).size(); i++) {. (1)
znajdz(tabc, wartosc)[i].przedstaw_sie;
}
W wektorze zapisane są wyniki wyszukiwania( obiekty typu Klasa). Nie wiem, jak te obiekty wyświetlić. Kompilator zwraca mi błędy :
po lewej .size() musi być struct/union.
wyrażenie(1) musi mieć typ klasy, (znajdz jest podkreślone)
A funkcja znajdz tak wyglada teraz:
std::vector<Klasa> znajdz(const std::vector<Klasa>& tabc, int wyszukane){
vector <Klasa> zwracany;
for (int i = 0; i <= 11; i++)
{
if (tabc[i].wartosc1 == wyszukane)
{
zwracany.push_back(tabc[i]);
}
}
return zwracany;
}
Sugerował bym użycie iteratora
for(std::vector<Klasa>::iterator it = v.begin(); it != v.end(); ++it) {
it->przedstaw_się()
}
EDIT za podaną niżej pętlą foreach (bo taka de facto jest) podpisuję się oboma ręcyma
BTW "klasyczny" środkowy warunek pętli u ciebie jest
a) ciężki (kosztowny)
b) błedogenny jeśli założymy, że dane jakoś żyją.
Generalnie mało satysfakcjonująca jest ta pętla.
Nie używaj magicznych liczb ( i <= 11
). Gdyby wektor miał tylko trzy elementy, to miałbyś UB (Undefined Behavior).
Można to zrobić w taki sposób ( C++17 ):
using namespace std;
class Foo
{
public:
int value {0};
void introduce() const { cout << "My value is : "+to_string(value) << "\n"; }
};
vector<Foo> find( const vector<Foo>& data , int value )
{
vector<Foo> result;
for( const auto& element : data ) if( element.value == value ) result.push_back(element);
return result;
}
int main()
{
for( const auto& element : find( {{2},{6},{5},{15},{5},{4}} , 5 ) ) element.introduce();
}
Ale pomyśl jednak o scaleniu funkcji wyszukującej find
z wywołaniem metody klasowej introduce
, tak aby zaoszczędzić sobie tworzenia niepotrzebnych bytów:
void find_and_introduce( const vector<Foo>& data , int value )
{
for( const auto& element : data ) { if( element.value == value ) element.introduce(); }
}
int main()
{
find_and_introduce( {{2},{6},{5},{15},{5},{4}} , 5 ) ;
}
Może byłby ktoś chętny odpłatnie(na privie) przejrzeć to co napisałem, poprawić?
Próbuje znaleźć błąd w tej funkcji, ale nie mogę. Przy konwertowaniu tablicy na vector, gdy próbuję wyświetlić zawartość wektora, to pokazuje 0. A wcześniej przy tablicy normalnie pokazuje. Czyli coś mam źle z konwersją tablicy?
vector<Klasa> znajdz( Klasa przekazana[], int wyszukane) {
vector <Klasa> zwracany;
std::vector<Klasa> konwert(przekazana, przekazana + sizeof przekazana / sizeof przekazana[0]);
cout << konwert.size();
for (int i = 0; i < konwert.size(); i++)
{
if (konwert[i].wartosc1 == wyszukane)
{
zwracany.push_back(konwert[i]);
}
}
return zwracany;
}
Koner0 napisał(a):
Próbuje znaleźć błąd w tej funkcji, ale nie mogę. Przy konwertowaniu tablicy na vector, gdy próbuję wyświetlić zawartość wektora, to pokazuje 0. A wcześniej przy tablicy normalnie pokazuje. Czyli coś mam źle z konwersją tablicy?
vector<Klasa> znajdz( Klasa przekazana[], int wyszukane) {
...
std::vector<Klasa> konwert(przekazana, przekazana + sizeof przekazana / sizeof przekazana[0]);
Dlaczego nie korzystasz ze wskazówek, np gotowego nagłówka funkcji od @stryku . Każdy kiedyś był początkujący, ale potrzebujesz rozsądku, a nie strzelania na oślep (pewnie jakimiś kawałkami z googla)
Wyrażenie z sizeof jest błędne, sizeof(przekazana) jest 4 lub 8 (rozmiar wskaźnika, taka uroda C). Twój nagłówek funkcji z tablicą jest zupełnie nieużyteczny (brak wiedzy o rozmiarze tablicy)
Rzuć w cholerę myślenie w stylu C ( tu jest C++) - a zwłaszcza błędne
Próbowałem, jestem naprawdę początkujący :) Muszę ten program oddać dziś do północy, mocno zmęczony po prostu już jestem do tego. Powiedzielibyście, jak mogę tę tablicę przekonwertować na wektor obiektów?
Czyli nie da się tego przekonwertować ? Wcześniej, gdy miałem tę funkcję konwertującą w main to działało, ale spojrzałem na warunki zadania i musiałem tablice do funkcji przesłać, więc zmieniłem i teraz próbuję zmienić tę tablicę na wektor, żeby później go przeszukać. Da się ten kod jakoś poprawić ? :)
Uff, dzięki, uratowaliście mnie. Program działa, dzięki wszystkim za pomoc. :)