alle a's in einem Text zählen



  • Hallo miteinander

    Folgende Aufgabe möchte ich lösen: Ich habe einen Text als Input und möchte in diesem Text nun alle Buchstaben a zählen. Nun habe ich mal "ganz klein" begonnen und möchte entscheiden, wenn ich einen Buchstaben eingebe, ob dieser ein a ist oder nicht. Wenns kein Element im Input hat, dann möchte ich, dass das Programm "hallo" ausgibt. Dazu habe ich auch mal ein Programm geschrieben, voilà:

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

    So. Nun zum Problem: Wenn ich nichts als Input "reingebe", dann gibt mir das Programm nicht "hallo" aus.... Warum ist mir ein Rätsel...Wisst ihrs?

    Vielleicht ein kleiner Hinweis: Ich bin ein absoluter Anfänger. Vor zwei Monaten wusste ich nicht einmal was C++ ist...

    Liebe Grüsse
    Rungo



  • Mein Tipp: Dein else sollte für die innere if gelten und nicht für die äußere.

    Meinst du nicht, dass es etwas übertrieben ist, wegen einem Buchstaben auf dynamische Speicherverwaltung zurückzugreifen? 😃



  • Ich glaube: Dein else ist schon richtig.

    Du weisst halt nicht, wann std::cin>>t[i] false liefert. Bei einem Enter müsste in t[i] '\n' stehen, bei einem C-d (Linux) oder Strg-Z (imho Windows) hingegen müsste hallo ausgegeben werden.



  • Hallo

    Also. Ich habe mal den Tipp mit dem else in die Tat umgesetzt und dann mal keinen Input reingegeben und natürlich kam das "hallo" auch sofort raus. Das Problem ist, wenn ich nun "b" eingebe kommt das "hallo" auch raus, was ich nicht will. Und die Antwort (sei mir nicht böse) von dir, gnuro, verstehe ich nicht wirklich...

    Gruss
    Rungo



  • Darf ich mal nachfragen, wie du als Anfänger in C++ "keinen Input" eingibst?
    Vielleicht reden wir alle aneinander vorbei



  • Also: Ich gebe in der Konsole einfach nichts ein und drücke auf enter...



  • Das hat ja gnuro bereits beantwortet. Auch Enter ist ein Input und somit steht bei dir '\n' drin. Wenn du bei diesem Zeichen die Ausgabe hallo haben möchtest, dann musst du diese explizit in einem if abfragen:

    std::cin>>t[i];
    
    	if (t[i]==letter)
    	{
    		++counter;
    	}
    	else if(t[i] == '\n')
    	{
    		 std::cout<<"hallo"; //Kein Input
    	}
    


  • Und es funktionniert. Merci für die schnelle Hilfe 🙂



  • 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


Anmelden zum Antworten