[Datei-Verschluessler] Wo ist der Fehler?



  • Hallo.
    Ich hab mir heut ein kleines Programm gebastelt, dass Dateien verschluesselt und auch wieder entschluesselt. Leider klappt das aber nur teilweise. Bestimmte Zeichen werden anscheinend falsch verschluesselt oder entschluesselt.

    inhalt ist ein string in der der gesamte Dateiinhalt enthalten ist.

    Verschluessler:

    for (size_t i=0; i<inhalt.size(); i++)
    	{
    		if (inhalt[i] < 255)
    		{
    			inhalt[i] += 1;
    		}
    		else
    		{
    			inhalt[i] = 0;
    		}
    	}
    

    Entschluessler:

    for (size_t i=0; i<inhalt.size(); i++)
    	{
    		if (inhalt[i] > 0)
    		{
    			inhalt[i] -= 1;
    		}
    		else
    		{
    			inhalt[i] = 255;
    		}
    	}
    

    Wo ist nur der Fehler?

    Gruss,
    Cartman



  • schau doch mal mit einem debugger nach, da siehst du sofort was schief läuft.
    tip: strings bestehen nicht aus unsigned chars.



  • ununterschrieben schrieb:

    schau doch mal mit einem debugger nach, da siehst du sofort was schief läuft.
    tip: strings bestehen nicht aus unsigned chars.

    Hab das nun geaendert und bei Text-Dateien klappt das jetzt ganz gut, glaube ich zumindest...
    Aber wenn ich ein Bild verschluessle/entschluessle, dann kommt irgendwie murgs raus... (aber das Bild kann man komischerweise trotzdem ansehen)

    Bild vor dem verschluesseln
    http://img228.imageshack.us/img228/3413/bild2ss9.jpg

    Bild nach dem verschluesseln/entschluesseln
    http://img175.imageshack.us/img175/3634/bildcr0.jpg

    Der Code sieht jetzt so aus:

    // Verschluesseln
    	for (size_t i=0; i<inhalt.size(); i++)
    	{
    		if (inhalt[i] < 127)
    		{
    			inhalt[i] += 1;
    		}
    		else
    		{
    			inhalt[i] = -127;
    		}
    	}
    
    	// Entschluesseln
    	for (size_t i=0; i<inhalt.size(); i++)
    	{
    		if (inhalt[i] > -127)
    		{
    			inhalt[i] -= 1;
    		}
    		else
    		{
    			inhalt[i] = 127;
    		}
    	}
    

    Warum wird das Bild nicht mehr richtig entschluesselt?
    Muss ja einen Grund geben 🙂

    Gruss
    Cartman



  • Ich würde nicht unbedingt std::string verwenden, da das ein typedef für std::basic_string<char> ist und char sich je nachdem wie signed char oder unsigned char verhält. Vielleicht besser eine weitere Instanziierung des basic_string -Templates...

    Zudem:

    else
            {
                inhalt[i] = -127;
            }
    

    Hier wird ja die Hälfte des Wertebereichs auf eine Zahl abgebildet. So ist die Bijektivität nicht mehr gegeben; wie soll beim Entschlüsseln entschieden werden, welcher ursprünglichen Zahl die -127 entsprochen hat?



  • Nexus schrieb:

    Ich würde nicht unbedingt std::string verwenden, da das ein typedef für std::basic_string<char> ist und char sich je nachdem wie signed char oder unsigned char verhält. Vielleicht besser eine weitere Instanziierung des basic_string -Templates...

    Zudem:

    else
            {
                inhalt[i] = -127;
            }
    

    Hier wird ja die Hälfte des Wertebereichs auf eine Zahl abgebildet. So ist die Bijektivität nicht mehr gegeben; wie soll beim Entschlüsseln entschieden werden, welcher ursprünglichen Zahl die -127 entsprochen hat?

    Also den Anfang deines Posts versteh ich nich ... (bin Anfaenger) 😞 Meinst du damit, dass es nich immer sicher ist, ob char signed oder unsigned ist (bezugelich des strings).

    Zum zweiteren:
    Es ist ja so... Der ASCII-Wert des Zeichens wird immer um 1 erhoeht. Wenn es sich aber um ein Zeichen handelt, dass schon den maximalen Wert hat (127) wird der auf das minimalste (-127) gesetzt ... Beim entschluesseln weiss ich ja dann, dass alle Zeichen die -127 sind vor dem Verschluesseln 127 waren...



  • Eric Cartman schrieb:

    Also den Anfang deines Posts versteh ich nich ... (bin Anfaenger) 😞 Meinst du damit, dass es nich immer sicher ist, ob char signed oder unsigned ist (bezugelich des strings).

    Ja, also C++ kennt die drei verschiedenen Typen:

    char
    signed char
    unsigned char
    

    Ob sich char nun bezüglich des Wertebereichs wie signed oder unsigned verhält, ist implementierungsspezifisch. Deshalb sollte man nicht davon ausgehen, dass der Wertebereich von -128 bis 127 geht.

    Eric Cartman schrieb:

    Es ist ja so... Der ASCII-Wert des Zeichens wird immer um 1 erhoeht. Wenn es sich aber um ein Zeichen handelt, dass schon den maximalen Wert hat (127) wird der auf das minimalste (-127) gesetzt ... Beim entschluesseln weiss ich ja dann, dass alle Zeichen die -127 sind vor dem Verschluesseln 127 waren...

    Klar. Sorry, ich hab da grad nicht durchgeblickt, bin vom falschen Wertebereich ausgegangen... Aber das Minimum wäre dennoch -128. 😉



  • @Nexus
    Ahja, jetzt hab ich es begriffen, thx 🙂 - kann mich auch ganz dunkel daran erinnern, dass das irgendwo auch in meinem C++-Buch besprochen wurde 🙂
    Nur wie loese ich jetzt das Problem, wenn ich will dass mein Code Compiler-unabhaengig funktioniert? Waere ein dynamischer signed char-vector das richtige?

    Uebrigens funktioniert mein Programm jetzt. Musste nur die -127 - Werte mit -128 ersetzen... thx 🙂



  • Nexus schrieb:

    Eric Cartman schrieb:

    Also den Anfang deines Posts versteh ich nich ... (bin Anfaenger) 😞 Meinst du damit, dass es nich immer sicher ist, ob char signed oder unsigned ist (bezugelich des strings).

    Ja, also C++ kennt die drei verschiedenen Typen:

    char
    signed char
    unsigned char
    

    Ob sich char nun bezüglich des Wertebereichs wie signed oder unsigned verhält, ist implementierungsspezifisch. Deshalb sollte man nicht davon ausgehen, dass der Wertebereich von -128 bis 127 geht.

    =>
    nimm std::numeric_limits <char>::max() bzw. std::numeric_limits <char>::min() und schau davor, ob max() und min() makro aus der winapi ausgeschalten ist ^^

    allerdings müsste es mit -128 auch bei nem unsigned typen gehen?!

    bb



  • Ein std::vector<signed char> wäre nicht schlecht, zumal es ja hier nicht um den String als Zeichenkette sondern um den Container von einzelnen Zeichen geht.

    Ansonsten - wenn du die Funktionalität von std::string benötigst - kannst du wie gesagt das Template einsetzen:

    typedef std::basic_string<signed char> SignedString;
    

    @ unskilled
    Ich bin mir nicht mehr ganz sicher, aber ich dachte, die Umwandlung negativer Zahlen zu unsigned wäre auch implementierungsspezifisch... Irgendwie kann man sich ja auf nichts wirklich verlassen. 😉

    Das mit numeric_limits finde ich unnötig, da man gleich signed char nehmen kann, um sicher zu gehen.



  • ich würde bei datei und vector bei char bleiben und nur beim rechnen casten.

    for (size_t i=0; i<inhalt.size(); i++) 
        { 
            unsigned char x=inhalt[i];
            ++x;
            inhalt[i]=x; 
        }
    


  • Nimm std::vector<unsigned char> und lass das if-Konstrukt weg. Ein Überlauf führt zum gleichen Ergebnis, egal was für einen Wertebereich du hast.



  • Okay, also ob ich std::basic_string<signed char> oder std::vector<signed char> nehme spielt also keine Rolle oder?

    @Ueberlaeufer
    Sicher? Gilt das auch fuer alle Compiler/Plattformen?

    Ich bin jetzt noch etwas verwirrt wegen char ...
    Warum gibt es signed char und unsigned char ???
    Waere 256 nicht dasselbe Zeichen wie -1?
    Und ich bin mir jetzt noch wegen des einlesens von der Datei unsicher... Wird das Zeichen immer als signed eingelesen? (mit fileobject.get() )

    😕



  • Eric Cartman schrieb:

    Sicher? Gilt das auch fuer alle Compiler/Plattformen?

    Ja, aber nur für vorzeichenlose Typen.


Anmelden zum Antworten