if-Bedingung wird nie wahr
-
@docshoe sagte in if-Bedingung wird nie wahr:
Hab außer Stilfragen leider nicht viel zu deinem Problem beizutragen, aber:
- Wenn du die Größen der Vektoren bereits kennst dann benutze reserve() , resize() oder inititalisiere die Vektoren mit der richtigen Größe, um unnötige Allokationen zu vermeiden.
- Vermeide Elementzugriffe mit at(), benutz´ stattdessen den Indexoperator[]
- Kopier´ ganze RGB Objekte statt jedes Attribute einzeln
- benutz´ keine handgeschriebenen Schleifen über Vektorelemente, dazu gibt es in der STL passende Funktionen.
Ansonsten kann ich Swordfishs Anregungen nur unterstützen: Halte deine Variablen so lokal wie möglich.
Nachtrag:
Wenn du häufig mit rechteckigen Blöcken arbeitest kann es sinnvoll sein, sich dazu eine Klasse zu basteln. N Vektoren aus M Elementen lässt sich als Vektor mit M*N Elementen realisieren. Vektoren aus Vektoren haben das Problem, dass der benutzte Speicher nicht zusammenhängend ist und der Zugriff auf Elemente möglicherweise langsamer ist als der Zugriff auf zusammenhängenden Speicher.Das klingt alles vernünftig - aber wenn ich jetzt mitten im manuellen Debugging auch noch die grundlegende Architektur meines Programms umbaue, kommt nur noch mehr Durcheinander bei heraus - erstmal will ich überhaupt eine funktionierende Version haben! Um Optimierung kann ich mich dann hinterher kümmern... das Programm ist ja kein Selbstzweck, sondern soll durchaus praktische (wenn auch nicht bezahlte) Arbeit verrichten!
-
@yadgar sagte in if-Bedingung wird nie wahr:
Um Optimierung kann ich mich dann hinterher kümmern...
Bei den Punkten, die Dir @docshoe, @hustbaer und ich ans Herz gelegt haben handelt es sich nicht um "Optimierungen" sondern um "schreib sauberen, wartbaren Code".
-
Hi(gh)!
Beim weiteren Debugging habe ich einen neuen, völlig absurden Fehler festgestellt: zwar werden jetzt 4 x 8-Bereiche mit mehr als 4 Farben richtig erkannt, bei der Bestimmung der Häufigkeiten kommt es aber immer im Zusammenhang mit schwarzen (rgb <0, 0, 0>) Pixeln zu Fehlern. Schwarz ist der erste Eintrag im globalen rgb-Vektor palette; die Umrechnung des ursprünglichen True Color-Bildes auf die 16farbige C 64-Palette fand bereits vorher statt, in der gegenwärtigen Version von yip wird dieses umgerechnete Bild ohne Prüfung auf maximal 4 Farben pro 4 x 8-Bereich auf der Festplatte gespeichert.
Ein Beispiel: im 4 x 8-Bereich 8/128 bis 12/136 sollten laut gespeichertem "C 64-Rohbild" gefunden werden:
1 x türkisgrün - rgb <48,230,198>
4 x "weiß" - rgb <253,254,252>
12 x hellgrau - rgb <164,167,162>
10 x mittelgrau - rgb <112,116,111>
4 x schwarz - rgb <0, 0, 0>
1 x dunkelblau - rgb <33,27,174>Tatsächlich findet c64multicolor_correct() (Abweichung gefettet):
1 x türkisgrün - rgb <48,230,198>
4 x "weiß" - rgb <253,254,252>
12 x hellgrau - rgb <164,167,162>
10 x mittelgrau - rgb <112,116,111>
4 x dunkelgrau - rgb <66,69,64>
1 x dunkelblau - rgb <33,27,174>Ein anderes Beispiel, 4 x 8-Bereich 16/128 bis 20/136:
Sollwerte laut gespeichertem Bild:
14 x mittelgrau - rgb <112,116,111>
8 x schwarz - rgb <0, 0, 0>
7 x dunkelgrau - rgb <66,69,64>
2 x hellrot - rgb <254, 74, 87>
1 x orange - rgb <184, 65, 4>Tatsächlich gefunden:
14 x mittelgrau - rgb <112,116,111>
4 x schwarz - rgb <0,0,0>
7 x dunkelgrau - rgb <66,69,64>
4 x hellgrau - rgb <164,167,162>
2 x hellrot - rgb <254,74,87>
1 x orange - rgb <184,65,4>- hier stimmt nicht einmal die Anzahl der Farben überein!
Ich bin völlig ratlos und zunehmend verwirrt...
Es sollte doch auch mit meiner ineffizienten Programmierweise möglich sein, diesen Fehler zu vermeiden... leider habe ich nicht die geringste Ahnung, was in meinem Code logisch falsch sein könnte! Wieso stehen in ein und demselben 4 x 8-Bereich im Vektor areacols[] andere Farben als in c64_area[][]?
Oder könnte es sein, dass das ganze Vorhaben für mich mindestens eine Nummer zu groß ist und ich yip besser vergessen sollte?
Ich habe mir testhalber noch mal die Farbwerte für den jeweiligen c64_area-Vektor anzeigen lassen - und bekomme jetzt nur noch einen konfusen Wust von short-Überläufen!
Bitte helft mir, ich blicke nicht mehr durch!!!
Hier ist der Link zum Gesamtprogramm yip (tar.gz-Archiv mit allen Source-Dateien, der Logdatei und einem Beispiel-Bild): http://www.rock-o-data.de/yip_20180707.tar.gz (habe die Veränderungen, die zu dem Überlauf-Chaos führten, wieder rückgebaut)
-
Dieser Beitrag wurde gelöscht!
-
Dann ist es vielleicht doch an der Zeit den Code umzustrukturieren. Lokale Variablen machen das Debugging oft einfacher, da man ganz sicher nicht mit Altlasten arbeitet.
-
Hi(gh)!
@docshoe sagte in if-Bedingung wird nie wahr:
Dann ist es vielleicht doch an der Zeit den Code umzustrukturieren. Lokale Variablen machen das Debugging oft einfacher, da man ganz sicher nicht mit Altlasten arbeitet.
Nun gut, ich sehe es ein, dass der einzige realistische Weg zur Lösung meines Problems in der Umsetzung des Code-Vorschlags von Swordfish vom letzten Dienstag liegt - und werde wohl noch heute damit anfangen. Allerdings vorab noch: diese Konstruktionen mit std:: finde ich verwirrend - wird das Kompilat kleiner, wenn man keine Bibliotheken inkludiert? Oder was ist sonst der Vorteil?
Bis bald im Khyberspace!
Yadgar
-
Und du solltest deinen Code in kleinere (
inline
) Funktionen unterteilen, dann ist der Code auch besser test- und wartbar. Wenn du schon in der großen Funktion den Fehler nicht per Debugger rausfindest, vllt. helfen dir dann Unit-Tests für die Teilfunktionen?!
-
@th69 sagte in if-Bedingung wird nie wahr:
Und du solltest deinen Code in kleinere (
inline
) Funktionen unterteilen, dann ist der Code auch besser test- und wartbar. Wenn du schon in der großen Funktion den Fehler nicht per Debugger rausfindest, vllt. helfen dir dann Unit-Tests für die Teilfunktionen?!Debugger? Ich weiß gar nicht, wie man so ein Ding bedient, ich habe bis jetzt immer von Hand debuggt... aber was ist denn jetzt mit std::? Wozu dieses Vorgehen?
-
Was ist "von Hand debuggen" ?
Ich benutze immer meine Hände, entweder and der Tastatur oder der Maus.... Sprachsteuerung ist da nicht so angesagt...
-
@martin-richter sagte in if-Bedingung wird nie wahr:
Was ist "von Hand debuggen" ?
Ich schätze er meint Konsolenausgaben um Variablenwerte zu kennen.
@th69 sagte in if-Bedingung wird nie wahr:
dann ist der Code auch besser test- und wartbar.
Das ganze Ding ist unlesbar und unwartbar. Alleine die
main()
ist gefühlte 1.000 Zeilen lang und durchsetzt mit#ifdefs
für lokalisierte Ausgaben und Variablen, die alle am Anfang deklariert werden um dann irgendwo in Zeile 784 benutzt zu werden ...@yadgar sagte in if-Bedingung wird nie wahr:
Debugger? Ich weiß gar nicht, wie man so ein Ding bedient
lernen?
@yadgar sagte in if-Bedingung wird nie wahr:
aber was ist denn jetzt mit std::? Wozu dieses Vorgehen?
std
ist der Namensraum in dem so ziemlich alles der Standardbibliothek liegt. Wenn Du die Angabe eines Namensraums vor einem Symbol (std::whatever
) nicht kennst, dann wurde Dir wahrscheinlich beigebracht in allen Deinen Programmenusing namespace std;
zu verwenden ohne zu verstehen, warum.
-
Hi(gh)!
@swordfish sagte in if-Bedingung wird nie wahr:
@martin-richter sagte in if-Bedingung wird nie wahr:
Was ist "von Hand debuggen" ?
Ich schätze er meint Konsolenausgaben um Variablenwerte zu kennen.
Ja, bei uns in Afghanistan läuft das so... da findet Datenfernübertragung auch noch mit Eselantrieb statt, wisst ihr? Ab und zu müssen die Bits an den Netzwerkknotenpunkten sogar von Hand umgeklappt werden, das machen so graubärtige Datenmechaniker in zerlumpten Pluderhosen...
Nein, ernsthaft: seit ich in C++ programmiere (also seit ungefähr 20 Jahren) mache ich das so... ich habe mir auch mal versucht, die Bedienungsanleitung eines der gängigen Debugger durchzulesen - und bin schier verzweifelt!
Das ganze Ding ist unlesbar und unwartbar. Alleine die
main()
ist gefühlte 1.000 Zeilen lang und durchsetzt mit#ifdefs
für lokalisierte Ausgaben und Variablen, die alle am Anfang deklariert werden um dann irgendwo in Zeile 784 benutzt zu werden ...1000? Es müssten mindestens 1500 sein!
lernen?
Alles zu seiner Zeit... jetzt möchte ich erstmal diesen Codewust in Ordnung bringen! Also, womit soll ich anfangen? All die Variablendeklarationen am Anfang werden natürlich nicht in den Funktionen gebraucht, sonst stünden sie ja nicht in main()... ich könnte zumindest die für das yip-Kommando "-c64" relevanten Variablen erst an der entsprechenden Parser-Verzweigung deklarieren, allerdings wird ein Teil davon (z. B. dither) auch schon vorher für andere yip-Kommandos gebraucht...
Und dann natürlich die rgb-Objekte in pixel-Objekte überführen, klar! Aber das für alle Funktionen durchführen, das dauert Wochen, wenn nicht Monate...
@yadgar sagte in if-Bedingung wird nie wahr:
aber was ist denn jetzt mit std::? Wozu dieses Vorgehen?
std
ist der Namensraum in dem so ziemlich alles der Standardbibliothek liegt. Wenn Du die Angabe eines Namensraums vor einem Symbol (std::whatever
) nicht kennst, dann wurde Dir wahrscheinlich beigebracht in allen Deinen Programmenusing namespace std;
zu verwenden ohne zu verstehen, warum.Ich weiß... aber gibt es einen konkreten Grund, auf "using namespace std;" (der "Breymann" benutzt es, der "Aupperle"...) zu verzichten und std:: statt dessen für jede verwendete Klasse, Template etc. explizit anzugeben?
Bis bald im Khyberspace!
Yadgar ((:->>
-
Es gibt tatsächlich einen Grund using namespace std nicht zu verwenden, nämlich Mehrdeutigkeiten zu vermeiden bzw. Eindeutigkeiten zu erzwingen. In cpp Dateien kann man das machen, in Header Dateien allerdings nicht.
Du bist Opfer deines eigenen Programmierstils geworden. Statt sich einen sauberen Stil anzueignen hast du vermutlich drauflosprogrammiert, ohne dir vorher Gedanken über Design und Strutur zu machen. Jetzt bist du an einem Punkt angekommen, wo das alles über dich hereinbricht und du den Überblick verloren hast. Natürlich ist ein Refactoring langwierig, aber da wirste wohl nicht drum rumkommen.
Du programmierst seit 20 Jahren C++? Oha.... Wie kann es dann sein, dass du Code wie yip produzierst? Und nichts über die STL weisst? Und nicht weisst, wie man einen Debugger bedient? Du hast im Diskussionsverlauf gefragt, ob yip eine Nummer zu groß ist? Mit den Informationen, die du gerade lieferst lautet die Antwort: Eindeutig ja.
Dein ganzes Projekt besteht aus 2 Dateien (yip.cc und yip_classes.h), in denen du, so leider muss ich ehrlich sein, unwartbaren Spaghetticode implementierst. Da ist überhaupt nichts modularisiert, wenigstens das hätte ich bei dem Ehrgeiz, einen ImageMagick Klon zu schaffen erwartet.
yip ist ein gutes Beispiel dafür, wie man´s nicht machen sollte, hier werden so gut wie alle guten Richtlinien verletzt.Edit:
Um wenigstens etwas Konstruktives beizutragen:- teile deinen Code in Header- und Implementationsdateien auf. Als Faustregel: pro Dateipärchen eine Klasse.
- richte dich nach der Faustregel "Eine Funktion - Eine Aufgabe". Schreibe viele kurze Funktionen statt eine lange. Funktionen über mehr als eine Bildschirmseite sollten die Ausnahme sein.
- übergib Objekte per const-reference, wenn du nur lesend drauf zugreifst
- deklariere Variablen so lokal wie möglich und vermeide globale Variablen. Hab´ keine Angst Objekte zu kopieren, heutige Compiler können Kopien häufig wegoptimieren
- überlege dir sinnvolle Klassen zur Datenhaltung. Eine Klasse/Struktur für die Kommandozeilenparameter ist sinnvoll, besonders, wenn es sich um viele Parameter handelt. Lager das Parsing in eine eigene Funktion aus, die die Kommandozeile untersucht, ein Objekt passend befüllt und zurückgibt.
- überfrachte Objekte nicht mit allen möglichen Methoden. Methoden, die ihre Aufgabe über das public interface eines Objektes durchführen können kann man als freie Funktionen implementieren
- benutze die STL wo immer es geht. Ziehe STL Algorithmen und Lambdas handgeschriebenen Schleifen vor
-
@yadgar sagte in if-Bedingung wird nie wahr:
Nein, ernsthaft: seit ich in C++ programmiere (also seit ungefähr 20 Jahren) mache ich das so... ich habe mir auch mal versucht, die Bedienungsanleitung eines der gängigen Debugger durchzulesen - und bin schier verzweifelt!
Mit aktuellen grafischen IDEs geht das sowas von einfach. Solltest du echt nochmal probieren. Gibt sicher genügend YouTube Videos wo die ersten Schritte schön gezeigt werden.
-
Selbst an gdb sollte man nicht scheitern... Da liest man sich kurz ein und kann auch damit arbeiten.
Ich hab sogar schon mit dem DOS "debug" gearbeitet.
-
@yadgar sagte in if-Bedingung wird nie wahr:
Nein, ernsthaft: seit ich in C++ programmiere (also seit ungefähr 20 Jahren)
Es ist erschreckend... Erst dachte ich mir, ok, der muss ja alt sein. Aber jetzt ist mir eingefallen, viel weniger ist es bei mir auch nicht ^^
-
Hi(gh)!
@docshoe sagte in if-Bedingung wird nie wahr:
Es gibt tatsächlich einen Grund using namespace std nicht zu verwenden, nämlich Mehrdeutigkeiten zu vermeiden bzw. Eindeutigkeiten zu erzwingen. In cpp Dateien kann man das machen, in Header Dateien allerdings nicht.
Du bist Opfer deines eigenen Programmierstils geworden. Statt sich einen sauberen Stil anzueignen hast du vermutlich drauflosprogrammiert, ohne dir vorher Gedanken über Design und Strutur zu machen. Jetzt bist du an einem Punkt angekommen, wo das alles über dich hereinbricht und du den Überblick verloren hast. Natürlich ist ein Refactoring langwierig, aber da wirste wohl nicht drum rumkommen.
Ich würde sagen, bevor ich mich daran mache, arbeite ich erst mal den ganzen "Aupperle" ("Die Kunst der Programmierung in C++") durch, mein Problem ist, dass ich bis jetzt bei der Programmiererei nie ausdauernd und diszipliniert genug bei der Sache war, sondern mich nur sporadisch mal alle paar Monate mit der Materie beschäftigt habe...
Du programmierst seit 20 Jahren C++?
Sagen wir besser, ich dilettiere seit 20 Jahren in C++ herum... in POV-Ray ist es auch nicht besser, da passieren mir bis auf den heutigen Tag Anfängerfehler, während die Cracks auf news.povray.org die komplexesten Szenen locker aus dem Ärmeln schütteln...
Oha.... Wie kann es dann sein, dass du Code wie yip produzierst? Und nichts über die STL weisst? Und nicht weisst, wie man einen Debugger bedient? Du hast im Diskussionsverlauf gefragt, ob yip eine Nummer zu groß ist? Mit den Informationen, die du gerade lieferst lautet die Antwort: Eindeutig ja.
Mir kommt es sogar oft so vor, dass das ganze Leben für mich mindestens eine Nummer zu groß ist...
Dein ganzes Projekt besteht aus 2 Dateien (yip.cc und yip_classes.h), in denen du, so leider muss ich ehrlich sein, unwartbaren Spaghetticode implementierst. Da ist überhaupt nichts modularisiert, wenigstens das hätte ich bei dem Ehrgeiz, einen ImageMagick Klon zu schaffen erwartet.
yip ist ein gutes Beispiel dafür, wie man´s nicht machen sollte, hier werden so gut wie alle guten Richtlinien verletzt.Um wenigstens etwas Konstruktives beizutragen:
- teile deinen Code in Header- und Implementationsdateien auf. Als Faustregel: pro Dateipärchen eine Klasse.
- richte dich nach der Faustregel "Eine Funktion - Eine Aufgabe". Schreibe viele kurze Funktionen statt eine lange. Funktionen über mehr als eine Bildschirmseite sollten die Ausnahme sein.
- übergib Objekte per const-reference, wenn du nur lesend drauf zugreifst
- deklariere Variablen so lokal wie möglich und vermeide globale Variablen. Hab´ keine Angst Objekte zu kopieren, heutige Compiler können Kopien häufig wegoptimieren
- überlege dir sinnvolle Klassen zur Datenhaltung. Eine Klasse/Struktur für die Kommandozeilenparameter ist sinnvoll, besonders, wenn es sich um viele Parameter handelt. Lager das Parsing in eine eigene Funktion aus, die die Kommandozeile untersucht, ein Objekt passend befüllt und zurückgibt.
- überfrachte Objekte nicht mit allen möglichen Methoden. Methoden, die ihre Aufgabe über das public interface eines Objektes durchführen können kann man als freie Funktionen implementieren
- benutze die STL wo immer es geht. Ziehe STL Algorithmen und Lambdas handgeschriebenen Schleifen vor
Was ist das, die STL? Was sind Lambdas? Bevor ich deine Ratschläge überhaupt verstehen kann, sollte ich wirklich erst mal richtig C++ lernen - und zwar nicht mit irgendwelchen aus dem Internet zusammengesuchten Informationskonfetti (dafür HASSE ich das Internet!), sondern ganz altmodisch mit einem vernünftigen Lehrbuch - wie eben etwa dem "Aupperle"!
Und wenn ich es danach immer noch nicht hinbekomme, bin ich wohl einfach zu dumm zum Programmieren... und sollte mich besser zum Tütenkleben in einer Behindertenwerkstatt anmelden!
Bis bald im Khyberspace!
Yadgar
-
Hi(gh)!
Habe mittlerweile meine alten C-Lehrbücher ausgegraben... und ich glaube wirklich, dass ich c64multicolor_correct() besser überwiegend in C schreibe (bzw. das erstmal sogar als eigenständiges Programm, um besser testen zu können)... da C 64-Bilder (GEOS mal außen vor gelassen) sowieso immer 160 x 200 Pixel groß sind, sind Vektoren mit ihrer dynamischen Speicherverwaltung in diesem Fall reiner Overkill, also täte es auch ein eindimensionales Pixel-Array, wo man die Pixelpositionen im Bild mit Integer- und Modulo-Divisionen errechnet...
Bis bald im Khyberspace!
Yadgar
-
Hi(gh)!
Überlegungen vorweg:
- Für Pixel bzw. Farben wird weiterhin eine dreiteilige Struktur verwendet:
struct rgb { short red; short green; short blue; };
Wobei, schlanker wäre ja unsigned char... was haltet Ihr davon? Bei Testausgaben müssten die Farbwerte dann natürlich explizit in short gewandelt werden, aber sonst sehe ich da keinen Nachteil... oder?
- Da der Datenbestand des C 64-Bildes zwischen mehreren Funktionen (loadTGA(), c64multicolor_correct() und saveTGA()) ausgetauscht und in der zweitgenannten auch verändert wird, muss das rgb-Array im Hauptprogramm bekannt sein:
rgb c64image[32000];
und wird per Referenz (Referenz auf Zeiger!) übergeben:
bool loadTGA(rgb(&*), string); void c64multicolor_correct(rgb(&*)); bool saveTGA(rgb(&*), string);
Bis bald im Khyberspace!
Yadgar
-
@yadgar sagte in if-Bedingung wird nie wahr:
wird per Referenz (Referenz auf Zeiger!) übergeben
Wozu soll das gut sein?