Leerzeichen komprimieren



  • Ich habe hier eine Aufgabe, in der ein Text der aus einer Datei ausgelesen wird und von jeglichen doppelten oder mehrfach nacheinander auftretenden Leerzeichen eliminiert werden soll und immer nur eins stehen bleibt.

    Bsp.: {2**Leerzeichen**und*****5*****Leerzeichen} in {2*Leerzeichen*und*5*Leerzeichen} *= Leerzeichen damit man es besser sieht was ich meine.

    #include <iostream>
    using namespace std;
    
    int main () {
    	char c;
    	while (cin.get(c)) {
    		if (c == 32) {
    			cout << c << "z" << endl;
    		}
    		else {
    			cout << c << endl;
    		}
    	}
    
    	system("pause");
    	return 0;
    }
    

    Das ist das was ich bis jetzt habe. Ich weiß aber nicht wie ich die überschüssigen Leerzeichen entferne und immer nur eins stehen lasse.
    Ich kann zwar jetzt die Leerzeichen markieren mit "z" (War nur Kontrolle für mich selber ob es die Leerzeichen überhaupt erkennt) aber wie ich es auf eins reduziere ist mir bis jetzt noch zu hoch ...

    mfg


  • Mod

    Merk dir, ob das vorherige Zeichen ein Leerzeichen war. Ist das nächste Zeichen auch eines, dann überspringst du es.



  • #include <iostream>
    using namespace std;
    
    int main () {
    	char c1, c2;
    	while (cin.get(c1), cin.get(c2)) {
    		if ((c1 == ' ') && (c2 == ' ')) {
    			cout << " ";
    		}
    		else {
    			cout << c1 << endl;
    		}
    	}
    
    	system("pause");
    	return 0;
    }
    

    Mhh, ich denke mal du meinst irgendwie so.
    Aber funzt noch nicht. Wo ist der Fehler?
    Ich muss dazusagen ich bin gerade dabei es neu zu lernen also entschuldige wenn ich länger brauche ^^



  • Du liest immer 2 Zeichen ein und vergleichst die dann.
    dh: sind beide ' ' dann gibts Du ein ' ' aus.

    Ich glaube das war nicht was Du wolltest 😉


  • Mod

    Lies die Zeichen nacheinander, nicht gleichzeitig. Sonst erwischt du immer nur, wenn zwei Leerzeichen genau an den richtigen Stellen stehen. Und bei 4 Leerzeichen nacheinander gibst du dann 2 aus, was wohl auch nicht Sinn der Sache ist. Ich dachte eher so:

    Pseudocode:

    vorheriges_zeichen_war_leerzeichen = false;
    anfang:
      lese zeichen;
      wenn zeichen == leerzeichen und vorheriges_zeichen_war_leerzeichen dann:
        tue nichts;
      anderfalls, wenn zeichen == leerzeichen dann:
        gib ein leerzeichen aus 
        vorheriges_zeichen_war_leerzeichen = true;
      andernfalls:
        gib zeichen aus
        vorheriges_zeichen_war_leerzeichen = false;
      zurück zu anfang
    


  • Das Problem was ich habe ist, das ich nicht weiß wie ich zwei Werte an zwei verschiedenen Stellen einlese.

    btw ... Diese Aufgabe ist als "leicht" klassifiziert aber bis jetzt konnte ich alle anderen Aufgaben und darunter auch als schwer klassifizierte innerhalb von 10-15min oder 30min alleine lösen. Hier sitz ich schon seit 2std und probiere mit dem vorhandenen Wissen was zu erreichen aber ich komm auf keinen grünen Zweig.
    Oder ich stehe einfach nur gewaltig auf dem Schlauch.
    Ich denke einfach, ich werde die Aufgabe erstmal sein lassen.



  • Dann liest du halt nur ein Zeichen ein und merkst dir das jeweils letzte. (ich würde ja std::unique() verwenden)



  • #include <iostream>
    using namespace std;
    
    int main () {
    	char c1, c2;
    	while (cin.get(c1)) {
    		c2 = c1;
    		if (c1 == ' ' && c2 == ' ') {
    			cout << "";
    		}
    		else {
    			if (c1 == ' ' && c2 != ' ') {
    				cout << " ";
    			}
    			else {
    				 cout << c1;
    			}
    		}
    	}
    
    	system("pause");
    	return 0;
    }
    

    Das ist das was ich habe und ich denke das hier halt nur fehlt wie ich c2 den Wert des vorherigen c1 Wertes verpasse. Also mir ist klar das

    c2 = c1
    

    falsch ist aber ich weiß auch nicht wie ich es anders machen soll.



  • Setze doch mal den Pseudocode von SeppJ um. Der ist doch schon sehr ausführlich.



  • user369 schrieb:

    Also mir ist klar das

    c2 = c1
    

    falsch ist aber ich weiß auch nicht wie ich es anders machen soll.

    Die Zuweisung ist schon richtig, nur steht sie an der falschen Stelle in der Schleife 😉



  • Ok, jetzt habe ich was gegessen und tadaaa 😃

    #include <iostream>
    using namespace std;
    
    bool c2 = false;
    
    int main () {
    	char c1;
    	bool c2 = false;
    	while (cin.get(c1)) {
    		if (c1 == ' ' && c2) {
    		}
    		else {
    			if (c1 == ' ') {
    				cout << " ";
    				c2 = true;
    			}
    			else {
    				 cout << c1;
    				 c2 = false;
    			}
    		}
    	}
    
    	system("pause");
    	return 0;
    }
    

    Aber ich bräuchte für mich zum Verständnis noch eine Erklärung warum man c2 am Anfang als Konstant false ansieht?



  • Schau mal, so geht es etwas einfacher:

    #include <iostream>
    using namespace std;
    
    int main () {
        char letztes = 'x';
        char aktuelles;
    
        while (cin.get(aktuelles))
        {
            if(!(aktuelles == ' ' && letztes == ' '))
            	  cout << aktuelles;
    
            letztes = aktuelles;
        }
    
    }
    

    zu Deiner Frage:
    c2 steht auf false, wenn das zuletzt gelesene Zeichen kein Leerzeichen war, deshalb wird es zu Programmbeginn mit false initialisiert. Im Programmablauf wird es auf true gesetzt, wenn ein Leerzeichen gefunden wurde, und wieder auf false, wenn ein anderes Zeichen gelesen wurde.



  • user369 schrieb:

    Ok, jetzt habe ich was gegessen und tadaaa 😃

    #include <iostream>
    using namespace std;
    
    bool c2 = false;
    
    int main () {
    	char c1;
    	bool c2 = false;
    	while (cin.get(c1)) {
    		if (c1 == ' ' && c2) {
    		}
    		else {
    			if (c1 == ' ') {
    				cout << " ";
    				c2 = true;
    			}
    			else {
    				 cout << c1;
    				 c2 = false;
    			}
    		}
    	}
    
    	system("pause");
    	return 0;
    }
    

    Aber ich bräuchte für mich zum Verständnis noch eine Erklärung warum man c2 als Konstant false ansieht?

    Du meinst wohl Default false? Das ist deshalb so, weil am Anfang der Eingabe ja noch keine Leertaste eingegeben wurde.

    Tipp 1: Benenne deine Variablen vernünftig
    Tipp 2: Die If-Bedingungen können SeppJ entsprechend vereinfacht werden.



  • Belli schrieb:

    Schau mal, so geht es etwas einfacher:

    #include <iostream>
    using namespace std;
    
    int main () {
        char letztes = 'x';
        char aktuelles;
        
        while (cin.get(aktuelles))
        {
            if(!(aktuelles == ' ' && letztes == ' '))
            	  cout << aktuelles;
            	  
            letztes = aktuelles;
        }
    
    }
    

    zu Deiner Frage:
    c2 steht auf false, wenn das zuletzt gelesene Zeichen kein Leerzeichen war, deshalb wird es zu Programmbeginn mit false initialisiert. Im Programmablauf wird es auf true gesetzt, wenn ein Leerzeichen gefunden wurde, und wieder auf false, wenn ein anderes Zeichen gelesen wurde.

    Ok, cool. Ich denke ich habs jetzt. 👍

    Fettes Danke an alle 🙂



  • user369 schrieb:

    Fettes Danke an alle 🙂

    Bei dir ist aber das Fett fett und nicht das Danke 😃



  • Das war ausnahmsweise mal Absicht 😉



  • Obligatorischer Verweis auf die Standardbibliothek:

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    
    bool both_spaces(char c, char d) {
      return c == ' ' && d == ' ';
    }
    
    int main() {
      std::cin.unsetf(std::ios::skipws);
      std::unique_copy(std::istream_iterator<char>(std::cin),
                       std::istream_iterator<char>(),
                       std::ostream_iterator<char>(std::cout, ""),
                       both_spaces);
    }
    

Log in to reply