# buchstaben in einer datei abzählen



## dev-c (3. April 2012)

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.


```
#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!


----------



## sheel (4. April 2012)

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.



```
#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ß


----------



## dev-c (4. April 2012)

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.


----------



## sheel (4. April 2012)

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.


----------



## dev-c (4. April 2012)

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


----------



## sheel (4. April 2012)

schäm.
Das fclose hab ich selbst vergessen 
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ß


----------



## dev-c (4. April 2012)

btw: wie kriege ich die korrekten syntax farben hin?


----------



## sheel (4. April 2012)

(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 )


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ß


----------



## dev-c (4. April 2012)

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?


```
#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?


----------



## sheel (4. April 2012)

dev-c hat gesagt.:


> ich hatte
> 
> 
> 
> ...


Ah so.
Ja, %d geht nur für int-Zeug, keine Kommazahlen.



dev-c hat gesagt.:


> 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.



dev-c hat gesagt.:


> 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:

```
printf("argc=%d\n", argc);
if(argc > 1)
    puts(argv[1]);
```
was da ausgegeben wird.

Wie genau übergibst du den CMD-Parameter?



dev-c hat gesagt.:


> 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?



dev-c hat gesagt.:


> 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.


----------



## dev-c (5. April 2012)

ja alles klar, ich dachte wenn ich für cmd mein programm aufrufe, dass dann das .c file ausgeführt wird... mein fehler. hatte zwar den c coce geändert, aber vergessen das ich ein neues exe file erstelle.

was mir jetzt aber noch auffällt, wenn ich jetzt mein prim factor tool starte, also nur die exe (keinen parameter übergebe), dan wird mir endlos  2*2*2*2... ausgegeben.
ich denke das hängt mit dem fac = 2 zusammen. kann ich das noch irgendwie abstellen?


----------



## sheel (5. April 2012)

Hast du am Anfang eine Überprüfung drin, ob es argv[1] überhaupt gibt?
(also ob ein Parameter übergeben wurde?)


```
if(argc < 2)
{
    printf("Kein Parameter\n");
    return 0; //Programmende
}
```

Zur Erklärung:
argc hat die Anzahl der Parameter in argv.
Wenn es zB. 2 ist, gibts argv[0] und argv[1],
wobei argv[0] immer der Dateiname vom Programm ist, egal wieviel Parameter.
Für einen Param + Programmname muss argc also 2 sein.
Wenn <2 Ende


----------



## ibafluss (5. April 2012)

Überprüfe ob argc > 1. Wenn nicht, wurden keine Kommandozeilenparameter übergeben.

Lg


----------



## dev-c (5. April 2012)

soweit so gut! läuft alles!
auch wenn ich einen dateinamen übergebe (für das buchstaben zähl toll)


```
int main(int argc, char *argv[])
...
datei = fopen(argv[1], "r")
```


----------



## saftmeister (5. April 2012)

Nur mal so nebenbei: C hat diese wundervollen Funktionen wie isalpha(), isdigit() oder isalnum. Vorteile dieser Funktionen: sie funktionieren mit Locales.


----------



## dev-c (13. Mai 2012)

Hallöchen,
Hier bin ich wieder mal. Ich möchte mein Progi etwas erweitern (relative Häufigkeit / sortieren / Buchstaben tauschen).

Was mach mein Programm im Moment:
1) Zählt die Buchstaben in einem .txt File
2) Bestimmt die relativen Häufigkeiten
3) "sollte" diese dann absteigend sortieren (funktioniert leider nicht ganz)

Probleme:
1) Irgend etwas stimmt bei meinem Bubble-Sort nicht - nur was?


```
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char *argv[])
{
    FILE *datei;
    float buchstaben[26][3];
    int i, j, temp;
    char c;
    float t=0;
    
    const int laenge = 26;		// for bubble-sort
    int sortiert = 0;			// for bubble-sort
 
    for(i = 0; i < 26; i++)
    {
		for(j = 0; j < 3; j++)
		{
				buchstaben[i][j] = 0;
		}
		buchstaben[i][0]='a'+i; 
    }
 
    datei = fopen(argv[1], "r");
 
    if(datei == NULL)
    {
        puts("Error");
        system("pause");
        return 1;					// 1 bei fehler; 0 bei alles OK
    }
    else
    {
        // puts("Error-Free");
    }
 
    while(!feof(datei))
    {
        c = fgetc(datei);
 
        if(c >= 'A' && c <= 'Z')
        {
            c = c - 'A' + 'a';		// große buchstaben in kleine umwandeln
        }
        if(c >= 'a' && c <= 'z')
        {
            buchstaben[c - 'a'][1]++;	// position im array bestimmten und buchstaben raufzählen
        }
    }
     
    // puts("End of File");
    
	for(i=0; i<26; i++)
    {
		t=t+buchstaben[i][1];
	}
	
	for(i=0; i<26; i++)
    {
		buchstaben[i][2]=buchstaben[i][1]*100/t;	// prozent berechnen
	}
	
	// bubble-sort
	while(sortiert == 0)
	{
		sortiert = 1;
		
		for(i = 0; i < laenge-1; i++)
		{
			if(buchstaben[i][3] > buchstaben[i+1][3])
			{
				sortiert = 0;
				
				int temp = buchstaben[i][3];
				buchstaben[i][3] = buchstaben[i+1][3];
				buchstaben[i+1][3] = temp;
			}
		}	
	}
		
    for(i = 0; i < 26; i++)
    {
		printf("%c\t %.0f\t %.3f%%\n", (char)buchstaben[i][0], buchstaben[i][1], buchstaben[i][2]);
    }
 
 	fclose(datei);
    system("pause");
    return 0;
}
```


Danke schon mal und nen schönen Sonntag!


----------



## sheel (13. Mai 2012)

a)
Warum machst du ein float-Array?
Ein struct wäre da sinnvoller.


```
struct probuchstabe
{
    char buchstabe;
    int anz;
    float prozent;
};
```


----------



## dev-c (13. Mai 2012)

jetzt stehe ich aber gerade auf der Leitung, wenn ich jetzt ein struct habe, wie befülle ich das?
sind das in der struct dann alles arrays? 
wenn ich dann ein array sortieren möchte, wie schaffe ich das, dass die restlichen Einträge mit sortiert werden?

edit: wäre das dann so:


```
struct probuchstabe
{
    char buchstabe;
    int anz;
    float prozent;
};

struct probuchstabe werte[26];

int main(void)
{
werte[0]. buchstabe = a;
werte[0]. anz = 234;
werte[0].prozent = 12;
}
```


----------



## sheel (13. Mai 2012)

Ja, so ungefähr.
Etwas ausgebessert:

```
struct probuchstabe
{
    char buchstabe;
    int anz;
    float prozent;
};
 
int main(void)
{
    struct probuchstabe werte[26];
    werte[0].buchstabe = 'a';
    werte[0].anz = 234;
    werte[0].prozent = 12.0;
}
```

Beim sortieren:
Man kann einfach ein ganzen struct kopieren:

```
werte[3] = werte[4];
//usw...
```

Kannst du die Buchstabenzählerei mal auf das struct (mit anz für die Anzahl) umstellen?


----------



## dev-c (13. Mai 2012)

Habe den Code jetzt angepasst. Nur jetzt läuft irgendwie nichts mehr. Es sieht alles etwas komisch aus. Was habe ich falsch gemacht?



```
#include <stdio.h>
#include <stdlib.h>

struct probuchstabe
{
    char buchstabe;
    int anz;
    float prozent;
};
 
int main(int argc, char *argv[])
{
    FILE *datei;
    float buchstaben[26][3];
    int i, j;
    char c;
    float t=0;
    
    const int laenge = 26;		// for bubble-sort
    int sortiert = 0;			// for bubble-sort
    
    struct probuchstabe werte[26];
    struct probuchstabe temp[1];
    
    for(i = 0; i < 26; i++)
    {
		werte[i].buchstabe = 'a'+i;
    	werte[i].anz = 0;
    	werte[i].prozent = 0.0;
    }
    
    temp[i].buchstabe = 'a';
    temp[i].anz = 0;
    temp[i].prozent = 0.0;
		
    datei = fopen(argv[1], "r");
 
    if(datei == NULL)
    {
        puts("Error");
        system("pause");
        return 1;					// 1 bei fehler; 0 bei alles OK
    }
    else
    {
        // puts("Error-Free");
    }
 
    while(!feof(datei))
    {
        c = fgetc(datei);
 
        if(c >= 'A' && c <= 'Z')
        {
            c = c - 'A' + 'a';		// große buchstaben in kleine umwandeln
        }
        if(c >= 'a' && c <= 'z')
        {
			werte[c - 'a'].anz++;		// position im array bestimmten und buchstaben raufzählen	
        }
    }
     
    // puts("End of File");
    
	for(i=0; i<26; i++)
    {
		t=t+werte[i].anz;
	}
	
	for(i=0; i<26; i++)
    {
		werte[i].prozent=werte[i].anz*100/t;	// prozent berechnen
	}
	
	// bubble-sort
	while(sortiert == 0)
	{
		sortiert = 1;
		
		for(i = 0; i < laenge-1; i++)
		{
			if(werte[i].prozent < werte[i+1].prozent)
			{
				sortiert = 0;
				
				temp[1] = werte[i];
				werte[i] = werte[i+1];
				werte[i+1] = temp[1];
			}
		}	
	}
		
    for(i = 0; i < 26; i++)
    {
		printf("%c\t %d\t %.3f%%\n", werte[i].buchstabe, werte[i].anz, werte[i].prozent);
    }
 
 	fclose(datei);
    system("pause");
    return 0;
}
```


----------



## sheel (13. Mai 2012)

a) Hier:

```
struct probuchstabe temp[1];
```
brauchst du kein Array

```
struct probuchstabe temp;
```

b) Du musst die 26 structs zuerst initialiseren.
anz auf 0 setzen und beim Buchstaben was eintragen.

c) Beim Hochzählen nicht buchstabe, sondern anz mit ++ erhöhen.

d) Bei der Prozentberechnung zuerst in float casten, sonst gibts ein Kommastellenproblem.

e) Beim Sort - wenn schon - temp[0] nehmen.
Aber wie gesagt, es muss kein Array sein.

f) Auch beim Sort: Wenn du sortiert vor der Schleife nicht auf 1 setzt
(oder eine do-while-Schleife machst) wird nie was sortiert werden.


----------



## dev-c (13. Mai 2012)

danke! auf das temp array wäre ich nicht so schnell gekommen...


```
#include <stdio.h>
#include <stdlib.h>

struct probuchstabe
{
    char buchstabe;
    int anz;
    float prozent;
    char correct;
};
 
int main(int argc, char *argv[])
{
    FILE *datei;
    float buchstaben[26][3];
    int i, j;
    char c;
    float t=0;
    
    const int laenge=26;		// for bubble-sort
    int sortiert=0;			// for bubble-sort
    
    struct probuchstabe werte[26];
    struct probuchstabe temp;
    
    for(i=0; i<26; i++)
    {
		werte[i].buchstabe = 'a'+i;
    	werte[i].anz = 0;
    	werte[i].prozent = 0.0;
    	werte[i].correct = 'a';
    }
    
    temp.buchstabe = 'a';
    temp.anz = 0;
    temp.prozent = 0.0;
    temp.correct = 'a';
		
    datei = fopen(argv[1], "r");
 
    if(datei == NULL)
    {
        puts("Error");
        system("pause");
        return 1;					// 1 bei fehler; 0 bei alles OK
    }
    else
    {
        // puts("Error-Free");
    }
 
    while(!feof(datei))
    {
        c = fgetc(datei);
 
        if(c >= 'A' && c <= 'Z')
        {
            c = c - 'A' + 'a';		// große buchstaben in kleine umwandeln
        }
        if(c >= 'a' && c <= 'z')
        {
			werte[c - 'a'].anz++;		// position im array bestimmten und buchstaben raufzählen	
        }
    }
     
    // puts("End of File");
    
	for(i=0; i<26; i++)
    {
		t=t+werte[i].anz;
	}
	
	for(i=0; i<26; i++)
    {
		werte[i].prozent=(float)werte[i].anz*100/t;	// prozent berechnen
	}
	
	// bubble-sort
	while(sortiert == 0)
	{
		sortiert = 1;
		
		for(i = 0; i < laenge-1; i++)
		{
			if(werte[i].prozent < werte[i+1].prozent)
			{
				sortiert = 0;
				
				temp = werte[i];
				werte[i] = werte[i+1];
				werte[i+1] = temp;
			}
		}	
	}
		
    for(i = 0; i < 26; i++)
    {
		printf("%c\t %d\t %.3f%%\t\n", werte[i].buchstabe, werte[i].anz, werte[i].prozent);
    }
    
    fclose(datei);
    
   // deutsche Buchstabenverteilung
	werte[0].correct = 'e';
	werte[1].correct = 'n';
	werte[2].correct = 'i';
	werte[3].correct = 's';
	werte[4].correct = 'r';
	werte[5].correct = 'a';
	werte[6].correct = 't';
	werte[7].correct = 'd';
	werte[8].correct = 'h';
	werte[9].correct = 'u';
	werte[10].correct = 'l';
	werte[11].correct = 'c';
	werte[12].correct = 'g';
	werte[13].correct = 'm';
	werte[14].correct = 'o';
	werte[15].correct = 'b';
	werte[16].correct = 'w';
	werte[17].correct = 'f';
	werte[18].correct = 'k';
	werte[19].correct = 'z';
	werte[20].correct = 'p';
	werte[21].correct = 'v';
	werte[22].correct = 'j';
	werte[23].correct = 'y';
	werte[24].correct = 'x';
	werte[25].correct = 'q';
	
    printf("\n\n");
    
    // Ausgabe
    datei = fopen(argv[1], "r");
    while(!feof(datei))
    {
    c = fgetc(datei);
    printf("%c", c);
	}
 	fclose(datei);
 	
 	printf("\n\n");
 	
 	for(i = 0; i < 26; i++)
    {
		printf("%c\t %c\n", werte[i].buchstabe, werte[i].correct);
    }
	    
    printf("\n\n");
    
	system("pause");
    return 0;
}
```

Mein Ziele wäre jetzt: Ich habe eine Text. Von dem hab ich die nach der Analyse die Verteilung der Buchstaben. b ... 20% / r ... 12% / z ... 9% / usw.

Die Buchstabenverteilung der deutschen Sprache sieht so aus:
http://upload.wikimedia.org/wikiped...vg/800px-Buchstabenhäufigkeit_Deutsch.svg.png

Da b 20% hat kann ich davon ausgehe, dass es sich um ein e handelt.

Ich hätte mir gedacht, ich schreibe die deutsche Buchstabenhäufigkeit in meine Struktur nach der Sortierung rein. Das ich dann die Gegenüberstellung habe b ... e

Wenn ich dann den verschlüsselten Text lade und auf der Console ausgeben will, so wird b mit e ersetzt. 

Nur irgendwie habe ich keine Plan wo ich am besten anfangen soll und ob mein Ansatz überhaupt richtig ist.


----------



## sheel (13. Mai 2012)

Warum hast du noch das float-Array buchstaben drin?

Zum Poblem:
Jetzt hast du also sortiert.

Mach als Nächstes einen String, der alle deutschen Buchstaben der Häufigkeit nach drin hat.

```
char haufigkeit[] = "enis";
```
Den Rest natürlich ergänzen.


Und jetzt stellt sich die Frage, wie genau du das zu lösen gedenkst.
Willst du
a) die wahrscheinlichste Lösung zeigen, Benutzer sagt richtig/falsch, ggf. kommt der nächstwahrscheinlichste Vorschlag...
b) mit einem Verfahren die beste Lösung ermitteln, die eventuell auch falsch sein kann -> Pech
c) ...?


----------



## dev-c (13. Mai 2012)

Danke schon mal. Ich werde mich morgen weiter mit dem Thema auseinander setzen und meine Ergebnisse dann posten.


----------



## deepthroat (14. Mai 2012)

Hi.

Du hast also einen mit einer Caesar Chiffre verschlüsselten Text.

Dabei wird das Alphabet im Prinzip nur "verschoben". Beim Brechen der Verschlüsselung mußt du nun diese Verschiebung berechnen.

Du mußt also das Histogramm der verschlüsselten Datei mit dem Histogramm des deutschen Alphabets vergleichen. Dazu kannst du z.B. den mittleren quadratischen Fehler berechnen.


```
/* Buchstabenhäufigkeit in Prozent für A bis Z laut http://.. */
double german[] = { 5.58,
	1.96,
	3.16,
	4.98,
	16.93,
	1.49,
  ... };

/* Buchstabenhäufigkeit in Prozent für A bis Z der Datei */
double haeufigkeit[] = ...;

/* Finde die Verschiebung bei dem der Fehler minimal wird */

double min_fehler = DBL_MAX;
int min_verschiebung = 0;
for (int verschiebung = 0; verschiebung < 26; ++verschiebung) {
  double fehler = vergleiche(german, haufigkeit, verschiebung);

  if (fehler < min_fehler) {
    ...
  }
}
```
Gruß


----------



## dev-c (14. Mai 2012)

Danke soweit.
Bei meinem Ansatz habe ich jetzt die Verschiebung zum meist vorkommenden Buchstaben und dem e berechnet.

Dann sage ich bei der Ausgabe Klartext, wenn der Buchstabe zwischen A und z liegt, so soll die Verschiebung abgezogen werden.

Wenn es sich um ein Satzzeichen handelt, dann soll es 1:1 ausgegeben werden.

Jetzt habe ich die Probleme:
1) was mache ich, wenn die von A der Schlüssel abgezogen wird, so wird mir 9 ausgegeben. Normal müsste aber hinten beim Z weiter gerechnet werden.

2) Was mache ich wenn zu Z der Schlüssel addiert wird, dann komme ich in die Kleinbuchstaben rein.

3) Zwischen Groß- und Kleinbuchstaben habe ich ja noch ein paar andere Zeichen.

Ich müsste es irgendwie hinkriegen, wenn es sich um einen Großbuchstaben handelt, egal ob der Schlüssel + oder - gerechnet wird, dass ich immer in den Großbuchstaben bleibe. Eine Art Kreis.

Das selbe halt auch bei den Kleinbuchstaben.



```
#include <stdio.h>
#include <stdlib.h>

// Stuct definieren
struct probuchstabe
{
    char buchstabe;
    int anz;
    float prozent;
    char correct;
};
 
int main(int argc, char *argv[])
{
	// Variablen definieren
    FILE *datei;
    float buchstaben[26][3];
    int i=0, j=0, x=0, y=0, count=0;
    char c;
    float t=0;
    
    const int laenge=26;	// for bubble-sort
    int sortiert=0;			// for bubble-sort
    
    struct probuchstabe werte[26];
    struct probuchstabe temp;
    
    //------------------------------------------
    
    for(i=0; i<26; i++)
    {
		werte[i].buchstabe = 'a'+i;
    	werte[i].anz = 0;
    	werte[i].prozent = 0.0;
    	werte[i].correct = 'a';
    }
    
    temp.buchstabe = 'a';
    temp.anz = 0;
    temp.prozent = 0.0;
    temp.correct = 'a';
	
	//------------------------------------------
		
    datei = fopen(argv[1], "r");
 
    if(datei == NULL)
    {
        puts("Error");
        system("pause");
        return 1;					// 1 bei fehler; 0 bei alles OK
    }
    else
    {
        // puts("Error-Free");
    }
 
    //while(!feof(datei) && count<30)
    while(!feof(datei))
    {
        c = fgetc(datei);
 
        if(c >= 'A' && c <= 'Z')
        {
            c = c - 'A' + 'a';			// große buchstaben in kleine umwandeln
        }
        if(c >= 'a' && c <= 'z')
        {
			werte[c - 'a'].anz++;		// position im array bestimmten und buchstaben raufzählen	
        }
    }
     
    // puts("End of File");
    
    // Gesamte Buchstaben berechnen
	for(i=0; i<26; i++)
    {
		t=t+werte[i].anz;
	}
	
	// Prozent berechnen
	for(i=0; i<26; i++)
    {
		werte[i].prozent=(float)werte[i].anz*100/t;
	}
	
	// bubble-sort
	while(sortiert == 0)
	{
		sortiert = 1;
		
		for(i = 0; i < laenge-1; i++)
		{
			if(werte[i].prozent < werte[i+1].prozent)
			{
				sortiert = 0;
				
				temp = werte[i];
				werte[i] = werte[i+1];
				werte[i+1] = temp;
			}
		}	
	}
	
	// Ausgabe
	/*	
    for(i = 0; i < 26; i++)
    {
		printf("%c\t %d\t %.3f%%\t\n\n\n", werte[i].buchstabe, werte[i].anz, werte[i].prozent);
    }
    */
    fclose(datei);
    
    // Schlüssel berechnen
    x=werte[0].buchstabe-'e';
    printf("Schluessel: %d\n\n", x);
    
    // Mindest Zeichen
    printf("mindest Zeichen: %d\n\n", count);
    
    // Ausgabe (Klartext)
    datei = fopen(argv[1], "r");
    while(!feof(datei))
    {
		c = fgetc(datei);
		
		if( c >= 'A' && c <= 'z' )
		{
			printf("%c", c - x );	
		}
		
		else
		{
			printf( "%c", c);
		}
	}
 	fclose(datei);
 	 		    
    printf("\n\n");
    
	system("pause");
    return 0;
}
```


----------



## sheel (14. Mai 2012)

Pseudocode

```
if(kleiner als A geworden)
    26 dazurechnen
if(größer als Z geworden)
    26 abziehen
```
Das Selbe für Kleinbuchstaben


----------



## dev-c (14. Mai 2012)

ein Großbuchstabe ist nach ASCII ja immer kleiner als ein Kleinbuchstabe. Von daher würde ja immer was dazu gezählt werden oder?


----------



## deepthroat (14. Mai 2012)

```
char encrypted = ...;

if (isalpha(encrypted)) {
  char start;

  if (islower(encrypted) {
    start = 'a';
  } else {
    start = 'A';
  }

  char decrypted = start + (encrypted - start + schlüssel) % 26;
}
```

Außerdem verwendet man kein feof in einer Schleife. Das funktioniert so nicht. Und fgetc gibt einen int zurück.

```
int c;
while ((c = fgetc(datei)) != EOF) {
  ...
}
```
Gruß


----------



## dev-c (3. Juni 2012)

Ich wollte ja meinen Code posten, hatte ich total vergessen! Das hole ich jetzt mal nach.
Er ist zwar nicht perfekt, aber er funktioniert.


```
#include <stdio.h>
#include <stdlib.h>

// Stuct definieren
struct probuchstabe
{
    char buchstabe;
    int anz;
    float prozent;
    char correct;
};
 
int main(int argc, char *argv[])
{
	// Variablen definieren
    FILE *datei;
    float buchstaben[26][3];
    int i=0, j=0, x=0, y=0, count=50;
    char c;
    float t=0;
    
    const int laenge=26;	// for bubble-sort
    int sortiert=0;			// for bubble-sort
    
    struct probuchstabe werte[26];
    struct probuchstabe temp;
    
    //------------------------------------------
    
    for(i=0; i<26; i++)
    {
		werte[i].buchstabe = 'a'+i;
    	werte[i].anz = 0;
    	werte[i].prozent = 0.0;
    	werte[i].correct = 'a';
    }
    
    temp.buchstabe = 'a';
    temp.anz = 0;
    temp.prozent = 0.0;
    temp.correct = 'a';
	
	//------------------------------------------
		
    datei = fopen(argv[1], "r");
 
    if(datei == NULL)
    {
        puts("Error");
        system("pause");
        return 1;					// 1 bei fehler; 0 bei alles OK
    }
    else
    {
        // puts("Error-Free");
    }
 
    //while(!feof(datei) && count<30)
    while(!feof(datei))
    {
        c = fgetc(datei);
 
        if(c >= 'A' && c <= 'Z')
        {
            c = c - 'A' + 'a';			// große buchstaben in kleine umwandeln
        }
        if(c >= 'a' && c <= 'z')
        {
			werte[c - 'a'].anz++;		// position im array bestimmten und buchstaben raufzählen	
        }
    }
     
    // puts("End of File");
    
    // Gesamte Buchstaben berechnen
	for(i=0; i<26; i++)
    {
		t=t+werte[i].anz;
	}
	
	// Prozent berechnen
	for(i=0; i<26; i++)
    {
		werte[i].prozent=(float)werte[i].anz*100/t;
	}
	
	// bubble-sort
	while(sortiert == 0)
	{
		sortiert = 1;
		
		for(i = 0; i < laenge-1; i++)
		{
			if(werte[i].prozent < werte[i+1].prozent)
			{
				sortiert = 0;
				
				temp = werte[i];
				werte[i] = werte[i+1];
				werte[i+1] = temp;
			}
		}	
	}
	
	// Ausgabe
	/*	
    for(i = 0; i < 26; i++)
    {
		printf("%c\t %d\t %.3f%%\t\n\n\n", werte[i].buchstabe, werte[i].anz, werte[i].prozent);
    }
    */
    fclose(datei);
    
    // Schlüssel berechnen
    x=werte[0].buchstabe-'e';
    printf("Schluessel: %d\n\n", x);
    
    // Mindest Zeichen
    printf("mindest Zeichen: %d\n\n", count);
    
    // Ausgabe (Klartext)
    datei = fopen(argv[1], "r");
while(!feof(datei))
    {
		c = fgetc(datei);
		
		if( c >= 'A' && c <= 'z' )
		{
			if( c - x > 'z' )
			{
				printf("%c", c - x - 58 );
			}
			
			else
			{
				if( c - x < 'A' )
				{
					printf("%c", 58 + c - x );
				}
				
				else
				{
					printf("%c", c - x );
                }
			}	
		}
		
		else
		{
			printf( "%c", c);
		}
	}
 	fclose(datei);
 	 		    
    printf("\n\n");
    
	system("pause");
    return 0;
}
```


Folgenden Text gilt es zu übersetzen:

MxE SDqsAD _myEm quzqE YADsqzE mGE GzDGtusqz `DmqGyqz qDImotFq, rmzp qD Euot uz Equzqy NqFF LG quzqy GzsqtqGqDqz azsqLuqrqD HqDImzpqxF. QD xms mGr Equzqy BmzLqDmDFus tmDFqz ^Gqowqz Gzp Emt, Iqzz qD pqz WABr quz Iqzus tAn, Equzqz sqIAqxnFqz, nDmGzqz, HAz nAsqzrAqDyusqz bqDEFqurGzsqz sqFquxFqz NmGot, mGr pqEEqz TAqtq Euot puq NqFFpqowq, LGy smqzLxuotqz ZuqpqDsxquFqz nqDquF, wmGy zAot qDtmxFqz wAzzFq. _quzq Huqxqz, uy bqDsxquot LG Equzqy EAzEFusqz ayrmzs wxmqsxuot pGqzzqz Nquzq rxuyyqDFqz uty tuxrxAE HAD pqz MGsqz.

"cmE uEF yuF yuD sqEotqtqz?", pmotFq qD. QE ImD wquz `DmGy. _quz fuyyqD, quz DuotFusqE, zGD qFImE LG wxquzqE YqzEotqzLuyyqD, xms DGtus LIuEotqz pqz HuqD IAtxnqwmzzFqz cmqzpqz. GqnqD pqy `uEot, mGr pqy quzq mGEquzmzpqDsqBmowFq YGEFqDwAxxqwFuAz HAz `GotImDqz mGEsqnDquFqF ImD - _myEm ImD ^quEqzpqD - tuzs pmE Nuxp, pmE qD HAD wGDLqy mGE quzqD uxxGEFDuqDFqz fquFEotDurF mGEsqEotzuFFqz Gzp uz quzqy tGqnEotqz, HqDsAxpqFqz ^mtyqz GzFqDsqnDmotF tmFFq. QE EFqxxFq quzq Pmyq pmD, puq yuF quzqy \qxLtGF Gzp quzqD \qxLnAm HqDEqtqz, mGrDqotF pmEmw Gzp quzqz EotIqDqz \qxLyGrr, uz pqy utD smzLqD azFqDmDy HqDEotIGzpqz ImD, pqy NqEotmGqD qzFsqsqztAn.

SDqsADE Nxuow DuotFqFq Euot pmzz LGy RqzEFqD, Gzp pmE FDGqnq cqFFqD - ymz tAqDFq ^qsqzFDABrqz mGr pmE RqzEFqDnxqot mGrEotxmsqz - ymotFq utz smzL yqxmzotAxuEot. "cuq ImqDq qE, Iqzz uot zAot quz Iqzus IquFqDEotxuqrq Gzp mxxq ZmDDtquFqz HqDsmqEEq", pmotFq qD, mnqD pmE ImD smqzLxuot GzpGDotrGqtDnmD, pqzz qD ImD sqIAqtzF, mGr pqD DqotFqz _quFq LG Eotxmrqz, wAzzFq Euot mnqD uz Equzqy sqsqzImqDFusqz fGEFmzp zuotF uz puqEq Xmsq nDuzsqz. YuF IqxotqD WDmrF qD Euot mGot mGr puq DqotFq _quFq ImDr, uyyqD IuqpqD EotmGwqxFq qD uz puq ^Gqowqzxmsq LGDGqow. QD HqDEGotFq qE IAtx tGzpqDFymx, EotxAw puq MGsqz, Gy puq LmBBqxzpqz Nquzq zuotF Eqtqz LG yGqEEqz, Gzp xuqw qDEF mn, mxE qD uz pqD _quFq quzqz zAot zuq sqrGqtxFqz, xquotFqz, pGyBrqz _otyqDL LG rGqtxqz nqsmzz.

"Mot SAFF", pmotFq qD, "ImE rGqD quzqz mzEFDqzsqzpqz NqDGr tmnq uot sqImqtxF! `ms mGE, `ms quz mGr pqD ^quEq. Puq sqEotmqrFxuotqz MGrDqsGzsqz Euzp Huqx sDAqwqD, mxE uy qusqzFxuotqz SqEotmqrF LG TmGEq, Gzp mGwqDpqy uEF yuD zAot puqEq \xmsq pqE ^quEqzE mGrqDxqsF, puq _ADsqz Gy puq fGsmzEotxGqEEq, pmE GzDqsqxymqwusq, EotxqotFq QEEqz, quz uyyqD IqotEqxzpqD, zuq mzpmGqDzpqD, zuq tqDLxuot IqDpqzpqD yqzEotxuotqD bqDwqtD. PqD `qGrqx EAxx pmE mxxqE tAxqz!" QD rGqtxFq quz xquotFqE VGowqz Anqz mGr pqy NmGot; EotAn Euot mGr pqy ^Gqowqz xmzsEmy zmqtqD LGy NqFFBrAEFqz, Gy pqz WABr nqEEqD tqnqz LG wAqzzqz; rmzp puq vGowqzpq _Fqxxq, puq yuF xmGFqD wxquzqz Iquwqz \GqzwFotqz nqEqFLF ImD, puq qD zuotF LG nqGDFquxqz HqDEFmzp; Gzp IAxxFq yuF quzqy Nquz puq _Fqxxq nqFmEFqz, LAs qE mnqD sxquot LGDGqow, pqzz nqu pqD NqDGqtDGzs GyIqtFqz utz WmqxFqEotmGqD.


----------



## deepthroat (4. Juni 2012)

dev-c hat gesagt.:


> ich wollte ja meinen code posten, hatte ich total vergessen! das hole ich jetzt mal nach.
> er ist zwar nicht perfekt, aber er funktioniert.


Hast du das denn ausprobiert?

Für die folgende Eingabe:

```
vpu jbyygr wn zrvara pbqr cbfgra, unggr vpu gbgny iretrffra! qnf ubyr vpu wrgmg zny anpu.
re vfg mjne avpug cresrxg, nore re shaxgvbavreg.

vpu jbyygr wn zrvara pbqr cbfgra, unggr vpu gbgny iretrffra! qnf ubyr vpu wrgmg zny anpu.
re vfg mjne avpug cresrxg, nore re shaxgvbavreg.
```
Erhalte ich bei deinem Programm die Ausgabe:

```
Schluessel: 13

mindest Zeichen: 50

ich ]UllZe ja meiTeT cUde VUYZeT, haZZe ich ZUZal \eXgeYYeT! daY hUle ich jeZ`Z mal Tach.
eX iYZ `]aX TichZ VeXfekZ, abeX eX f[TkZiUTieXZ.

ich ]UllZe ja meiTeT cUde VUYZeT, haZZe ich ZUZal \eXgeYYeT! daY hUle ich jeZ`Z mal Tach.
eX iYZ `]aX TichZ VeXfekZ, abeX eX f[TkZiUTieXZ.
ÿ
```
Sieht irgendwie nicht wirklich korrekt aus... 

Und bitte halte dich an die Netiquette bzgl. Groß-/Kleinschreibung. Danke!

Gruß


----------



## dev-c (4. Juni 2012)

Ich habe jetzt den Beispieltext beim Beitrag davor eingefügt. Weiters habe ich die while Schleife nochmal überarbeitet.
Trotzdem kriege ich bei deinem Text nicht das richtige raus.

Folgendes muss halt zutreffen:
1) das e muss der häufigste Buchstabe im Text sein (so wie in der deutschen Sprache es üblich ist).
2) Die Verschiebung des Schlüssels muss einen fixen Wert nach rechts oder links haben. Das Alphabet darf nicht durcheinander gewürfelt sein.

Gruß


----------



## deepthroat (4. Juni 2012)

dev-c hat gesagt.:


> Ich habe jetzt den Beispieltext beim Beitrag davor eingefügt. Weiters habe ich die while Schleife nochmal überarbeitet.
> Trotzdem kriege ich bei deinem Text nicht das richtige raus.


Ja, dein Programm funktioniert nicht.


dev-c hat gesagt.:


> Folgendes muss halt zutreffen:
> 1) das e muss der häufigste Buchstabe im Text sein (so wie in der deutschen Sprache es üblich ist).
> 2) Die Verschiebung des Schlüssels muss einen fixen Wert nach rechts oder links haben. Das Alphabet darf nicht durcheinander gewürfelt sein.


Das trifft beides zu. Der berechnete Schlüssel ist auch richtig. Deine Entschlüsselungsroutine stimmt nur nicht.

Und dann druckst du noch dieses extra ÿ Zeichen aus, welches gar nicht im Text ist.

Gruß


----------



## dev-c (4. Juni 2012)

Puh, da bin ich jetzt überfragt. Da es mit dem einen Beispieltext funktioniert hat, dachte ich mir das ich alles richtig gemacht habe.
Dann muss ich mir das wohl noch einmal ansehen.


----------

