buchstaben in einer datei abzählen

dev-c

Mitglied
hallo,
ich bin gerade dabei das ich ein programm schreibe, mit dem ich die einzelnen buchstaben einer datei abzählen kann. zum schluss soll ausgegeben werden, wie viele aA ... zZ in einer datei vorhanden sind. groß und klein soll zusammen gezählt werden.

Code:
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{

FILE *Datei;
int alpha[26];
alpha[0]=0;
int g=65;
int k=97;
int count=0;
char c;

Datei = fopen("test.txt", "r");

if(Datei == NULL)
{
	puts("Error");
}
else
{
	puts("Error-Free");
}

// A = 65 ... Z = 90
// a = 97 ... z = 122

while(!feof(Datei))
{
	c = fgetc(Datei);
	if (c == g || c == k)
	{
		alpha[count]++;
		g=65;
		k=97;
		count=0;
	}
	
	/*
	else
	{
		g++;
		k++;
		count++;	
	}
	*/
	
	if(feof(Datei))
	{
		puts("End of File");
		printf("%d", alpha[0]);
		printf("%d", alpha[1]);	
	}
}



    system("pause");
    return 0;
}


bis jetzt werden die aA erkannt. nur wenn ich dann die bB zählen will (das auskommentierte), dann funktioniert das nicht mehr und das programm stürtzt ab.

ich dachte mir, ich fange einfach bei aA an, erhöhe dann die buchstaben wenn es zu keiner übereinstimmung kommt und so weiter.

danke im voraus!
 
Zuletzt bearbeitet:
Hi und Willkommen bei tutorials.de,

In der while-!feof-Schleife hast du einen Denkfehler.
Wenn das Auskommentierte entkommentiert wird
prüfst du den ersten Buchstaben, ob er ein a ist. Nur, ob er a ist.
Der zweite Buchstabe wird nur auf b geprüft, der Dritte nur auf c, usw...

Wenn die Datei mehr als 26 Buchstaben hat, gibts dadurch noch zwei Probleme:
Weil z schon dran war, wird auf irgendein seltsames Zeichen geprüft.
Und beim Array, das nur 26 Plätze hat, wird auf den 27., 28. usw... zugegriffen.
Der Absturz kommt wahrscheinlich daher.

Bei jedem Dateibuchstaben müssen alle a-z durchgeprüft werden.
Geht, weil die Buchstaben hintereinander kommen, ohne Schleife.
Und eine Abfrage, ob der Dateibuchstabe überhaupt etwas zwischen a und z ist
(nicht eine Ziffer oder so) sollte auch noch rein.

Noch ein Problem:
Am Anfang müssen alle 26 Elemente von alpha auf 0 gesetzt werden (Schleife),
nicht nur eins. (Warum heißt das überhaupt alpha)?

Paar andere Sachen:

Wenn die Datei nicht geöffnet werden konnte sollte das Programm abbrechen (return).
Wenns mit einer nicht geöffneten Datei bis zum feof und fgetc kommt stürzt es sonst auch ab.

Am Schluss fehlt ein fclose. Das ist wichtig. Alles, was mit fopen geöffnet wurde...

Das if(feof) im while(!feof) ist sinnlos.
Die Zahlenausgabe kann auch nach dem kompletten while erfolgen.

Das Schema von Groß-/Kleinschreibung bei den Variablennamen sollte konstant gehalten werden.
Kein Fehler, aber kein guter Stil, wenn man manchmal groß, manchmal klein beginnt.


C++:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	FILE *datei;
	int buchstaben[26];
	int i;
	char c;

	for(i = 0; i < 26; i++)
	{
		buchstaben[i] = 0;
	}

	datei = fopen("test.txt", "r");

	if(datei == NULL)
	{
		puts("Error");
		return 1;
		/*Die Nummer beim return kann zwar auch 0 sein, aber:
			"Schön" ist es, wenn 0 dann ist, wenn alles ok war,
			sonst eine andere Nummer. Je nach Fehler eine andere.
		*/
	}
	else
	{
		puts("Error-Free");
	}

	while(!feof(datei))
	{
		c = fgetc(datei);

		if(c >= 'A' && c <= 'Z')
		{
			c = c - 'A' + 'a';
		}
		if(c >= 'a' && c <= 'z')
		{
			buchstaben[c - 'a']++;
		}
	}

	puts("End of File");
	for(i = 0; i < 26; i++)
	{
		printf("%c ist %d Mal vorgekommen.\n", 'a' + i, buchstaben[i]);
	}

	fclose(datei);
	system("pause");
	return 0;
}
So. Hab die Variablen teilweise umbenannt.
Ungetestet.

Wenns Fragen gibt, einfach schreiben :)

Gruß
 
Zuletzt bearbeitet:
vielen dank!

alpha heißt es, wegen alphabet. Ja stimmt, da habe ich die schleife vergessen.

"Nur, ob er a ist. Der zweite Buchstabe wird nur auf b geprüft, der Dritte nur auf c, usw..."
prüfe ich mit dem || nicht ob der buchstabe klein oder groß ist?

zahlen, leerzeichen etc. sind egal. es sind nur die buchstaben wichtig.
 
Doch, mit || wird schon klein und Groß geprüft, aber mit dem g++ und k++ beim else
wechselst du den Buchstaben. Immer eins weiter.

Zuerst prüfst du nur auf a, und wenn es mal kein a war, dann von dort weg nur auf b, usw...

Würde funktionieren,wenn deine Datei zB. so wäre:
aaaaaaaaaaabbbbcccccccccddddddddddddd
Aber wenns durchgemischt ist
abcdnjasdnklnkcasnkcnaksldnklaslnda
würde das nicht mehr gehn.

Code ist oben.
 
vielen vielen dank!
code funktioniert.

if(c >= 'A' && c <= 'Z') --> hier prüfst du ob es sich um eine großen buchstaben handelt

c = c - 'A' + 'a'; --> was macht diese zeile


if(c >= 'a' && c <= 'z') --> hier prüfst du ob es sich um einen kleinen buchstaben handelt

buchstaben[c - 'a']++; --> hier schreibst du den wert zum jeweiligen buchstaben, aber warum c - 'a'

wo soll das fclose hin?


edit: achso
c = c - 'A' + 'a'; --> hier werden die großen buchstaben in kleine umgewandelt
buchstaben[c - 'a']++; --> hier wird die position im array bestimmt

also ich glaube auf das wäre ich auch nach 3 tagen noch nicht gekommen ;)
 
Zuletzt bearbeitet:
schäm.
Das fclose hab ich selbst vergessen :D
Ist jetzt im Code oben dabei, drittletzte Zeile.


Zur ersten Frage:
Ja, da wird geprüft, ob es ein Großbuchstabe ist.
Wenn ja, wird er in einen Kleinbuchstaben umgewandelt.
Du weißt ja, dass A 65 und a 97 ist.
B 66, C 67 ... b 98, c 99...

Und wenn ich jetzt zB. ein großes C in ein kleines c ändern will,
kann ich von 67 zuerst ein A 65 wegrechnen, =2
und dann ein a 97 dazuzählen =99 = c
Also immer minus 65, plus 97
Wenn ich einfach +32 schreiben würde, wäre es auch gleich.

Warum ich eigentlich einen Kleinbuchstaben haben will?
Das nächste if (mit Inhalt) berücksichtigt nur Kleinbuchstaben.
Wenn ich das auch noch für Großbuchstaben machen würde, würde es auch gehen.
Aber hier mach ich Große eben zuerst zu kleinen. Kleine bleiben klein.
Dann hat man in jedem Fall Kleine.


Zweite Frage:
Das if ist, um Ziffern etc. zu ignorieren.

Und das -'a': Wieder Buchstabenrechnerei:
Das Array geht von [0] für a bis [25] für z.
In c gehts aber bei 97 los...also minus 97.

Gruß
 
(Einfach casten, wie in der anderen Schleife oben.
(float)buchstaben[i]
Aber das hast da wahrscheinlich selber grad gemerkt, weil der Text jetzt ja weg ist :D)


Zu den Farben:
Zurzeit hast du den Code in sowas:
[code]...[/code]

Für verschiedene Sprachen gibt es statt code eigene Kürzel,
für C++ (und C) geht "cpp"
[code=cpp]...[/code]

Weil es doch einige Sprachen sind, gibts nicht für jede einen eigenen Button im Editor,
muss händisch eingegeben werden.
Eine Liste findest du im Codetags-Link in meiner Signatur.

Gruß
 
ich hatte (float)buchstaben[i] gemacht, nur es ging trotzdem nicht.
bin dann drauf gekommen, dass ich bei der ausgabe der zahl immer noch %d statt %f hatte...

habe das jetzt aber ohne cast gemacht. kann es sein, dass es gar kein problem ist wenn ich eine int und eine float zahl verrechne, das ergebnis ist dann einfach in float - oder?


jetzt noch eine frage: wenn ich mein programm über die command line mit einem parameter aufrufen will, wie muss ich das machen?
ich habe zB ein prim factor tool geschrieben. wenn ich es mit einem fix wert starte, dann geht alles, möchte ich aber das programm (prim.c) mit prim 53 aufrufen, so kommt immer 2 raus.
was mache ich da falsch?

C++:
#include <stdio.h>
#include <stdlib.h>
 
// int main(int argc, char *argv[])
int main(void)
{
	
    // int zahl = 0;
    // zahl = atoi(argv[1]);
	
	int zahl = 53;
	int fac = 2;
	
	if (zahl == fac)
	{
		printf("%d\n\n", zahl);
    }
     
    if (zahl != fac)
    {
		while (zahl % fac != 0)
        {
			fac++;
          
            if(zahl - fac == 0)
            {
				printf("%d\n\n", fac);
                return 0;
            }
        }
         
                  
        while (zahl % fac == 0)
        {
			zahl=zahl/fac;
            printf("%d * ", fac);
               
            while (zahl % fac != 0)
			{
				fac++;
            }
               
               
            if(zahl - fac == 0)
            {
				printf("%d", fac);
				break;    
            }             
        }

        printf("\n\n");
    }
     
system("pause");
return 0;
}

weiters:
muss ich main(int argc, char *argv[]) und anschließend zahl = atoi(argv[1]); schreiben, oder könnte ich sagen:
main(int argc, int *argv[]) und anschließend zahl = argv[1];

atoi ist ja dafür, dass ich char in zahlen umwandle oder?
 
ich hatte
Code:
(float)buchstaben[i]
gemacht, nur es ging trotzdem nicht.
bin dann drauf gekommen, dass ich bei der ausgabe der zahl immer noch %d statt %f hatte...
Ah so.
Ja, %d geht nur für int-Zeug, keine Kommazahlen.

habe das jetzt aber ohne cast gemacht. kann es sein, dass es gar kein problem ist wenn ich eine int und eine float zahl verrechne, das ergebnis ist dann einfach in float - oder?
Kann natürlich auch kein Problem sein. Hängt auch teilweise vom Compiler ab usw.,
was selber gecastet werden muss. Wenn es irgendwo ohne Cast problematisch werden könnte
bekommt man sowieso (im Normalfall) eine Warnung vom Compiler.

Wenn man sich nicht sicher ist, schaden ein paar Casts zuviel jedenfalls nicht.

jetzt noch eine frage: wenn ich mein programm über die command line mit einem parameter aufrufen will, wie muss ich das machen?
Die Sache mit argc/argv schaut in Ordnung aus (nur auskommentiert sollte sie natürlich nicht sein).
Mach am main-Anfang mal testweise das:
C++:
printf("argc=%d\n", argc);
if(argc > 1)
    puts(argv[1]);
was da ausgegeben wird.

Wie genau übergibst du den CMD-Parameter?

weiters:
muss ich main(int argc, char *argv[]) und anschließend zahl = atoi(argv[1]); schreiben, oder könnte ich sagen:
main(int argc, int *argv[]) und anschließend zahl = argv[1];
= geht nicht.
zahl ist eben eine Zahl, und argv[1] ist ein Char-Array.
Wenn da 10000 Buchstaben drin wären, wie sollen die unverändert in eine Zahl rein?

atoi ist ja dafür, dass ich char in zahlen umwandle oder?
Ja (nur...es ist ein char-Array. Ein einzelner char wäre nur ein einzelner Buchstabe/Ziffer).
So ein Buchstabenhaufen wie '1' '7' '4' wird in ein int=174 umgewandelt.
Es gibt mehrere Methoden, um das zu erreichen, atoi ist eine davon.

Bitte etwas mehr auf Netiquette 15 achten. Danke.
 

Neue Beiträge

Zurück