Zadanie na płaszczyżnie

0

Witam, akurat staram się zrobić pewne zadanie, ale jako że z niektórymi rzeczami mam problem to prosiłbym o wyjaśnienie jak to zrobić. Wymienię problemy które mam z zadaniem.
Po pierwsze jak zdefiniować strukturę Rect tak by robiła to czego chcą w zadaniu, zadeklarowałem punkty w strukturze ale nie wiem jak to dalej zrobić. Dalej mam problem z vectorem, zadeklarowałem go i starałem się potem dodać do niego jakieś polecenia w środku ale że w argumentach funkcji process znajduje się argument function to nie chce mi działać. Function próbowałem utworzyć jako osobną klasę, ale to i tak wyskakuje błąd. Tutaj niżej jest treść zadania.

Zdefiniuj strukturę Point z polami x i y (typu double) odpowiadającymi współrzędnym na płaszczyźnie kartezjańskiej. Zdefiniuj też strukturę Rect opisującą prostokąty na płaszczyźnie kartezjańskiej z bokami równoległymi do osi, polami tej struktury są dwa punkty będące lewym-górnym i prawym-dolnym wierzchołkiem prostokąta. Napisz funkcję:

std::vector<double> process(const Rect* rects, size_t sz, std::function<double(Rect)> f);

która pobiera tablicę prostokątów i jej wymiar oraz funkcję typu Rect→double, a zwraca wektor wyników przekształcenia kolejnych prostokątów z tablicy dostarczoną funkcją. Napisz program testujący napisaną funkcję; jako trzeciego argumentu wywołania użyj zarówno lambd jak i wskaźników do własnych funkcji. Jako funkcji transformującej możesz, na przykład, użyć funkcji obliczającej pole prostokąta albo długość jego przekątnej. Wtedy dla prostokątów:

[(0,4),(4,1)], [(−6,3),(6,−2)], [(−7,4),(8,−4)],

wynik powinien być 12, 60, 120 (pola) i 5, 13, 17 (długości przekątnych).

Tutaj jest mój kod:

#include <iostream>
#include <vector>

using namespace std;

struct Point
{
    double pointx;
    double pointy;
} x, y;

struct Rect
{
    double pointx;
    double pointy;
    double pointz;
} x, y, z;

void function();

vector<double> process(const Rect* rects, size_t sz, function<double(Rect)> f);

int main()
{
   
}

void function()
{

}

vector<double> process(const Rect* rects, size_t sz, function<double(Rect)> f)
{
    return vector<double>();
}

0

Rect ma się składać z dwóch punktów chyba

#include <iostream>
#include <cmath>
#include <functional>


struct Point {
	double x;
	double y;
};
struct Rect {
	Point a;
	Point b;
};
double area(Rect p) {
	return abs(p.b.x  - p.a.x) * abs(p.b.y - p.a.y);
}
int main(){
	std::function<double(Rect)> f = area;
	return 0;
}

Musisz stworzyć tablice prostokątów i przekazać ją do funkcji, wszystko Masz opisane.

0

Jak na razie udało mi się znależć podobne zadanie i na jego podstawie napisałem część tego co trzeba, ale muszę wymyśleć jak je pozmieniać by pasowało do wymagań tego pierwszego, jeżeli możesz napisać coś pomocnego byłbym wdzięczny.

To mój obecny kod:

#include <iostream>
#include <vector>

using namespace std;

struct Point
{
    double x, y;
};

struct Rect
{
    Point A, B, C;
};

void info(const Point*);               
void info(const Rect*);             
void rot(Point*, double);               
void rot(Rect*, double);     

//vector<double> process(const Rect* rects, size_t sz, function<double(Rect)> f);

int main()
{
    Point A;
    A.x = -1;
    A.y = 2;

	Point B = { -1, 1 };
	
    Point C = { 2 };
    C.y = -1;
	
    Rect T = { A, B };
    T.C = C;
    
	 cout << "Wyjsciowe punkty: ";
	 info(&A); info(&B); info(&C);
	 cout << "\nTrojkat: ";
	 info(&T);
     cout << endl;
	
	 rot(&A, 90); rot(&B, 90); rot(&C, 90);                
	 cout << "A, B, C po obrocie o 90 stopni:\n";
	 info(&A); info(&B); info(&C);
	 cout << endl;
	
	 rot(&T, 90); rot(&T, 90);                            
	 cout << "T po obrocie dwa razy o 90 stopni:\n";
	 info(&T);

	      rot(&T, 180);                                       
    cout << "T po obrocie o nastepne 180 stopni:\n";
     info(&T);
}

void info(const Point* pP) {
      cout << "(" << pP->x << ", " << pP->y << ") ";

}

  void info(const Rect* pT) {
	  cout << "A="; info(&pT->A);                        
	  cout << "B="; info(&pT->B);
	  cout << "C="; info(&pT->C);
	  cout << endl;
	
}

  void rot(Point* pP, double phi) {
    static double conver = atan(1.) / 45;
    phi = phi * conver; // stopnie -> radiany
	
    double c = pP->x;
    pP->x = pP->x * cos(phi) - pP->y * sin(phi);
    pP->y = c * sin(phi) + pP->y * cos(phi);
}

  void rot(Rect* pT, double phi) {
	 rot(&pT->A, phi);                                 
     rot(&pT->B, phi);
     rot(&pT->C, phi);
}

/*vector<double> process(const Rect* rects, size_t sz, function<double(Rect)> f)
{
    return vector<double>();
}
*/

1

Właśnie, gdzieś Znalazłeś i Kopiujesz bezmyślnie, prostokąt ma się składać z dwóch punktów: lewy dolny róg i prawy górny, a nie trzech. Napisałęm Ci prawie wszystko, teraz tylko Musisz stworzyć tablicę prostokątół w pętli i wysłać do funkcji process, gdzie w pętli "Zmapujesz" funkcję na tablicę, dodając wybiki do wektora i go Zwrócisz [ten wektor].

0

Czy mógłby ktoś spojrzeć na ten kod i napisać jak to powinno wyglądać. Próbuję zrobić to zadanie ale jak na razie mam kilka problemów. Nie wiem jak dokończyć funkcję process tak by zapisywać w pętli wyniki f(rects) i w jaki sposób wywołać w mainie funkcje process tak by raz było z funkcją area a drugi raz z lambdą. Starałem się stworzyć vector który posiadał by te wymagane prostokąty w zadaniu ale nie mogę użyć opcji push_back by dodać wartości.
Tu kod który zmieniłem:

int main() {
	function<double(Rect)> f = area;

	int c = -6;
	int v = -2;
	int b = -7;
	int n = -4;

	vector < Rect > prost;
	prost.push_back((0, 4), (4, 1));
	prost.push_back((c, 3), (6, v));
	prost.push_back((b, 4), (8, n));

	for (int i = 0; i < 3; ++i)
	{
		process(area());
		printf()
	}

}


vector<double> process(const Rect* rects, size_t sz, function<double(Rect)> f)
{
	vector<double> prost;
	for (auto i = 0; i < sz; ++i)
	{
	 prost[i] = f(rects(i))
	}
	return prost;
		
}
0

(0, 4) to jest wyrażenie równoważne 4. Jak chcesz utworzyć obiekt to użyj nazwy typu. Np. Foo{0, 4}

0

OK. poprawiłem to, ale to i tak nie eliminuje błędu z użyciem push_back.

0

Jaki jest obecny kod?

0

to cały kod

#include <iostream>
#include <cmath>
#include <functional>
#include <vector>

using namespace std;

struct Point {
	double x;
	double y;
};

struct Rect {
	Point a;
	Point b;
};

double area(Rect p) {
	return abs(p.b.x - p.a.x) * abs(p.b.y - p.a.y);
}

int main() {
	function<double(Rect)> f = area;

	int c = -6;
	int v = -2;
	int b = -7;
	int n = -4;

	vector < Rect > prost;
	prost.push_back({ 0, 4 }, { 4, 1 });
	prost.push_back({ c, 3 }, { 6, v });
	prost.push_back({ b, 4 }, { 8, n });

	for (int i = 0; i < 3; ++i)
	{
		process(area());
		printf()
	}

}


vector<double> process(const Rect* rects, size_t sz, function<double(Rect)> f)
{
	vector<double> prost;
	for (auto i = 0; i < sz; ++i)
	{
	 prost[i] = f(rects(i))
	}
	return prost;
		
}


0

push_back przyjmuje jeden argument.

0

Mi chodzi o stworzenie vectora prostokątów z danymi jak w poleceniu zadania, żeby ich potem użyć w funkcji process. To jak mam to inaczej zrobić?

0

prost.push_back({{ 0, 4 }, { 4, 1 }});

0

Dzięki, teraz działa, a możesz jeszcze napisać jak poprawić funkcję process i ją wywołać w mainie. Próbuję ją wywołać na funkcji area i lambdzie.

0

Generalnie to są podstawy programowania: typy i liczba argumentów funkcji musi się zgadzać z jej definicją.

1

Jakoś tak by to wyglądało, zgodnie z warunkami zadania, stworzona jakaś kulawa :) tablica prostokątów:

#include <iostream>
#include <algorithm>
#include <vector>
#include <stdio.h>
#include <cmath>
#include <functional>

using namespace std;
struct Point {
	double x;
	double y;
};

struct Rect {
	Point a;
	Point b;
};
double area(Rect p) {
	return abs(p.b.x  - p.a.x) * abs(p.b.y - p.a.y);
}

std::vector<double> process(const Rect *rects, size_t sz, std::function<double(Rect)> f) {
	std::vector<double> vv;
	for (size_t i = 0; i < sz; ++i) {
		vv.push_back(f(rects[i]));
	}
	return vv;
}

int main(){
	std::function<double(Rect)> f = area;
	
	
	Rect arrayRects [2];
	for (int i = 0; i < 2; ++i) {
			arrayRects[i] = {{0.0 + i, 0.0 + i}, {1.1 + i, 1.1 + i}};
	}
	
	std::vector<double> v = process(arrayRects, 2, f);
	
	for (auto e: v)
		cout << e <<" ";
	
	return 0;
}
0

Rozumiem, że funkcje wymagają odpowiednich argumentów do działania, nie wiem tylko jak przesłać na przykład vector Rect z 2 wartościami z których każda ma kolejne dwie. Taki trójkąt na płaszczyżnie, żeby to działało, lub jak to wywołać raz na innej funkcji a raz na lambdzie. Ja przeczytałem w opisie funkcji czego wymaga, ale przy próbie wpisywania argumentów na różne spsoby wyrzuca mi błąd.

0

Starałem sie dokończyć to zadanie i wywołać funkcję z odpowiednimi argumentami ale mam problem, mogę wywołać te wszystkie wartości na tym arrayrects i to wychodzi dobrze, ale w trzecim argumencie wywołania miałem użyć funkcji z lambdą i wskaźnikiem, no i tutaj mam błąd związany z konwersją elementu który nie wiem jak poprawić oraz powinienem dodać tu wskażnik, jak należy to poprawnie napisać? Poza tym w zadaniu było że mam użyć lambdy i wskaźników jako 3 argumentu wywołania, czy to będzie dobrze jeśli 2 razy wywołam funkcję process tylko z innymi argumentami?

Tutaj jest to co zmieniłem:

int main() {
	function<double(Rect)> f = area;

	Rect arrayRects[3]; 
		arrayRects[0] = { {0.0, 4.0 }, {4.0, 1.0 } };
		arrayRects[1] = { {-6.0, 3.0 }, {6.0, -2.0 } };
		arrayRects[2] = { {-7.0, 4.0}, {8.0, -4.0 } };
	
		vector<double> v = process(arrayRects, 2, f);

	for (auto e : v)
		cout << e << " ";
	
	vector<double> z = process(arrayRects, 1, [arrayRects]() {(abs(arrayRects[2].b.x) - abs(arrayRects[2].a.x)) - (abs(arrayRects[2].b.y) - abs(arrayRects[2].a.y));});

	for (auto r : z)
	{
		cout << r;
	}

	return 0;
}


Jeszcze nad tym siedzę ale z tego co zauważyłem, to wywoływałem lambdę w złym miejscu. Teraz to zmieniłem i tak wygląda, ale nie wiem jak pozbyć się błędu z konwersją i czy to działa. Wyświetlanie nie jest chyba jeszcze w pełni dobrze. Nie rozumiem czy mam od nowa pisać zasadę działania funkcji area czy tylko ją jakoś wywołać w lambdzie, i w jaki sposób mam użyć tam wskażnika, do czego ma się on odnosić?

1

Błąd związany jest z niewłaściwą sygnaturą lambdy - powinna zwracać double i posiadać parametr wejściowy Rect

[]( Rect r ) { return ( abs(r.b.x - r.a.x) - abs(r.b.y - r.a.y) ); }

Nie łatwiej będzie jednak zaimplementować funkcję obliczania pola wewnątrz struktury Rect ?

#include <iostream>
#include <vector>

using namespace std;

struct Point
{
    double x {0};
    double y {0};
};

struct Rect
{
    Point a;
    Point b;
    double area() const { return abs(b.x  - a.x) * abs(b.y - a.y); }
};

int main()
{
    vector<Rect> arrayRects;
    arrayRects.push_back( { {0.0, 4.0  }, {4.0, 1.0  } } );
    arrayRects.push_back( { {-6.0, 3.0 }, {6.0, -2.0 } } );
    arrayRects.push_back( { {-7.0, 4.0 }, {8.0, -4.0 } } );

    for( auto rect : arrayRects ) cout << rect.area() <<" ";

    return 0;
}
0

Dzięki za odpowiedż znajomy mi już to wytłumaczył, ale ten sposób też wygląda na dobry.

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