Buchstaben zählen



  • Hallo

    Ich bin noch ein Neueinsteiger in Sachen programmieren und habe mal eine Frage.

    Ich will bei diesem Programm, dass das Programm zählt wie viele 'a' in diesem Text enthalten sind. Es funktioniert leider nur beim ersten wort, nach einem Leerzeichen zählt er es nicht mehr.

    Wer kann mir helfen? 🙂

    int main()
    {
    
        char text[199];
        int i=0,a=0;
    
        gets(text);
    
        while (text[i]!='\0')
        {
    
            if (text[i]=='a')
            {
    
                a++;
            }
    
            i++;
        }
    
        cout<<a;
    }
    


  • Milanfan schrieb:

    Ich bin noch ein Neueinsteiger in Sachen programmieren und habe mal eine Frage.

    dann solltest du dir als erstes std::string ansehen. Wesentlich komfortabler als "char[199]".



  • Funktioniert doch...

    http://ideone.com/LwZYnz


  • Mod

    gets ist gefährlich und sollte niemals benutzt werden. Außerdem ist es C (da gilt die Gefahr aber auch!) und nur aus Kompatibilitätsgründen noch mit in C++. Nutz string und getline (die Version für strings!).

    Den Rest deines Problems kann ich nicht nachvollziehen, es funktioniert wunderbar mit Leerzeichen:
    http://ideone.com/t9q9Pg

    Eine wesentlich flexiblere Lösung als alle Buchstaben einzeln zu zählen wäre ein Array, bei dem die Indizes die Buchstaben 'a' bis 'z' repräsentieren. Oder die ultimative Lösung eine map<char, int> , mit der dann jede Art von Zeichen gezählt werden kann (Beim Array von 'a' bis 'z' macht man sich nämlich zunutze, dass in jeder gängigen Zeichencodierung 'a' bis 'z' aufeinander folgen. Das gilt bei anderen Zeichen nicht mehr unbedingt.).



  • SeppJ schrieb:

    Oder die ultimative Lösung

    ... ist std::count.

    std::cout << std::count(std::istreambuf_iterator<char>(std::cin),
                            (std::istreambuf_iterator<char>()), 'a') << '\n';
    

    (ungetestet)



  • SeppJ schrieb:

    Oder die ultimative Lösung eine map<char, int> , mit der dann jede Art von Zeichen gezählt werden kann

    Um jede Art von Zeichen zu zählen nimmt man

    char counting_c_array[std::numeric_limits<unsigned char>::max()];
    

    <


  • Mod

    ultimatief schrieb:

    std::cout << std::count(std::istreambuf_iterator<char>(std::cin),
                            (std::istreambuf_iterator<char>()), 'a') << '\n';
    

    (ungetestet)

    Zählt nur 'a's. Das ist nicht ultimativ, sondern das Gegenteil.

    ultimatief schrieb:

    SeppJ schrieb:

    Oder die ultimative Lösung eine map<char, int> , mit der dann jede Art von Zeichen gezählt werden kann

    Um jede Art von Zeichen zu zählen nimmt man

    char counting_c_array[std::numeric_limits<unsigned char>::max()];
    

    <

    Und wenn ein wchar vorliegt mit Maximum 2^64? Wem map nicht passt, der nehme unordered_map.



  • SeppJ schrieb:

    Zählt nur 'a's. Das ist nicht ultimativ, sondern das Gegenteil.

    Ist genau das Geforderte in ultimativer Kurzheit. Man kann jedes Problem unendlich verallgemeinern, nur ist das weder sinnvoll noch ultimativ.

    SeppJ schrieb:

    Und wenn ein wchar vorliegt mit Maximum 2^64? Wem map nicht passt, der nehme unordered_map.

    Falls ein char vorliegt sollte diese Variante geschätzt um Faktor 1000 schneller sein.
    Und falls wchar_t vorliegt ändere ich den Typ halt auf unordered_map. Weil das Interface gleich bleibt ist das die einzige Änderung; da du auch das Interface ändern musst ist deine Variante genauso gleich unultimativ.


  • Mod

    ultimatief schrieb:

    Falls ein char vorliegt sollte diese Variante geschätzt um Faktor 1000 schneller sein.

    Bei mir Faktor 8. Ok, das ist nicht gut. Dafür ist der Code eben ohne Änderung für alle Fälle passend. Selbst wenn man anfängt Wörter statt Buchstaben zu zählen.

    Ja, das braucht man nicht unbedingt und der TE schreibt nur vom 'a'. Hier ist das berühmte zwischen den Zeilen lesen angesagt, dass das eine typische Schulaufgabe ist und wie wohl Aufgabe b) lauten wird.

    P.S.: Ganz zu schweigen, was passiert, wenn du nicht aufpasst und einen signed char als Index benutzt.



  • SeppJ schrieb:

    Bei mir Faktor 8. Ok, das ist nicht gut.

    Ist zu wenig, bei mir ist es über Faktor 10.

    std::ios_base::sync_with_stdio(false);
    #ifdef SEPPJ
      std::map<unsigned char, unsigned> counting;
    #else
      unsigned counting[1+(int)std::numeric_limits<unsigned char>::max()] = {};
    #endif
      std::for_each(std::istreambuf_iterator<char>(std::cin),
                    std::istreambuf_iterator<char>(),
                    [&](char c){++counting[static_cast<unsigned char>(c)];});
    #ifdef PRINT_IT
      for (int i=0; i<=std::numeric_limits<unsigned char>::max(); ++i)
        std::cout << i << ": " << counting[i] << '\n';
    #endif
    

  • Mod

    unordered_map habe ich genommen.



  • Ich verfolge den Thread hier auch als Anfänger, ich glaube mit den Lösungen außerhalb von string und char überfordert ihr ihn (also mich zumindest). 😉



  • Anonymus42 schrieb:

    Ich verfolge den Thread hier auch als Anfänger, ich glaube mit den Lösungen außerhalb von string und char überfordert ihr ihn (also mich zumindest). 😉

    Wenn du meinst, die Motivation der Leute hier wäre den Anfängern die für sie bestmöglichen Antworten zu liefern, dann hast du Foren falsch verstanden.



  • Jemand Lust auf eine Runde Golf?

    int n=0,c;for(;(c=getchar())-EOF;n+=!(c-'a'));printf("%d\n",n);
    
    int n=0,c;for(;c-EOF;c=getchar())n+=!(c-'a');cout<<n<<'\n';
    
    int n=0;for(char c;cin.get(c);n+=!(c-'a'));cout<<n<<'\n';
    
    cout<<count<istream_iterator<char>>(cin,{},'a')<<'\n';
    


  • SeppJ hat doch in seinem ersten Post auf ideome verwiesen, wo der korrigierte Code steht. Danach werden weitere Lösungen angeboten, zu denen man sich die Details in Ruhe anschauen und diese nachlesen kann. Der Tipp sich erstmal richtig std::string anzuschauen, ist wohl sicher auch nicht der schlechteste.

    Also ich sehe nicht, wie hier in dem Thread anfänger-unfreundlich umgegangen wurde. Milanfan hat sich ja auch noch nicht wieder gemeldet.



  • kassandra schrieb:

    Anonymus42 schrieb:

    Ich verfolge den Thread hier auch als Anfänger, ich glaube mit den Lösungen außerhalb von string und char überfordert ihr ihn (also mich zumindest). 😉

    Wenn du meinst, die Motivation der Leute hier wäre den Anfängern die für sie bestmöglichen Antworten zu liefern, dann hast du Foren falsch verstanden.

    nein, es gibt genügend Foren, wo Anfänger nicht mit (für sie) viel zu komplizierten Lösungen zugeballert werden.

    In diesem Forum gibt es leider einige selbstdarsteller, die sehr gerne zeigen, was für geile Hack0r sie sind und die sich selbst für die Größten halten, wenn sie möglichst komplizierten und nur schwer verständlichen Template-Code schreiben können.

    In diesem Thread ist das noch harmlos, das finde ich jetzt nicht so schlimm.

    Bitte nicht falsch verstehen: Ich finde es gut, dass bei "einfache" Fragen auch fortgeschrittene Lösungen angeboten werden. Aber einem Anfänger kommentarlos irgendwas Unleserliches hinzuklatschen geht einfach nicht.



  • kassandra schrieb:

    Anonymus42 schrieb:

    Ich verfolge den Thread hier auch als Anfänger, ich glaube mit den Lösungen außerhalb von string und char überfordert ihr ihn (also mich zumindest). 😉

    Wenn du meinst, die Motivation der Leute hier wäre den Anfängern die für sie bestmöglichen Antworten zu liefern, dann hast du Foren falsch verstanden.

    Naja, Foren sind zum diskutieren, austauschen und helfen da (hier ja speziell zum helfen). Das war ja auch nicht böse gemeint, aber wozu denn Anfänger mit Dingen überfordern, die sie noch nie gesehen haben? Das ist dann auch teilweise schwer nachzuvollziehen.


Anmelden zum Antworten