Lauflängenkodierung rle



  • Hallo alle zusammen,
    ich versuche mich gerade an einem rle programm. ich verwende code::blocks.
    ich habe schon recht ausführlich gegooglt und habe auch mehrere gute ansätze gefunden. Der code der schön kurz und übersichtlich ist und mir gefiehl ist:

    #include <iostream>
    using namespace std;
    
    string encode(string str)
    {
    	string encoding = "";
    	int count;
    
    	for (int i = 0; str[i]; i++)
    	{
    		count = 1;
    		while (str[i] == str[i + 1])
    			count++, i++;
    
    		encoding += to_string(count) + str[i];
    	}
    
    	return encoding;
    }
    
    int main()
    {
    	string str = "ABBCCCD";
    
    	cout << encode(str);
    
    	return 0;
    }
    

    quelle: http://www.techiedelight.com

    Leider läuft der auf code::blocks nicht.
    Code::blocks erkennt den Befehl to_String nicht.
    Ich geh mal davon aus, da dass ein Befehl ist der von C++ 11 und neuer ist, der compiler von code::blocks ein etwas "klassicherer" ist.
    Ich habe versucht den int to string befehl umzuschreiben.

    #include <iostream>
    #include <sstream>
    using namespace std;
    
    string encode(string str)
    {
    	string encoding = "";
    	int count;
    	string zahl;
    	stringstream buffer;
    
    	for (int i = 0; str[i]; i++)
    	{
    
    		count = 1;
    
    		while (str[i] == str[i + 1])
    			count++, i++;
    
            buffer << count;
            zahl = buffer.str();
    		encoding += zahl;
    		encoding +=  str[i];
    
    	}
    
    	return encoding;
    }
    
    int main()
    {
    	string str = "ABBCCCD";
    
    	cout << encode(str);
    
    	return 0;
    }
    

    Jetzt habe ich statt des richtigen Ergebnisses, wie der 1. Code ihn ausgegeben hat: 1A2B3C1D ; das Ergebiss : 1A12B123C1231D ( ganz seltsam ist die letzte ausgabe für D).
    Mein Gedanke ist, das es mit dem loop zusammenhängt, aber wieso funktioniert dann to_String()?
    Vielleicht könnt ihr mir etwas helfen?
    Vielen Dank schonmal in Vorraus.
    P.S.: Ich hoffe ich habe kein fehler mit dem



  • Verwende die Compileroption -std=c++11 oder auch 14, 17 (nein, ich weiß nicht, wo das in deiner IDE konfiguriert wird).



  • Codeblocks: Settings->Compiler->Have g++ follow the C++11 ...
    Damit interpretiert dein g++ Compiler dein Programm als C++11, somit sollte auch to_string funktionieren.

    Ansonsten kannst du immer noch auf die "alten" C Funktionen zurückgreifen (itoa): http://www.cplusplus.com/reference/cstdlib/itoa/



  • Erstmal Danke für eure Ansätze, doch mein Lehrgang ist nun mal auf den älteren Compiler ausgelegt, also will ich es auch gerne so lösen. Desweiteren hab ich ja schon die neuere Lösung und die läuft ja auch mit neueren Compilern.
    Also jetzt mal zur Lösung:
    Ich musst lediglich den buffer innerhalb des for-loops deklarieren und jetzt läuft es. Hier der auf älteren als C++11 laufenden compilern:

    #include <iostream>
    #include <sstream>
    using namespace std;
    
    string encode(string str)
    {
    	string encoding = "";
    	int count;
        string zahl;
    
    	for (int i = 0; str[i]; i++)
    	{
    
            stringstream buffer;
    		count = 1;
    
    		while (str[i] == str[i + 1])
    			count++, i++;
    
                buffer << count;
                zahl = buffer.str();
                encoding += zahl;
                encoding +=  str[i];
    	}
    	return encoding;
    }
    
    int main()
    {
    	string str = "ABBCCCD";
    	cout << encode(str);
    	return 0;
    }
    

    Danke für eure schnelle Anteilnahme und bis bald beim nächsten Problem 😉



  • Die zahl variable kann raus und die encoding append am ende des for loops ändern zu...

    encoding += buffer.str() + str[i];
    


  • for (int i = 0; str[i]; i++)
    

    Der Test auf das Ende des Strings in in alten Compilern illegal. Ein String kennt seine Länge.



  • while (str[i] == str[i + 1])
    

    Auch das greift mit alten Compiler am Stringende illegal zu.



  • Ok...ich bin erst am Anfang und will es gerne besser machen...
    Ich habe mir auf der Schnelle mal so ein paar Zeilen aus Wiki kopiert...

    Während while und do-while immer eine Bedingung erwarten, muss bei einer for-Schleife nicht unbedingt eine Bedingung angegeben werden. Wenn keine Bedingung angegeben ist, wird einfach angenommen, dass die Bedingung immer erfüllt ist...
    ...Im Anweisungsteil können Sie eine beliebige Anweisung ausführen, dieser Teil wird oft verwendet, um Variablen bei jedem Schleifendurchlauf hoch oder runter zu zählen...

    Ich geh mal davon aus, dass solange nicht das Ende des String eintrifft und damit ein fehler, wiederhole den loop.

    Der Code lässt sich ja in beiden variationen auf den entsprechenden compilern ohne fehler kompilieren und gibt das richtige Ergebnis aus.
    Vielleicht meinst du, dass ich einen schlechten Stil verwendet habe, dann erläutert mich, damit ich es besser machen kann.



  • Du hast eine Bedingung angegeben und diese ist fehlerhaft, da sie außerhalb des erlaubten Bereichs auf den String zugreift. Programmieren ist nicht raten. Wenn es übersetzt und das Richtige rauskommt kann das Programm - wie bei dir - fehlerhaft sein. Ein Wiki ist sicher keine brauchbare Quelle um C++ zu lernen.

    dass solange nicht das Ende des String eintrifft und damit ein fehler,

    Was ist das Ende des Strings? Was für ein Fehler könnte wohl eintreten?



  • Danke für die Wiederholung deiner Aussage ohne Verbesserungsvorschlag.
    Natürlich verwende ich nur Wiki!!!
    Neben den Büchern, mein Lehrmaterial, MSDN, cppreference, etc...
    Ich habe deinen Kommentar auch nicht verneint, sondern um eine Verbesserung gebeten und nicht um den selben Kommentar + ein schlaumeier Spruch.
    Wie gesagt, läuft es und gibt keinen fehler wieder. Wiederholt auf verschiedenen compilern probiert.
    Ich werde, in Bezug deiner Aussage, nochmal meine schlauen Bücher konsultieren,
    wieso der code bei einem offensichtlichen syntax fehler, so gut läuft.
    😉



  • Ja, ich weiß dass du den Code kopiert hast, als deinen eigenen ausgibst und nicht im Ansatz verstehst.



  • Mannis Punkt ist doch gerade, dass das Programm fehlerhaft ist, obwohl es KEINEN Syntaxfehler enthält. Du redest zwar vom Ende des Strings, aber du hast keine Bedingung drin, die das auch überprüft. Die Länge eines Strings ist theString.size() , d.h. du darfst auf theString[0] bis theString[theString.size()-1] zugreifen. Du hast aber überhaupt keinen diesbezüglichen Check drin und greifst munter auf theString[i] und theString[i+1] zu, ohne jemals i+1<size zu prüfen.

    Und noch zu was anderem:

    mein Lehrgang ist nun mal auf den älteren Compiler ausgelegt, also will ich es auch gerne so lösen

    Gegenfrage: würdest du zu einer Fahrschule gehen, die dir fahren in einem 1950er Fahrschulwagen mit Zwischengas, ohne Airbag, ohne Tempomat, ohne ... beibringt? Die Antwort ist wohl "nein". Warum willst du dann veraltetes C++ lernen? Wozu soll das gut sein? C++11 ist, wie der Name schon sagt, von 2011. Jetzt ist 2018. Wenn das noch nicht im Kurs angekommen ist, wechsle den Kurs. Wenn du noch C++98 lernen willst, bitte. Aber sei dir im klaren, dass das schon 20 Jahre alt ist (nicht alles da ist schlecht, bitte versteh mich nicht falsch. Aber mit C++11 programmiert es sich so viel besser!)



  • Spaßvogel.
    Nutzlose Komentare und auch noch schnell eingeschnappt.
    Ich habe garnichts hier für meines ausgegeben.
    Ich habe doch die Quelle angegeben 😕 , da ist deine Aufmerksamkeit wohl schnell ausgelastet und einfach vom Proll ersätzt.
    😃
    Schönen Abend



  • Danke wob,
    ich habe ja auch eingelängt, dass das ein offensichtlicher Syntax fehler ist und nach Verbesserungsvorschlägen gefragt. Ich begrüsse deine Vorschläge. 👍
    Deiner Aussage, dass man doch eher mit aktuelleren compilern und entsprechenden neuen Funktionen arbeiten sollte, kann ich dir nur zustimmen. Dieser Studiengang sieht das leider anders. 😡
    P.S. @mani66 nicht mehr schmollen, ich werde es ja korrigieren 😃



  • @wob
    Ich verusch die aktuelle Syntax zu lernen, indem ich mich bemühe die Aufgaben nach Beendigung ohne zu spicken auch im VS2017 zu wiederholen.
    Der Grundgedanke und das ausformulieren des Problems ist eher der schwer Punkt. Es geht auch schon bald vom Lehrgang über zu C#-PHP-SQL...
    Danke für das angerägte Gespräch und ich werde den check einbauen... 🙂



  • Gesounds schrieb:

    Danke wob,
    ich habe ja auch eingelängt, dass das ein offensichtlicher Syntax fehler ist

    Es ist, ich wiederhole mich, KEIN Syntaxfehler.

    Und die Ironie ist doch gerade, dass der Code in C++11 ok wäre, siehe hier http://en.cppreference.com/w/cpp/string/basic_string/operator_at den Unterschied. Du hast undefiniertes Verhalten.



  • okay...sehe ich ein...danke für den link und die Klarstellung...also kein Syntax fehler, sondern ein undefiniertes Verhalten und fehlerhaft, weil kein bound checking und "da sie außerhalb des erlaubten Bereichs auf den String zugreift".
    Bin ich voll und ganz mit einverstanden und werde es wie versprochen auch in zukünftigen projecten einhalten. Jetzt können wir die komplette Situation titulieren, aber ich würde immer noch gerne wissen, wieso es keinen fehler wiedergibt...k.p. wie ein buffer overrun, ein endlos schleife, ein compiler fehler, so was halt.
    Ist ein undefined bahavior ab C++11 "tatsächlich" fehlerhaft? oder ein Stilmittel?
    Ich betone, ich verstehe, dass ein check von der String Länge fehlt und das fehlerhaft ist.



  • Eigentlich wollte ich am Anfang nur wissen, wo der fehler in der int to string Konvertierung lag und das ist ja auch inzwischen gelöst.
    Ich habe mir auch über dieses undefinierte Verhalten fragen gestellt und dank eurer kommentare bin ich in dieser Sache einen Schritt weiter.
    Ich will es gerne richtig machen und bei zweifel mir die Fragen, die sich bei einem laufenden Programm stellen, vollständig beantworten können.
    Nochmals Danke 🙂 👍



  • @wob sorry, wegen meiner Unachtsamkeit dir mit "Syntaxfehler" zu antworten. 🙄



  • So...noch ein Versuch...reicht es, wenn ich den Check in die Kondition der FOR Schleife setze oder muss es auch in dem while statement stehen?

    Aktueller Code:

    #include <iostream>
    #include <sstream>
    using namespace std;
    
    string encode(string str)
    {
    	string encoding = "";
    	int count;
            int size;
    	size = str.size() - 1;
    
    	for (int i = 0; i < size; i++)
    	{
    		count = 1;
    		stringstream buffer;
    
    		while (str[i] == str[i + 1])
    			count++, i++;
    
                    buffer << count;
    		encoding += buffer.str() + str[i];
    	}
    
    	return encoding;
    }
    
    int main()
    {
    	string str = "ABBCCCD";
    
    	cout << encode(str);
    
    	return 0;
    }
    

    Ist das weiterhin fehlerhaft?


Anmelden zum Antworten