ungelöst: Zeichen auslesen, getchar(), 3 Fragen von Neuling



  • Hallo! (aktuelle Fragen siehe letzter Post)

    Ich arbeite gerade das Buch "C lernen in 21 Tagen" durch und bin bei Tag 13. Hier muss ich aus einer .txt Datei die Zeichen auslesen lassen und das Programm soll mir die Häufigkeit der einzelnen Buchstaben als Statistik ausgeben. Ich hoffe ich trete hier niemand auf den Schlipps wenn ich einfach den Code so reinstelle, denn mein Anliegen ist nicht, eine andere Lösung zu finden, sondern zu erfragen, warum mein Code so nicht funktioniert. Ich arbeite mit Linux, alles funktioniert über die Konsole und wenn ich das Programm starte, via Umleitung den Inhalt einer Datei einbinde (.txt-Datei) kriege ich nur Leerzeilen. Es muss etwas kleines sein, da in einer älteren Version das Programm einzeilig funktioniert hat. Hier ist ein Fragment.

    /* Schreiben Sie ein Programm, das via Umleitung den Inhalt einer Datei einliest und zählt, wie oft jeder Buchstabe
    in der Datei vorkommt. Als Ergebnis soll das Programm eine Statistik auf den Bildschirm ausgeben. */
    
    #include <stdio.h>
    
    #define MAX 1000
    
    int main (void)
    {
    	int z[54];
    	int ctr;
    	int i;
    
    	/* Alle Array-Elemente werden mit 0 initialisiert */
    
    	for (i = 0; i <= 54; i++)
    		z[i] = 0;
    
    	/* Tausend Zeichen werden abgezaehlt und je nach Buchstabe wird der entsprechende Zaehler um 1 erhoeht. */
    
    	for (ctr = 0; ctr <= MAX; ctr++)
    	{
    		switch ( getchar() )
    		{
    			case '\n':	{ continue; }
    			case 'a':	{ z[1] += 1; continue; }
    		}
    	}
    
    	printf("Das kleine a kam %d mal vor: \t", z[1]);
    
    	return 0;
    }
    

    Ich hoffe mir kann jemand helfen. Dies ist auch mein erster Beitrag, ich hoffe diese Art Fragestellung hier ist OK. Vielen Dank 🙄 😉



  • Deine erste for-Schleife wird 55 mal ausgeführt, Du hast aber nur 54 Elemente angelegt.

    for (i = 0; i < 54; i++) // ohne =
    

    Das gleiche gilt für die 2. for-Schleife!

    Einen Zweig im switch-case-Konstrukt beendet man eigentlich mit break statt mit continue.



  • hi!

    erstmal danke, du hast recht.
    aber ich will ja nicht, dass die schleife komplett abgebrochen wird, sondern dass er weiter ein zeichen einliest und je nach buchstabe den wert des betroffenen array-elementes erhöht. so dass wenn z.b. in einer .txt-datei 20 mal der buchstabe "a" vorkommt, das programm am ende für den wert z[1] = 20 hat. am schluss soll er mir dann angeben, dass der buchstabe "a" z[1]-mal vorgekommen ist.



  • Das break sorgt nur dafür, dass der nachfolgende Code im switch-case-Block nicht ausgeführt wird. Die for-Schleife wird in diesem Fall davon nicht beeinflusst.



  • Hi,

    deine for-Schleife zum Initialisieren von z[] läuft eine Stelle zu weit:

    int z[54], i;
        for (i=0; i<54; ++i) z[i] = 0;
    

    Den gleichen Fehler machst du in deiner zweiten for-Schleife. Du liest
    1001 Zeichen ein.

    Im switch-Block verlässt man die einzelnen cases mit break, anstelle von
    continue. Ein continue bewirkt, dass der nächste Schleifendurchlauf
    gestartet wird. Ein break würde hier zum Ende des switch-Blocks springen.

    Du solltest ebenfalls noch ein default-State einführen, damit das Programm
    weiß, was es mit Zeichen machen soll, die nicht gelistet sind.

    for (ctr = 0; ctr < MAX; ctr++)
        {
            switch ( getchar() )
            {
                case '\n':    break;
                case 'a':     z[1] += 1; break;
                default:      break;
            }
        }
    

    Gruß mcr

    EDIT: wurde schon MiP alles gepostet.



  • danke, jetzt funktionierts einwandfrei! *stolz*
    erstes größeres noob-programm ohne lösung für einen noob 😉

    aber drei fragen noch:

    1. macht eine continue-anweisung in einem swich-block überhaupt sinn?
    2. was macht die for-schleife, wenn sie mehr elemente initialisieren soll, als das array überhaupt hat? bzw. wieso gibt mir mein compiler keinen fehler bzw. ist sowas schlimm?
    3. wie kann ich es bewerkstelligen, dass ich mich nicht auf 1000 zeichen beschränke, sondern er einfach bis zum ende der datei durchliest (ich kenne noch keinen befehl oder mechanismus, wie das funktionieren soll, jedenfalls ist mir nichts bekannt).

    edit: weiß das denn grad keiner 😉 ? wäre super, wenn grad jemand ganz kurz zeit hätte, mir das zu beantworten 😉 danke!



  • Hallo,

    zu 1: kann Sinn machen, stelle dir vor, nach dem switch stehen noch weitere, viele, und eventuell sogar "zeitraubende" Anweisungen, da ist es doch gut, dass man die übergehen kann.

    zu 2: das ist einer der "kritischen" Punkte, wenn man C programmiert, man ist selbst dafür verantwortlich, aufzupassen, nicht über Array-Grenzen hinweg zuzugreifen. Der Compiler hilft hier nicht, es kann sich so verhalten, wie ich es hier:

    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1547571.html#1547571

    beschrieben habe.

    zu 3: in (d)einer Dokumentation zu den Funktionen der C-Laufzeitbibliothek wirst du finden, dass getchar den (speziellen) Wert EOF zurückgeben kann, der auf einen Fehler oder das Dateiende hinweist, den kannst du auswerten bzw. so behandeln, dass die Schleife abbricht.

    MfG,

    Probe-Nutzer


Anmelden zum Antworten