Daten einlesen, neu schreiben
-
SeppJ schrieb:
Als Funktionsparameter statt Containern Iteratoren benutzen! -> vector, string, array, eigener containertyp; alles kein Problem!
Kannst du mir da ein beispiel zeigen ich versteh das noch nicht ganz.
@Sone bitte verwirr mich nicht!

-
Schau dir mal das Iterator-Pattern der Gang of Four an.
Im Prinzip macht man da nichts anderes als den Zugriff auf Container zu kapseln und darüber dann seine Algorithmen anzuwenden.
template<class T> void sortiere(vector<T> & v){} template<class T> void sortiere(list<T> & v){} template<class T> void sortiere(set<T> & v){} template<class T> void sortiere(DeinContainerBaumDing<T> & v){}So ist der "triviale" Weg. Mit Iteratoren sparst du dir da viel viel Arbeit:
template<class Iterator> void sortiere(Iterator begin, Iterator end){} int main() { vector<int> vec = { /* ... */ }; sortiere(vec.getBeginiterator(), vec.getEndIterator()); DeinContainerBaumDing c = /*... */; sortiere(c.getBeginiterator(), c.getEndIterator()); // usw... }Du musst also nicht deinen Algorithmus für viele verschiedene Container/Datenstrukturen immer wieder neu implementieren, sondern du gibst Iteratoren an die Algorithmen. Diese kapseln den Zugriff und lassen sich auf das nächste Element verschieben(oder sogar noch mehr). Du musst also nur noch für deine Datenstruktur einen Iterator zur Verfügung stellen und schon kannst du sämtliche Algorithmen nutzen (anstatt diese komplizierten Dinger neu zu schreiben).
In Java geben die Datenstrukturen normalerweise per ".iterator()" Methode einen Iterator zurück, der sowas kann wie "it.next()" und "it.hasNext()". Ich denke das ist relativ selbsterklärend.
In C++ gibt es dafür die Methode ".begin()", die einen Iterator auf das erste Element zurückgibt. In jedem Fall kann man diesen Iterator inkrementieren (auf das nächste Element setzen mit "it++" bzw "++it" und auch dereferenzieren, also das Element, auf das gezeigt wird, ansprechen mit "*it".
Der End-iterator zeigt gewöhnlich immer hinter das letzte Element einer Struktur, so dass die normale Schleifenbedingung ist: Solange it ungleich c.end(), mache xyzSieht so aus:
vector<double> v; for(vector<double>::iterator it = v.begin(); it != v.end(); ++it) { double & currentElement = *it; // mach was }Abgekürzt mit C++11:
vector<double> v; for(auto it = v.begin(); it != v.end(); ++it) { double & currentElement = *it; // mach was }oder noch kürzer:
vector<double> v; for(double & currentElement : v) { // mach was }Es gibt da einiges drüber zu lesen und zu wissen, aber das ist echt wichtig, wie ich finde.
-
Danke schon mal für die Antworten!!
Also ich hab jetzt versucht:
template <class Iterator> void copyFile(Iterator begin, Iterator end){ /*...*/ } void blaclass::blafunc(string const& Filepath){ std::ifstream file(FilePath); if(!file.is_open()){ std::cerr << "Error: No file found!" << '\n'; } std::istreambuf_iterator<char> fileit{file}; copyFile<char>(fileit.begin(), fileit.end()); }Nur ist das mit dem iterator noch nicht so richtig! Der hat kein begin und end. Da hab ich doch irgendwas nicht verstanden.
Die /**/stream_isteratoren haben, zu mindestens laut reference, kein begin und end.
Hoffe ich nerv nicht.
-
Der Iterator ist doch auch schon selbst der Iterator!

std::istreambuf_iterator<char> fileit{file}, file_end_it; copyFile(fileit, file_end_it);Hier nutzt man, dass ein default-konstruierter stream-Iterator einen end-of-stream Iterator darstellen, wie du in einer Referenz herausgefunden hättest.
Da sind aber noch mehr Designschwächen drin:
void blaclass::blafunc(string const& Filepath);->
void blaclass::blafunc(istream & File);Denn sofern deine Klasse nicht selber eine Datei darstellt, ist ihre Aufgabe nicht, sich um Dateien zu kümmern. Klare Trennung von Zuständigkeiten! Ein gutes Argument dafür ist schon deine unbeholfene Art und Weise, wie du in deinem Eingangsbeitrag die Fehler behandelst. Deine Klasse ist nicht für Dateihandling gemacht, sie versagt bei der Behandlung.
void blaclass::blafunc(istream & File);->
void blafunc(istream & File);Nichts an deinem Code deutet darauf hin, dass dies überhaupt eine Klassenfunktion sein sollte. Vielleicht hast du auch zu wenig gezeigt, aber ich tippe eher auf Designfehler.
buffer = new char[length];Wirklich?
Wie viele Millionen mal muss man dir eigentlich std::vector erklären? Nimm niemals new für Arrays!Ich glaube, die gesamte Funktion soll wohl einfach nur
std::ifstream file("Blah"); std::vector<char> blah(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());sein, oder? Also gar keine Funktion, sondern einfach nur zwei Zeilen Code.
-
SeppJ schrieb:
buffer = new char[length];Wirklich?
Wie viele Millionen mal muss man dir eigentlich std::vector erklären? Nimm niemals new für Arrays!

Ich MUSS wirklich MUSS das so machen! Ich hab das ganze was ich grade umschreibe mit einem vector gelöst. Dann durfte ich mir anhören das der leider nicht threadsafe(lieblings Argmument) ist und ich das doch bitte ändern soll.(Erklärung warum das so ist gab es nicht, angeblich sollen begin und end nicht funktionieren hat er mal irgendwo in einer reference gelesen ganz unten nie wieder auffindbar) Was bleibt mir den wenn ich von C++ kein std benutzen soll? -.- Ich kann nicht mal richtig Hilfe suchen weil ich einfach immer für absolut behindert erklärt werde.
Trotzdem danke für eure Beiträge da ich dadurch für mich privat lerne wie ich es machen soll. Buch bin ich auch schon am Durcharbeiten was mich hier immer mehr hinterfragen lässt.
(Der C++ Programmierer)EDIT:
Die Funktion soll ein Bild (Datei) einlesen und diese soll dann nach Markern(JPEG Marker) durchsucht werden um mein bekanntes Thema zu behandeln.
-
Fuchs aus dem Wald schrieb:
Dann durfte ich mir anhören das der leider nicht threadsafe(lieblings Argmument) ist und ich das doch bitte ändern soll.(Erklärung warum das so ist gab es nicht, angeblich sollen begin und end nicht funktionieren hat er mal irgendwo in einer reference gelesen ganz unten nie wieder auffindbar)

Hat der auch behauptet, dass static_cast nicht threadsafe ist?
Der Typ scheint weder programmieren, noch diskutieren zu können. Von dem lernst du nichts, der schadet dir bloss. Entweder kannst du ihn auswechseln, oder du machst was er sagt, wohlwissend, dass das alles Quatsch ist, den du sofort wieder vergessen sollst.
-
Scott Meyers ist im November in Stuttgart. Schick den Typen da hin, damit seine Kenntnisse wieder mal aufgefrischt werden

-
ellol schrieb:

Hat der auch behauptet, dass static_cast nicht threadsafe ist?
JA!
ellol schrieb:
Der Typ scheint weder programmieren, noch diskutieren zu können. Von dem lernst du nichts, der schadet dir bloss. Entweder kannst du ihn auswechseln, oder du machst was er sagt, wohlwissend, dass das alles Quatsch ist, den du sofort wieder vergessen sollst.
Bin dabei.
MichelRT schrieb:
Scott Meyers ist im November in Stuttgart. Schick den Typen da hin, damit seine Kenntnisse wieder mal aufgefrischt werden

Super Idee! Ich frag mein Chef, ob man da nicht mal hin kann um besser zu werden!
EDIT: 1.990€ ...

-
Auf die Gefahr hin sofort erschlagen, erschossen und gehängt zu werden

Also ich glaube ich muss mich über sowas hier 0 wundern. Aber ich weiß leider grade auch nicht weiter. Ich soll so arbeiten aber ich weiß nicht wie.Fehler:
*** glibc detected *** ../build/src/mxpw: malloc(): memory corruption: 0x000000000060c510 ***Code:
bool ImgFile::getFile(std::string Rootpath, std::string FilePath){ int imgfile = open((Rootpath+FilePath).c_str(), O_RDONLY); if(imgfile != -1){ off_t imglen=lseek(imgfile, 0, SEEK_END); Buff = new char[imglen]; lseek(imgfile, 0, SEEK_SET); read(imgfile, (void*)Buff, imglen); //generate mxJPEG list if(!MxjpegRoot){ MxjpegRoot = new mxJPEG; MxjpegCurr = MxjpegRoot; }else{ MxjpegCurr->NextMxjpeg = new mxJPEG; MxjpegCurr = MxjpegCurr->NextMxjpeg; } MxjpegCurr->NextMxjpeg = NULL; //find all mkarker and save them into mxJPEG instance int dqtIndex = 0; int dhtIndex = 0; int checkDht = 0; int checkDqt = 0; for(int i = 0; i<imglen; ++i){ switch((unsigned char)Buff[i]){ case(unsigned char)0xd8: MxjpegCurr->setSOI(&Buff[i]); break; case(unsigned char)0xdb: MxjpegCurr->setDQT(&Buff[i], dqtIndex); ++dqtIndex; break; case(unsigned char)0xc4: MxjpegCurr->setDHT(&Buff[i], dhtIndex); ++dhtIndex; break; case(unsigned char)0xda: MxjpegCurr->setSOS(&Buff[i]); break; case(unsigned char)0xd9: MxjpegCurr->setEOI(&Buff[i]); break; } } if(checkDht != 4){ for(int j = 0; j<4; ++j){ MxjpegCurr->setDHT(0, j); } } if(checkDqt != 2){ for(int k = 0; k<2; ++k){ MxjpegCurr->setDQT(0, k); } } }else{ std::cerr << "Error: Failed to load file!" << '\n'; } }EDIT:
Ja ja oh wunder std::cerr darf ich benutzen.
-
Programmier doch einfach vector nach. Dein komischer Kollege merkt bestimmt ohnehin nicht. Oder mach sogar eine Kopie einer Open-Source vector-Implementierung, damit es auch gut ist, und nenn die Klasse um. Dann passieren solche Fehler einfach nicht mehr und du sparst Unmengen Zeit bei der Fehlersuche.P.S.: Du castest Case-Marken?
Noch dazu mit C-Style Casts? Hast du das auch von deinem Kollegen, der nicht weiß, was Casting ist? Literalen kannst du einen Typ geben. 0uist zum Beispiel ein unsigned int. Und Casting machen wir wenn dann sowieso nur mit C++-Casts, bei den C-Casts ist nicht eindeutig, was sie überhaupt machen und eine Änderung an einer ganz anderen Stelle im Programm könnte somit eine Katastrophe auslösen und aus einem static_cast einen reinterpret_cast machen.
-
Also ich benutze, genau wie Volkard es einmal angedeutet hat (kann das Zitat nicht finden), um Skalare o.ä. zu casten nur function-style-casts. static_cast drückt für mich eher ein Flair aus der zum OOP passt.
-
Sone schrieb:
Also ich benutze, genau wie Volkard es einmal angedeutet hat (kann das Zitat nicht finden), um Skalare o.ä. zu casten nur function-style-casts. static_cast drückt für mich eher ein Flair aus der zum OOP passt.
Ja, da kann
nicht vielnichts passieren, aber es ist sicherlich eine gute Idee, dass man darüber nachdenkt, was man warum tut. Ich wette, der Threadersteller hat die function-style Casts eher aus Unkenntnis oder aus falschen Ratschlägen heraus (Threadsicherheit, lol :p ) benutzt.
-
SeppJ schrieb:
Du castest Case-Marken?
Halte ich an dieser Stelle nicht für völlig abwegig - wenn man mit den Promotionsregeln nicht fest vertraut ist. Der einzige (für Portabilität) erforderliche Cast ist hier nat. nur der im Auswahlausdruck.
Sone schrieb:
Also ich benutze, genau wie Volkard es einmal angedeutet hat (kann das Zitat nicht finden), um Skalare o.ä. zu casten nur function-style-casts.
Komisch, dabei sind es doch gerade Casts, bei denen Skalare involviert sind, die überhaupt nur richtig gefährlich sein können.
-
camper schrieb:
Sone schrieb:
Also ich benutze, genau wie Volkard es einmal angedeutet hat (kann das Zitat nicht finden), um Skalare o.ä. zu casten nur function-style-casts.
Komisch, dabei sind es doch gerade Casts, bei denen Skalare involviert sind, die überhaupt nur richtig gefährlich sein können.
In meinem Code gibt es keine gefährlichen Casts. Ich habe größtenteils nur unbedeutenden Fälle, wie: Cast in einer initializer-list um narrowing zu umgehen. Ich caste nie Zeiger hin oder her, jedenfalls nicht in eigenen Projekten. Nur
If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4).
@SeppJ: Wie kann ein function-style-cast also nicht gefährlich sein? Er stellt dasselbe wie ein C-Cast dar.
-
Sone schrieb:
@SeppJ: Wie kann ein function-style-cast also nicht gefährlich sein? Er stellt dasselbe wie ein C-Cast dar.
Na, dann, wenn du ihn nur ganz bewusst in unkritischen Fällen einsetzt, die unter keinen Umständen umgedeutet oder uneindeutig werden können. Ich hatte gedacht/gehofft, dass du eben diese Fälle meinst, in denen du die Casts so einsetzt.
-
SeppJ schrieb:
Programmier doch einfach vector nach. Dein komischer Kollege merkt bestimmt ohnehin nicht. Oder mach sogar eine Kopie einer Open-Source vector-Implementierung, damit es auch gut ist, und nenn die Klasse um. Dann passieren solche Fehler einfach nicht mehr und du sparst Unmengen Zeit bei der Fehlersuche.Der Fehler kam durch ein fehlendes delete! Also ist genau der Fall eingetroffen vor dem ihr mich immer gewarnt habt! Ich danke euch noch mal hier das ihr obwohl ich nur mist Poste immer noch beisteht und zeigt wie es richtig geht.
Klassen Namen werde ich noch mal überdenken.
Das mit dem vector nach Programmieren könnte man echt hier fast so sehen. Nur in langsamer.
SeppJ schrieb:
P.S.: Du castest Case-Marken?
Noch dazu mit C-Style Casts? Hast du das auch von deinem Kollegen, der nicht weiß, was Casting ist? Literalen kannst du einen Typ geben. 0uist zum Beispiel ein unsigned int. Und Casting machen wir wenn dann sowieso nur mit C++-Casts, bei den C-Casts ist nicht eindeutig, was sie überhaupt machen und eine Änderung an einer ganz anderen Stelle im Programm könnte somit eine Katastrophe auslösen und aus einem static_cast einen reinterpret_cast machen.Ehm ja wurde mir alles so gezeigt und static_cast darf ich ja nun nicht benutzen. Bleibt ja nur der C-cast.

Ja ich sollte das so casten. Ich wusste nicht das man das auch anders lösen kann. Mir wurde der cast gesagt aber das auch einfach 0xd8 reicht wusste ich nicht. Danke!
Also es funktioniert jetzt so:case 0xd8:Allerdings muss dann im switch das bleiben:
switch((unsigned char)Buff[i])){
-
Fuchs aus dem Wald schrieb:
Ehm ja wurde mir alles so gezeigt und static_cast darf ich ja nun nicht benutzen. Bleibt ja nur der C-cast.

WTF! Hast du deinem Profiprogger denn nicht mal das Beispiel aus deinem letzten Thread gezeigt?
struct strange { operator int() { return !(std::cout << "Diese Operation ist nicht threadsafe!" << std::endl); } }; int main() { strange s; static_cast<int>(s); (int)s; }
-
Problem

Sowas will er nicht hören! Und da ich ja eh hier der Anfänger bin hab ich keine Ahnung.
-
bar.h
class Bar{ public: Bar(); ~Bar(); void read(); private: const char* Buffer; Foo* foo; };foo.h
class Foo{ public: const char*getFooFii(); void setFii(const char* fii); private: const char* FII[4]; };bar.cpp
Bar::Bar(){ foo = new Foo; } Bar::~Bar(){ delete foo; } void Bar::read(){ //liest datei in Buffer ein //sucht punkte in Buffer foo->setFii(Buffer[i]); }Habe ich recht, wenn ich sage, dass wenn ich mir aus einer anderen Klasse jetzt getFooFii() aufrufe ich zwar ein pointer habe aber sobald ich dann sowas mache wie foo+1.. oder foo[1..] dann hab ich undefinertes verhalten?
Also:const char* foo = foo->getFooFii(); std::cerr << *foo+1 << \n;