alle a's in einem Text zählen



  • Du könntest auch gleich einen ganzen std::string einlesen und dann mit input.empty() schauen, ob du eine Leerzeile eingegeben hast. Das sollte weniger Probleme bereiten.

    #include <iostream>
    #include <string>
    
    int main()
    {
        std::string input;
        unsigned int counter = 0;
        std::cin >> input;
    
        if(input.empty()) cout << "hallo\n";
        else
        {
            for(size_t i = 0; i < input.size(); ++i) if(input[i] == 'a') ++counter;
            cout << "Sie haben " << counter << " mal den Buchstaben 'a' eingegeben";
        }
    }
    


  • Also. Ich bin schon auf das nächste Problem gestossen. Nun möchte ich alle a bis z in einem Text zählen. Dafür habe ich mein a-Programm etwas erweitert, voilà:

    #include <iostream>
    #include <ios>
    
    int main()
    {
      std::cin>>std::noskipws;
    
      char*const t = new char [1];
      for(char letter='a';letter<='z';++letter) 
     {
       int i=0;
       int counter=0;
       for(;;++i)
         {
           if(std::cin>>t[i])
    	 {
    	   if (t[i]==letter)
    	     {
    	       ++counter;
    	     }
    	   else if(t[i]=='\n')break; //Input zu Ende
    	 }
         }
      std::cout<<letter<<":"<<counter<<"of"<<i<<".\n";
    
    }  
    
     delete [] t; 
     return 0;
    }
    

    Das Problem: Für a gibts den richtigen Wert aus, für den Rest des Alphabets nicht mehr... Was ist falsch?

    Gruss
    Rungo



  • oder noch besser die Größe vor der Schleife berechnen, damit .size( ) nur einmal aufgerufen wird. Wer weiß, wie lang der Text wird... 😉

    size_t inputSize = input.size( );
    for(size_t i = 0; i < inputSize; ++i)
    {
        if(input[i] == 'a') ++counter;
    }
    


  • Du liest in jeder Schleife ein.
    Mein Vorschlag:

    #include <iostream>
    #include <string>
    
    int main()
    {
        std::string input;
        unsigned int counter = 0;
        std::cin >> input;
    
        if(input.empty()) cout << "hallo\n";
        else
        {
            for(char letter = 'a'; letter <= 'z'; ++letter)
            {
                for(size_t i = 0; i < input.size(); ++i) if(input[i] == letter) ++counter;
                cout << "Sie haben " << counter << " mal den Buchstaben '" << letter << "' eingegeben";
            }
        }
    }
    

  • Administrator

    Und einfach noch wegen der Vollständigkeit:

    #include <string>
    #include <iostream>
    #include <algorithm>
    
    int main()
    {
      std::string line;
      std::getline(std::cin, line);
    
      if(line.empty())
      {
        std::cout << "Hallo?\n";
      }
      else
      {
        int count = std::count(line.begin(), line.end(), 'a');
        std::cout << "Sie haben " << count << " mal den Buchstaben a eingegeben.\n"
      }
    }
    

    @Rungo,
    Gerade noch in der Vorschau gesehen. Du kannst aus dem Stream nur einmal lesen. Was du einmal gelesen hast, ist auch eingelesen. Oder meinst du ein anderes Problem? Dann präzisiere die Problembeschreibung bitte.

    Grüssli


  • Administrator

    minstaros schrieb:

    oder noch besser die Größe vor der Schleife berechnen, damit .size( ) nur einmal aufgerufen wird. Wer weiß, wie lang der Text wird... 😉

    Ein Kompiler wird das höchstwahrscheinlich selber wegoptimieren. Das sind unnötige Mikrooptimierungen.

    Grüssli



  • Moment mal... hier ist eine Universal-Statistik-Lösung:

    #include <iostream>
    #include <string>
    
    #define CHAR_MAX_VALUE (255)
    
    int main()
    {
        std::string input;
        unsigned int letter_statistics[CHAR_MAX_VALUE];
    
        //initialisieren mit 0
        for(size_t i = 0; i < CHAR_MAX_VALUE; ++i) letter_statistics[i] = 0;
    
        std::cin >> std::noskipws >> input;
    
        if(input.empty()) cout << "hallo\n";
        else
        {
            for(size_t i = 0; i < input.size(); ++i) ++letter_statistics[(int)input[i]];
            for(size_t i = 0; i < CHAR_MAX_VALUE; ++i) cout << (char)i << ": " << letter_statistics[i] << "\n";
        }
    }
    


  • @wxSkip: Du hast 2 Schleifen verschachtelt, das heißt, das Ding läuft für jeden Buchstaben 26x durch.

    Was hilft ist die Bibliothek:

    #include <cctype>
    
    ...
    
    for(  ...  )    if( islower( input[ i } ) ++counter;
    


  • minstaros schrieb:

    @wxSkip: Du hast 2 Schleifen verschachtelt, das heißt, das Ding läuft für jeden Buchstaben 26x durch.

    Was hilft ist die Bibliothek:

    #include <cctype>
    
    ...
    
    for(  ...  )    if( islower( input[ i } ) ++counter;
    

    Ich wollte auch, dass das 26 mal durchläuft, so sah das zumindest bei Rungo aus.



  • wxSkip schrieb:

    Ich wollte auch, dass das 26 mal durchläuft, so sah das zumindest bei Rungo aus.

    Du hast recht, hab mir da nur die neue "Aufgabenstellung" durchgelesen und war im Kopf noch bei der Einmal-über-alle-Input-Buchstaben-Schleife. Diese reicht ja auch aus, wenn man für jeden Buchstaben nur prüft, ob er zwischen 'a' und 'z' liegt (oder kurz eben islower( ) ).



  • minstaros schrieb:

    wxSkip schrieb:

    Ich wollte auch, dass das 26 mal durchläuft, so sah das zumindest bei Rungo aus.

    Du hast recht, hab mir da nur die neue "Aufgabenstellung" durchgelesen und war im Kopf noch bei der Einmal-über-alle-Input-Buchstaben-Schleife. Diese reicht ja auch aus, wenn man für jeden Buchstaben nur prüft, ob er zwischen 'a' und 'z' liegt (oder kurz eben islower( ) ).

    Hm, geht es um das Zählen von allen a-z (Gesamtsumme) oder um jeden Buchstaben einzeln? Im letzteren Fall ist die Statistiklösung natürlich richtig... Ich geh jetzt lieber was essen... Weiter viel Spaß! 😉



  • Hallo

    Ich melde mich auch wieder einmal zu Wort. Leider verstehe ich nicht viel von euren Vorschlägen und es ist mir bewusst, dass ich für jeden Buchstaben nochmals den ganzen Input einlese, was nicht sonderlich elegannt ist, klar. Wie könnte ich mein Programm (siehe den letzen meiner Beiträge) in dieser Form trotzdem zum laufen kriegen? Ich bin einfach daran interessiert, wo mein Fehler liegt.

    Liebe Grüsse
    Rungo



  • char*const t = new char [1];
    

    Was soll das?



  • Naja. Ich konstruiere mir ein array der Länge 1, in das ich nach und nach die Werte einlese... (Erklärung eines Anfängers). Evtl könnte man das natürlich anders lösen, aber soweit ich das richtig sehe, funktionierts...



  • Rungo schrieb:

    Naja. Ich konstruiere mir ein array der Länge 1, in das ich nach und nach die Werte einlese... (Erklärung eines Anfängers). Evtl könnte man das natürlich anders lösen, aber soweit ich das richtig sehe, funktionierts...

    Ja, aber es ist einfach unleserlich. Nimm lieber einen stinknormalen char.
    Wie ich schon geschrieben habe, liegt der Fehler daran, dass du in jeder Schleife neu die Buchstaben einliest. Was genau verstehst du an meinen beiden Programmen nicht?



  • Du benötigst irgendwas von string input und so. Irgenwie kann ich schon erahnen, wie es funktioniert, obwohl ich soetwas noch nie gesehen habe, allerdings darf ich das auch noch gar nicht benutzen, da dies eine Aufgabe für die Schule ist. Wieso funktionnierts denn nicht, wenn ich in jeder Schleife neu einlese?



  • Rungo schrieb:

    Du benötigst irgendwas von string input und so. Irgenwie kann ich schon erahnen, wie es funktioniert, obwohl ich soetwas noch nie gesehen habe, allerdings darf ich das auch noch gar nicht benutzen, da dies eine Aufgabe für die Schule ist. Wieso funktionnierts denn nicht, wenn ich in jeder Schleife neu einlese?

    OK. Dürft ihr char-Arrays, also C-Strings verwenden?
    Was gibt std::cin>>t[i] zurück?
    Wenn es tatsächlich so funktioniert wie du es willst, liest du Zeichen bis zu einem Zeilenumbruch ein und überprüfst sie auf dem Buchstaben a. Die nächste Zeile überprüfst du auf den Buchstaben b usw.



  • Hab da mal was zusammengepfuscht. Gar nicht leicht, wenn man nix hinzuverwenden darf 😃

    - Achtung: Grossbuchstaben kannst du dir selber was noch dazudenken 🙂
    - Und schau dir mal die Ascii-Tabelle an

    #include <iostream>
    
    int main()
    {
    	char input[500];
    	const char *seek = input;
    	int cntAll = 0;
    	// ein Array, weil ja jeder Buchstabe gezaehlt werden soll
    	int cntLetter[26];
    
    	// Array mit 0 vorfuellen, damit man irgendwo mit zaehlen beginnen kann
    	for(int i=0; i<26; ++i)
    		cntLetter[i] = 0;
    
    	// Text einlesen (inc Leerzeichen)
    	std::cin.getline(input, 500);
    
    	// nochmal anschauen ;)
    	std::cout << input << std::endl;
    
    	// solange loopen, bis das Terminierungszeichen \0 erreicht ist
    	while(*seek)
    	{
    		// Buchstabe nochmal ausgeben zum pruefen
    		std::cout << *seek << std::endl;
    
    		// Jeden Buchstaben zaehlen
    		cntAll++;
    
    		// Spagetti-Methode
    // ENTWEDER
    		if(*seek == 'a')
    			cntLetter[0]++;
    		if(*seek == 'b')
    			cntLetter[1]++;
    // ODER
    		// Ansonsten geht auch
    		// 'b'-'a' = 98-97 = 1 ... somit cntLetter[1] erhoehen
    		// !!Achtung index noch pruefen von 0-25
    		int index = *seek - 'a';
    		cntLetter[index]++;
    
    		// Zeiger auf den naechsten Buchstaben
    		seek++;
    	}
    
    	// Ausgabe des Zaehlergebnisses
    	for(int i=0; i<26; ++i)
    		// Buchstabe 'a' hat im Ascii-Zeichensatz die 97 ... drum 97+0=a / 97+1=b usw.
    		std::cout << static_cast<char>(i+'a') << ":" << cntLetter[i] << std::endl;
    }
    


  • @ Rungo:
    Naja, was dürft Ihr denn verwenden? Wenn Ihr in C++ schreiben sollt, sollten Standard-Typen wie string schon erlaubt sein.
    Wenn es reines C sein soll, dann mußt Du mit char[ ]-Arrays arbeiten und mit scanf( ) als Eingabe (statt cin).

    Schau Dir mal an, was cin macht: Es liest von einer Eingabe (hier Tastatur) bis zu einem Zeilenendezeichen, also der Enter-Taste. Dieses wird der darauf folgenden Variable zugewiesen. Und das hängt ab vom Typ der Variable. Wenn es also ein einzelnes char ist, wird ein Buchstabe gespeichert, wenn es ein float ist, kriegst Du eine Zahl, oder mit dem Typ string eben eine komplette Zeile.

    char buchst;
    cin >> buchst;
    
    float zahl;
    cin >> zahl;
    
    string zeile;
    cin >> zeile;
    

    Was Du vermutlich willst ist ja eine Zeile. Und mehrmals das cin für jeden Buchstaben (char) einzeln ausführen dürfte lästig werden, da Du jedes Mal Enter drücken müsstest.

    Versuche zudem die Aufgaben getrennt zu betrachten und einzeln zu lösen: Zuerst die Eingabe des Textes abschließen (in der Version 2.0 Deines Programms kommt evtl. das Feature hinzu, dass die Eingabe nicht von der Tastatur, sondern per Satellit vom Server auf dem Mond erfolgen soll... 😉 ). Als zweites dann die Auswertung mit dem Buchstabenzählen. Und für den Austausch musst Du ja die gesamte Zeile irgendwo speichern - z.B. in einem char-Array oder in einem String.


Anmelden zum Antworten