selveee Temat założony przez niniejszego użytkownika |
[C++] Dostęp do prywatnego wektora z innej klasy - program bazujący na UML » 2017-10-31 20:59:11 Witam złote rączki, piszę z męczącym mnie od kilku dni problemem, który już prawie porzuciłem ( a muszę go rozwiązać i ukończyć cały projekt do niedzieli włącznie ): otrzymałem od prowadzącego wytyczne na temat kolejnego z projektów, wytyczne to schemat UML programu: Link do zdjęcia UMLLink do skanu powyższegoWszystko pięknie ładnie, napisałem program, podzieliłem go wstępnie na oddzielne pliki .h (dalszy wywód pod zawartością ostatniego pliku): Plik z klasą Sygnal: #ifndef _Sygnal_h_ #define _Sygnal_h_ #include <iostream> #include <vector> #include "Probka.h" using namespace std; class Sygnal { private: vector < Probka > probki; public: Sygnal() { } void dodajProbke( const Probka & _p ) { probki.push_back( _p ); } int iloscProbek() { return probki.size(); } Probka & operator []( int i ); friend ostream & operator <<( std::ostream & aStream, const Sygnal & aSygnal ); }; #endif
Plik z klasą Probka: #ifndef _Probka_h_ #define _Probka_h_ using namespace std; class Probka { public: double t; double x; Probka(); Probka( double _t, double _x ) { t = _t; x = _x; } friend ostream & operator <<( ostream & aStream, const Probka & aProbka ); }; #endif
Plik z klasą AnalizatorSygnalu: #ifndef _AnalizatorSygnalu_h_ #define _AnalizatorSygnalu_h_ #include "Sygnal.h" using namespace std;
class AnalizatorSygnalu { public: AnalizatorSygnalu() { } double dlugosc( const Sygnal & _sygnal ) { double _min = _sygnal.probki[ 0 ].x; double _max = _sygnal.probki[ 0 ].x; for( int i = 0; i < _sygnal.probki.size(); i++ ) { if( _sygnal.probki[ i ].x < _min ) _min = _sygnal.probki[ i ].x; if( _sygnal.probki[ i ].x > _max ) _max = _sygnal.probki[ i ].x; } return _max - _min; } double minimum( const Sygnal & _sygnal ) { double _min = _sygnal.probki[ 0 ].x; for( int i = 0; i < _sygnal.probki.size(); i++ ) { if( _sygnal.probki[ i ].x < _min ) _min = _sygnal.probki[ i ].x; } return _min; } double maksimum( const Sygnal & _sygnal ) { double _max = _sygnal.probki[ 0 ].x; for( int i = 0; i < _sygnal.probki.size(); i++ ) { if( _sygnal.probki[ i ].x > _max ) _max = _sygnal.probki[ i ].x; } return _max; } double srednia( const Sygnal & _sygnal ) { double m = 0.0; for( int i = 0; i < _sygnal.probki.size(); ++i ) { m += _sygnal.probki[ i ].x; } if( _sygnal.probki.size() > 0 ) { m /= _sygnal.probki.size(); } return m; } double calka( const Sygnal & _sygnal ) { double calka = 0, dt = 0, dpole = 0; for( int i = 0; i < _sygnal.probki.size(); i++ ) { dt = _sygnal.probki[ i + 1 ].t - _sygnal.probki[ i ].t; dpole =( _sygnal.probki[ i ].x + _sygnal.probki[ i + 1 ].x ) * dt / 2; calka = calka + dpole; } return calka; } };
#endif Oraz plik z klasą SygnalLoader: #ifndef _SygnalLoader_h_ #define _SygnalLoader_h_ #include <string> #include <fstream> #include <sstream> #include "Sygnal.h" using namespace std; class SygnalLoader { public: SygnalLoader() { } Sygnal wczytajSygnal( string _nazwaPliku ) { } void zapiszSygnal( Sygnal & aSygnal, std::string aNazwaPliku ); }; #endif
Main ( do przetestowania działania ): #include <iostream> #include "AnalizatorSygnalu.h" #include "Sygnal.h" #include "Probka.h" #include "SygnalLoader.h" using namespace std;
int main() { SygnalLoader sl; AnalizatorSygnalu as; Sygnal s; Probka p = Probka( 10, 20 ); s.dodajProbke( p ); Probka p2 = Probka( 20, 30 ); s.dodajProbke( p2 ); cout << "iloscProbek: " << s.iloscProbek() << endl; cout << "maksimum: " << as.maksimum( s ) << endl; cout << "minimum: " << as.minimum( s ) << endl; cout << "srednia: " << as.srednia( s ) << endl; cout << "dlugosc: " << as.dlugosc( s ) << endl; cout << "calka: " << as.calka( s ) << endl; }
Po uruchomieniu programu main wyskakują, niedziwiące mnie zresztą błędy wskazujące na to, że wektor jest prywatny biorące się z klasy AnalizatorSygnalu ale zapewne także brałoby się z klasy SygnalLoader która służy do wczytania sygnału z pliku - fragment programu został wykomentowany bo sprawiał jakieś małe problemy. Dodałbym do funkcji Sygnal klasę zaprzyjaźnioną AnalizatorSygnalu, ale niestety prowadzący powiedział, tu cytuję: "Nie ma takiego elementu na schemacie UML więc proszę to usunąć". Jak więc mogę dostać się do tego elementu nie działając na więziach pomiędzy klasami? Jak pobrać zawartość wektora, jak coś do niego wpisać. Liczę na pomoc. Jeżeli potrzeba więcej informacji na temat ww. dostarczę jak najszybciej. Pozdrawiam. |
|
pekfos |
» 2017-10-31 22:12:59 Po co ci dostęp do tego wektora? Nie wystarczą metody z klasy Sygnal? |
|
YooSy |
» 2017-10-31 22:17:24 np. tak: double _min = _sygnal[ 0 ].x; , ale do tego musi być zdefiniowany Probka & operator []( int i ) { return probki[ i ]; } const Probka & operator []( int i ) const { return probki[ i ]; } Ogólnie kod jest do poprawienia. Użycie przestrzeni nazw std w pliku nagłówkowym to zła praktyka. Dodawanie podkreślenia przed nazwą zmiennej to zły nawyk. Stosuj się do zasady The rule of three/five/zero |
|
selveee Temat założony przez niniejszego użytkownika |
» 2017-10-31 22:43:56 @pekfos W teorii wystarczyłyby mi metody z klasy Sygnal, w praktyce jednak nie widzę, swoim okiem przynajmniej, bo dla klasy AnalizatorSygnalu nie widzę sposobu aby pobrać elementy z wektora chyba, że robiąc coś w stylu podpowiedzi kolegi @YooSy.
@YooSy Co do definiowania operatorów, mam twardo zapisaną w schemacie UML ilość elementów, tj. funkcje, operatory i inne pierdółki, a jeżeli mi się dobrze wydaje to jeden z operatorów ( const ) jest dodany już od Ciebie a nie jest zawarty w schemacie - prowadzący bije po łapach jak próbujemy coś dodać, chyba że zawiera się wewnątrz elementu :(.
Dodałem przestrzeń nazw z przyzwyczajenia, pierwotnie było bez tego ale przepisywałem kod na nowo i dodałem żeby było szybciej, _ używam z przyzwyczajenia, możliwe że niesłusznie ale przynajmniej wiem co gdzie i jak.
|
|
selveee Temat założony przez niniejszego użytkownika |
» 2017-10-31 23:16:06 Dziękuję Panowie ( i Panie ? ) za podrzucenie wręcz gotowego rozwiązania, działać działa jak należy, mam jednak pytanie co do jeszcze jednej klasy - mianowicie SygnalLoader, Sposób przedstawiony powyżej jest nieprawidłowy, tj. nie działa poprawnie, wysypuje program, robi różne cuda. Co trzeba tam poprawić, dodać, odjąć żeby nie sypał całego programu ( dodam że dane są w formie xxx, xxx gdzie xxx to liczby i jest ich 100 rekordów ) oraz jak sprawić aby dane zapisały się do wektora tego samego na którym będę później operował. W przypadku gdyby funkcja miała formę w stylu Sygnal wczytajSygnal(Sygnal& aSygnal, string _nazwaPliku) to nie byłoby problemu, tutaj jednak coś takiego nie występuje, jakieś pomysły ?
WIem, że może niejasno się wyrażam ale staram się przekazać co mam w swojej głowie jasno i zrozumiale :/ |
|
YooSy |
» 2017-10-31 23:41:15 WIem, że może niejasno się wyrażam ale staram się przekazać co mam w swojej głowie jasno i zrozumiale :/ |
Jaśniej i zrozumialej będzie jeśli powiesz co i w jaki sposób się "sypie". Czy są to jakieś wyjątki, komunikaty systemowe, nieprawidłowe działanie, dane wyjściowe niezgodne z oczekiwanymi (mile widziane przykłady). Pierwszym razem dokładnie był wskazany problem i został rozwiązany. Sygnal x; x.dodajProbke( nowa_probka ); |
W każdej iteracji tworzysz nowy obiekt klasy Sygnal, zapisujesz dane i tracisz. Zdefiniuj obiekt przed pętlą. Nic nie zwracasz z metody wczytajSygnal choć deklarujesz, że zwrócisz. Poza tym mocno komplikujesz sobie sprawę. stringstreamy nie są ci potrzebne. Sygnal sygnal; double liczba1, liczba2; char ignorowany_znak; while( plik >> liczba >> ignorowany_znak >> liczba2 ) { sygnal.dodajProbke( Probka { liczba1, liczba2 } ); } Coś takiego. |
|
selveee Temat założony przez niniejszego użytkownika |
» 2017-10-31 23:45:13 Nie potrafię tego przedstawić ze strony kompilatora, gdyż nie wysypuje mi żadnych widzialnych błędów ( tak używam Dev-Cpp i wszelakie debugery są mi obce, nie korzystałem nigdy ), zwyczajnie po uruchomieniu programu, dla przykładu: Z klasy SygnalLoader ( mowa o funkcji wczytajSygnal ): #ifndef _SygnalLoader_h_ #define _SygnalLoader_h_ #include <string> #include <fstream> #include <sstream> #include "Sygnal.h" using namespace std; class SygnalLoader { public: SygnalLoader() { } Sygnal wczytajSygnal( string _nazwaPliku ) { Probka nowa_probka = Probka( 10, 21 ); Sygnal s; s.dodajProbke( nowa_probka ); } void zapiszSygnal( Sygnal & _Sygnal, std::string _nazwaPliku ); }; #endif Oraz z main: #include <iostream> #include "AnalizatorSygnalu.h" #include "Sygnal.h" #include "Probka.h" #include "SygnalLoader.h" using namespace std;
int main() { SygnalLoader sl; AnalizatorSygnalu as; Sygnal s; Probka p = Probka( 10, 20 ); s.dodajProbke( p ); Probka p2 = Probka( 20, 30 ); s.dodajProbke( p2 ); sl.wczytajSygnal( "sygnal.csv" ); } Program najzwyczajniej w świecie myśli 1 - 2 sekundy po czym wypluwa komunikat że przestał działać. Drugi problem to to, że potrzebuję zastosować to tak, aby przy utworzeniu obiektu s klasy Sygnal móc wczytać elementy z wektora do którego zostały wpisane dane poprzez wczytanie funkcją wczytajSygnal - tak jak wspomniałem, gdyby funkcja przybrała formę Sygnal wczytajSygnal( Sygnal & _sygnal, string _nazwaPliku ) nie byłoby problemu, jednak tutaj przesłać do funkcji obiektu klasy nie mogę. Może teraz coś więcej to opowie :) |
|
YooSy |
» 2017-10-31 23:56:21 W poprzednim poście dopisałem kilka uwag. Tutaj znalazłem kilka sposobów debugowania, gdy nie zna się swojego debuggera lub nie ma do niego dostępu. https://www.youtube.com/watch?v=FqKjc_VKPCkProgram najzwyczajniej w świecie myśli 1 - 2 sekundy po czym wypluwa komunikat że przestał działać. |
Program w tym momencie ma niezdefiniowane zachowanie i może zachować się w dowolny sposób. |
|
« 1 » 2 |