Gorß- und Kleinbuchstaben sowie Sonderzeichen zählen



  • Hallo erstmal.

    Ich habe folgendes Problem:
    Ich möchte eine Textdatei öffnen und alle Großbuchstaben, Kleinbuchstaben und Sonderzeichen zählen. Die Anzahlen sollen in Variable gespeichert werden. Eine Variable für Großbuchstaben eine für Kleinbuchstaben und eine für Sonderzeichen. Diese integer-Variablen müssen dann in char-Arrays konvertiert werden damit ich sie in meinem Fenster anzeigen kann.

    Um diese Aufgaben zu lösen habe ich eine Funktion geschrieben.

    char smallL[27] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','ß' };
    char bigL[26] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
    char num[10] = { '1','2','3','4','5','6','7','8','9','0' };
    char symbol[17] = { '.',',',':',';','!','?','-','_','/','*','+','%','&','$','€','µ' };
    char space = ' ';
    char CsmallL2[10];
    char CbigL2[10];
    char Cnum2[10];
    char Csymbol2[10];
    char Cspace2[10];
    int CsmallL = 0;
    int CbigL = 0;
    int Cnum = 0;
    int Csymbol = 0;
    int Cspace = 0;
    
    int CountAll(HWND hWnd, char file[256]) {
    
    	CsmallL = 0;
    	CbigL = 0;
    	Cnum = 0;
    	Csymbol = 0;
    	Cspace = 0;
    
    	memset(&letters2[0], 0, sizeof(letters2));
    	memset(&allsymb2[0], 0, sizeof(allsymb2));
    	memset(&CsmallL2[0], 0, sizeof(CsmallL2));
    	memset(&CbigL2[0], 0, sizeof(CbigL2));
    	memset(&Cnum2[0], 0, sizeof(Cnum2));
    	memset(&Csymbol2[0], 0, sizeof(Csymbol2));
    	memset(&Cspace2[0], 0, sizeof(Cspace2));
    	memset(&character[0], 0, sizeof(character));
    
    	GetWindowTextA(TBFunction5, &character[0], 256);
    
    	fi.open(file, ios::in);
    
    	if (!fi.is_open()) {
    		MessageBox(hWnd, L"Error", L"Error", MB_ICONERROR | MB_OK);
    		return -1;
    	}
    
    	for (i = 0; i <= 26; i++) {
    
    		while (fi.get(c)) {
    
    			if (c == smallL[i]) {
    
    				CsmallL++;
    
    			}
    			else if ((i <= 25) & (c == bigL[i])) {
    
    				CbigL++;
    
    			}
    			else if ((i <= 9 ) & (c == num[i])) {
    
    				Cnum++;
    
    			}
    			else if ((i <= 16) & (c == symbol[i])) {
    
    				Csymbol++;
    
    			}
    			else if (c == space) {
    
    				Cspace++;
    
    			}
    
    		}
    
    	}
    
    	letters = CsmallL + CbigL;
    	allsymb = Cnum + Csymbol;
    
    	_itoa_s(letters, letters2, 10, 9);
    	_itoa_s(allsymb, allsymb2, 10, 9);
    
    	_itoa_s(CsmallL, CsmallL2, 10, 9);
    	_itoa_s(CbigL, CbigL2, 10, 9);
    	_itoa_s(Cnum, Cnum2, 10, 9);
    	_itoa_s(Csymbol, Csymbol2, 10, 9);
    	_itoa_s(Cspace, Cspace2, 10, 9);
    
    	return 0;
    
    }
    

    Ich weiß nicht wo das Problem liegt, aber die Werte die dabei rauskommen sind falsch.
    Habe mal nachgezählt:
    Programm: 6 Kleinbuchstaben
    gezählt: 22 Kleinbuchstaben
    Programm: 0 Großbuchstaben
    gezählt: 10 Großbuchstaben

    Die Sonderzeichen stimmen auch nicht, hab die zwar nicht alle gezählt aber auch da gibt die Funktion definitiv zu wenige an.
    Leerzeichen hab ich noch nicht nachgezählt, aber das könnte ungefähr hinkommen.

    Weiß vielleicht jemand von euch woran das liegt?



  • Guck dir einfach mal deine Schleife an, und überleg dir Schritt für Schritt was die macht.
    Dann sollte dir auffallen dass, und warum, die so nicht funktionieren kann.



  • Ok. Ich schätze ich sollte die for-Schleife wohl in die while-Schleife tun.
    Hätte ich ja auch selber drauf kommen können...

    Danke jedenfalls.

    Ich habe allerdings noch ein Problem:

    Ich stelle die Werte mit einer TextOutA () in meinem Fenster dar. Das Funktioniert zwar soweit, das die Zahlen angezeigt werden aber leere Stellen im char-Array werden nicht als Leerzeichen oder gar nicht dargestellt sondern dort werden merkwürdige Symbole angezeigt. Diese Symbole sehen aus wie ein senkrechter Strich mit einer null auf der rechten Seite dran.
    Wie bekomme ich die weg bzw. wie bekomme ich raus wieviele Stellen des Array tatsächlich mit Zahlen belegt sind?



  • Habe jetzt die while-Schleife nach außen und die for-Schleife nach innen gemacht, doch aus irgendeinem Grund bekomme ich immer noch falsche Werte. Jetzt liegt der unterschied zum richtigen wert aber nur noch bei maximal 20.

    Wo könnte das jetzt dran liegen?



  • Zeig den Code wie du ihn jetzt hast. 1:1 Copy&Paste.

    Wenn du nämlich ausser die Schleifen zu vertauschen nichts geändert hast, dann ist klar dass zu viele Leerzeichen gezählt wurden.
    Auch hier: guck es dir selbst an, du wirst sicher draufkommen wieso 😉

    Und ansonsten wie gesagt nochmal den Code den du jetzt aktuell hast.

    Und auch 'was die komischen Symbole angeht: bitte Code zeigen. Anhand der Beschreibung weiss ich nicht was du meinst (also wie dein Code aussehen könnte), und zum Rätselraten bin ich gerade etwas zu faul.



  • XP schrieb:

    char smallL[27] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','ß' };
    char bigL[26] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z' };
    char num[10] = { '1','2','3','4','5','6','7','8','9','0' };
    char symbol[17] = { '.',',',':',';','!','?','-','_','/','*','+','%','&','$','€','µ' };
    

    Dafuq?

    inline bool is_upper_alpha(char character)
    {
            return (character >= 'A' && character <= 'Z');
    }
    inline bool is_lower_alpha(char character)
    {
            return (character >= 'a'  && character <= 'z');
    }
    inline bool is_number_dec(char character)
    {
            return (character >= '0' && character <= '9');
    }
    

    Wenn du die Magie dahinter nicht verstehst, schau dir mal eine ASCII-Tabelle an.
    Wie du auf 'ß' prüfst, überlass ich dir als Hausaufgabe.

    Und was die Symbole angeht:

    char symbol[] = ".,:;!?-_/*+%&$€µ";
    

    Und das Buch, mit dem du lernst, solltest du wegwerfen (ist das zufällig von Jürgen Wolf?).

    EDIT: Und ansonsten stimme ich ein in Hustbaers Bariton, wir wollen den kompletten Code sehen.



  • Lass ihn doch erstmal seine Fehler finden bevor du ihm Code gibst der seinen fehlerhaften komplett ersetzt.
    Danach, wenn er Code hat der erstmal korrekt läuft, wäre der richtige Zeitpunkt gewesen ihm zu zeigen wie man es effizienter machen kann.



  • hustbaer schrieb:

    Lass ihn doch erstmal seine Fehler finden bevor du ihm Code gibst der seinen fehlerhaften komplett ersetzt.
    Danach, wenn er Code hat der erstmal korrekt läuft, wäre der richtige Zeitpunkt gewesen ihm zu zeigen wie man es effizienter machen kann.

    Wenn er wirklich daran interessiert ist, was daraus zu lernen, dann wird er den Code eh erst mal nicht anschauen, sondern erst mal ein bestehendes Programm fixen. Was ich übrigens immer gemacht habe, und sei es, um damit kolossal auf die Fresse zu fliegen. Anders lernt man nicht. Also, anders lerne ich nicht.

    Und dann kommt er vielleicht zu der Erkenntnis, dass das alles Schrott ist - und dann hat er direkt einen Weg, wie man's besser machen kann.

    Und wenn er nicht daran interessiert ist zu lernen, dann sollten wir uns beide an die eigene Nase fassen, denn wir haben's nicht erkannt. Warum sollten wir posten, wenn wir ihn nicht für lernfähig halten?



  • Eine viel elegantere, funktionierende Lösung präsentiert zu bekommen vermindert die Motivation den eigenen Code zu fixen massiv. Vor allem wenn sie so einfach ist dass man sie versteht.
    Auch wenn man daran interessiert ist zu lernen.



  • Also,

    Ich habe versucht meine Fehler zu finden und zu entfernen aber natürlich ist der Vorschlag von dachschaden wesentlich einfacher.
    Ich habe also jetzt diesen Vorschlag verwendet und mein Programm geändert:

    int CountAll(HWND hWnd, char file[256]) {
    
    	CsmallL = 0;
    	CbigL = 0;
    	Cnum = 0;
    	Csymbol = 0;
    	Cspace = 0;
    
    	memset(&letters2[0], 0, sizeof(letters2));
    	memset(&allsymb2[0], 0, sizeof(allsymb2));
    	memset(&CsmallL2[0], 0, sizeof(CsmallL2));
    	memset(&CbigL2[0], 0, sizeof(CbigL2));
    	memset(&Cnum2[0], 0, sizeof(Cnum2));
    	memset(&Csymbol2[0], 0, sizeof(Csymbol2));
    	memset(&Cspace2[0], 0, sizeof(Cspace2));
    	memset(&character[0], 0, sizeof(character));
    
    	GetWindowTextA(TBFunction5, &character[0], 256);
    
    	fi.open(file, ios::in);
    
    	if (!fi.is_open()) {
    		MessageBox(hWnd, L"Error", L"Error", MB_ICONERROR | MB_OK);
    		return -1;
    	}
    
    	while(fi.get(c)){
    
    			if (c >= 'a' && c <= 'z') {
    
    				CsmallL++;
    
    			}
    			else if (c >= 'A' && c <= 'Z') {
    
    				CbigL++;
    
    			}
    			else if (c >= '0' && c <= '9') {
    
    				Cnum++;
    
    			}
    			else if (c == 'ß') {
    
    				CsmallL++;
    
    			}
    			else if (c == ' ') {
    
    				Cspace++;
    
    			}
    			else {
    
    				for (i = 0; i = 16;i++){
    
    					if (c == symbol[i]) {
    
    						Csymbol++;
    
    					}
    
    			}
    
    		}
    
    	}
    
    	letters = CsmallL + CbigL;
    	allsymb = Cnum + Csymbol;
    
    	_itoa_s(letters, letters2, 10, 9);
    	_itoa_s(allsymb, allsymb2, 10, 9);
    
    	_itoa_s(CsmallL, CsmallL2, 10, 9);
    	_itoa_s(CbigL, CbigL2, 10, 9);
    	_itoa_s(Cnum, Cnum2, 10, 9);
    	_itoa_s(Csymbol, Csymbol2, 10, 9);
    	_itoa_s(Cspace, Cspace2, 10, 9);
    
    	if ((character[0] == 'J') | (character[0] == 'j')) {
    
    		p = 4;
    
    	}
    	else if ((character[0] == 'N') | (character[0] == 'n')) {
    
    		p = 5;
    
    	}
    	return 0;
    
    }
    

    Doch wenn die Funktion aufgerufen wird bleibt das gesamte Programm hängen, hat aber keinen Fehler. Ich vermute das es irgendwo in einer Schleife hängenbleibt und diese nie verlässt.

    Kann mir jemand sagen wo das Problem ist?

    Zu den merkwürdigen Zeichen:

    Hier ist der Code der die Werte anzeigen soll:

    TextOutA(
    				hdc,
    				10,
    				70,
    				"kleine Buchstaben: ",
    				19);
    
    			TextOutA(
    				hdc,
    				150,
    				70,
    				CsmallL2,
    				sizeof(CsmallL));
    
    			TextOutA(
    				hdc,
    				10,
    				100,
    				"große Buchstaben: ",
    				17);
    
    			TextOutA(
    				hdc,
    				150,
    				100,
    				CbigL2,
    				sizeof(CbigL));
    
    			TextOutA(
    				hdc,
    				10,
    				130,
    				"Zahlen: ",
    				8);
    
    			TextOutA(
    				hdc,
    				150,
    				130,
    				Cnum2,
    				sizeof(Cnum));
    
    			TextOutA(
    				hdc,
    				10,
    				160,
    				"Sonderzeichen: ",
    				15);
    
    			TextOutA(
    				hdc,
    				150,
    				160,
    				Csymbol2,
    				sizeof(Csymbol));
    
    			TextOutA(
    				hdc,
    				10,
    				190,
    				"Leerzeichen: ",
    				13);
    
    			TextOutA(
    				hdc,
    				150,
    				190,
    				Cspace2,
    				sizeof(Cspace));
    

    Ich würde ja auch einen Screenshot von den Zeichen machen, aber da Das Programm hängenbleibt bevor das Fenster neu gezeichnet wird, geht das nicht.



  • for (i = 0; i = 16;i++)
    

    Schau dir mal die Schleifenbedingung an!

    PS: Und der Debugger ist ein guter Freund 😉



  • Zu den komischen Zeichen...

    sizeof(CsmallL)
    Das ist die Grösse des char-Arrays CsmallL .
    Die ist fix, und unabhängig davon wie viele Zeichen du mittels _itoa_s reingeschrieben hast.
    Hinter dem letzten "normalen" Zeichen steht bei nullterminierten Strings noch ... eine Null (und _itoa_s erzeugt nullterminierte Strings). Danach kommt dann irgendwas.

    Da du aber die gesamte Länge des Arrays an TextOutA übergibst, will TextOutA natürlich auch alle Elemente des Arrays ausgeben. Auch das Null-Zeichen und auch das was dahinter noch steht. Daher erhältst du komische Zeichen im Output.

    Tip: Eine Funktion die dir hier helfen kann ist strlen .

    Tip 2: Guck dir mal die Parameterliste von _itoa_s an. Ich gehe nämlich davon aus dass du da was machst was du eigentlich nicht willst.

    Tip 3: Wenn du sizeof schon kennst, wieso schreibst du dann die Länge der Arrays bei den _itoa_s hard-coded rein (also direkt als Zahl)? Damit erzeugst du bloss unnötige zusätzliche Fehlerquellen.



  • Ja. Da hab ich wohl ein = vergessen.....

    Danke jedenfalls für eure bisherige Hilfe! 🙂

    Hab jetzt das zweite = hinzugefügt und an sonsten nichts geändert.
    Ich bekomme aber immer noch falsche Zahlen.

    Ich benutze eine Textdatei die mal von einem Programm erstellt und gespeichert wurde zum Testen.

    Hier ist der gesamte Inhalt der Datei:

    SIW v4.4.0514e Home Edition Compiled on Jun 9 2013 15:09:46
    LOG: 2016-06-02 15:59:32
    5-2108 155932: ThreadPool.cpp-144 ThreadPool::acceptHandler Util::IsShutdown() inside acceptHandler

    Das Programm zählt jetzt:

    kleine Buchstaben: 101
    große Buchstaben: 21
    Zahlen: 50
    Sonderzeichen: 0
    Leerzeichen: 20

    Wer jetzt mal nachzählt wird feststellen, das diese Werte alle falsch sind.

    Woran liegt das?

    Und Ich hab auch noch nen Screenshot, wo die Symbole zu sehen sind, die ich mir nicht erklären kann.

    http://www.mediafire.com/view/gp8xbnhp75b75p7/Zeichen....png

    Wo kommen diese Zeichen her und wie bekomme ich sie da weg?



  • OK. Die komischen Symbole sind jetzt weg, da ich strlen() benutze.

    Die Frage nach den falschen Zahlen bleibt.



  • XP schrieb:

    Die Frage nach den falschen Zahlen bleibt.

    Dann solltest auch den aktuellen Code zeigen.



  • Der aktuelle Code:

    int CountAll(HWND hWnd, char file[256]) {
    
    	CsmallL = 0;
    	CbigL = 0;
    	Cnum = 0;
    	Csymbol = 0;
    	Cspace = 0;
    
    	memset(&letters2[0], 0, sizeof(letters2));
    	memset(&allsymb2[0], 0, sizeof(allsymb2));
    	memset(&CsmallL2[0], 0, sizeof(CsmallL2));
    	memset(&CbigL2[0], 0, sizeof(CbigL2));
    	memset(&Cnum2[0], 0, sizeof(Cnum2));
    	memset(&Csymbol2[0], 0, sizeof(Csymbol2));
    	memset(&Cspace2[0], 0, sizeof(Cspace2));
    	memset(&character[0], 0, sizeof(character));
    
    	GetWindowTextA(TBFunction5, &character[0], 256);
    
    	fi.open(file, ios::in);
    
    	if (!fi.is_open()) {
    		MessageBox(hWnd, L"Error", L"Error", MB_ICONERROR | MB_OK);
    		return -1;
    	}
    
    	while(fi.get(c)){
    
    			if (c >= 'a' && c <= 'z') {
    
    				CsmallL++;
    
    			}
    			else if (c >= 'A' && c <= 'Z') {
    
    				CbigL++;
    
    			}
    			else if (c >= '0' && c <= '9') {
    
    				Cnum++;
    
    			}
    			else if (c == 'ß') {
    
    				CsmallL++;
    
    			}
    			else if (c == ' ') {
    
    				Cspace++;
    
    			}
    			else {
    
    				for (i = 0; i == 16;i++){
    
    					if (c == symbol[i]) {
    
    						Csymbol++;
    
    					}
    
    			}
    
    		}
    
    	}
    
    	letters = CsmallL + CbigL;
    	allsymb = Cnum + Csymbol;
    
    	_itoa_s(letters, letters2, sizeof(letters2));
    	_itoa_s(allsymb, allsymb2, sizeof(allsymb2));
    
    	_itoa_s(CsmallL, CsmallL2, sizeof(CsmallL2));
    	_itoa_s(CbigL, CbigL2, sizeof(CbigL2));
    	_itoa_s(Cnum, Cnum2, sizeof(Cnum2));
    	_itoa_s(Csymbol, Csymbol2, sizeof(Csymbol2));
    	_itoa_s(Cspace, Cspace2, sizeof(Cspace2));
    
    	if ((character[0] == 'J') | (character[0] == 'j')) {
    
    		p = 4;
    
    	}
    	else if ((character[0] == 'N') | (character[0] == 'n')) {
    
    		p = 5;
    
    	}
    	return 0;
    
    }
    


  • XP schrieb:

    Hab jetzt das zweite = hinzugefügt und an sonsten nichts geändert.
    Ich bekomme aber immer noch falsche Zahlen.

    Naja "==" ist an der Stelle ja auch nicht richtig.
    Betrifft aber natürlich nur die Sonderzeichen.
    Lies dir nochmal durch wie for-Schleifen funktionieren.

    XP schrieb:

    Wer jetzt mal nachzählt wird feststellen, das diese Werte alle falsch sind.

    Also ich für mich hab jetzt keine Lust nachzuzählen.
    Kannst du nicht einen kürzeren Text verwenden?



  • Ok. Hat sich erledigt.

    Ich habe die for-Schleife jetzt geändert:

    for (i = 0; i <= 16;i++){
    
        if (c == symbol[i]) {
    
    	Csymbol++;
    
        }
    }
    

    Und jetzt sind alle Zahlen korrekt.
    Ich habe allerdings keine Ahnung warum sie falsch waren.
    Außer natürlich den Symbolen.

    Danke jedenfalls. 🙂
    Ihr habt mir sehr geholfen.


Log in to reply