Forum: PC-Programmierung C# Buchstaben aus Array zählen und Häufigkeit bestimmen


von Marc M. (madmarc)


Lesenswert?

Servus zusammen,

mein Name ist Marc, ich studiere Elektrotechnik im 1. Semester (seit 
März) und hatte bisher kaum etwas mit Programmierung und 
Programmiersprachen zu tun. Aktuell besuche ich die Vorlesung 
"C-Programmierung" und habe eine Frage zu einer Aufgabe aus dem 
Tutorium. Die Aufgabe lautet:
Lesen Sie eine Zeichenketten (max. 80 Zeichen) ein und geben Sie die 
Anzahl der Klein- und Großbuchstaben in einem 2-D array aus (ä, ö, ü 
sollen vernachlässigt werden). Die Verwendung der Speicherverwaltung 
(malloc,...) und Zeiger werden zum Lösen der Aufgabe nicht benötigt.

Mein Ansatz sieht so aus:
1
#include <stdio.h>
2
#include <string.h>
3
#include <stdlib.h>
4
5
#define aufg2
6
7
int main(void)
8
{
9
10
#ifdef aufg2
11
12
    char stringkette[81]={0}; //Feld zum einlesen der Zeichenkette
13
    char auswertung[26][1]={{0},{0}}; //Feld zur Auswertung der Klein-/Großbuchstaben und der Häufigkeit
14
    int i=0, j=0;
15
    
16
    printf("Bitte geben Sie eine beliebige Zeichenkette (max. 80 Zeichen) ein:\n");
17
    fgets(stringkette, 81, stdin);
18
    
19
    printf("Die eingegebene Zeichenlänge beträgt: %d", strlen(stringkette)-1);
20
       
21
    for(i=0; i<=strlen(stringkette); i++)  //for-Schleife für Werte in Array zu prüfen, hier könnte man auch sizeof vorwenden 
22
    {
23
        if ((stringkette[i] > 64) && (stringkette[i] < 91)) || ((stringkette[i] > 96) && (stringkette[i] < 123)) //Prüfe ob Groß- oder Kleinbuchstabe
24
        {
25
        ???
26
        }
27
28
        else
29
        {
30
        printf("Ungültige Eingabe!"); 
31
        }
32
      
33
}


Mein Knackpunkt ist, wie bekomme ich die einzelnen Buchstaben in das 
array auswertung und wie Zähle ich die Anzahl. Für mich sind es momentan 
zu viele Werte, die geprüft werden müssten.
Theoretisch müsste ich eine Schleife schreiben, die prüft, wie oft kommt 
das Zeichen a vor, zähle dies und schreibe es in array auswertung[i][j]. 
Wie oft kommt das Zeichen b vor, zähle dies,... und da bin ich mit 
meinem C momentan am Ende.

Wenn ich nur ein Zeichen (z. Bsp. a) suchen würde, aus einer beliebigen 
Zeichenkette, dann würde ich es so schreiben:
1
for(i = 0; i <= 81; ++i)
2
        if(zeichenkette[i]=='a')
3
            z++;
4
    printf("Gesuchtes Zeichen -%s- kam %d mal vor.\n", zeichen, z);

Vielleicht kann mir jemand ja einen guten Tipp geben, wie ich weiter 
komme bzw. ob ich einen Denkfehler habe.

Vielen Dank im Voraus.

Grüße

Marc

[Mod: C-Formatierungs-Tags eingefügt]

: Bearbeitet durch Moderator
von Peter II (Gast)


Lesenswert?

Marc Mer schrieb:
> Vielleicht kann mir jemand ja einen guten Tipp geben, wie ich meine
> Aufgabe lösen kann.

schau mit mal ein Dictionary an.

https://msdn.microsoft.com/de-de/library/xfhwa508(v=vs.110).aspx

Dort kannst du zu jedem Buchstaben eine Zahl speichern.

von nicht"Gast" (Gast)


Lesenswert?

Peter II schrieb:
> schau mit mal ein Dictionary an.
>
> https://msdn.microsoft.com/de-de/library/xfhwa508(v=vs.110).aspx

Moin,

ich glaube, da hat sich der TE einen freudschen verschreiber geleistet. 
Der Code schaut nicht grad nach C# aus. Ist wohl eher C und die 
Aufgabenstellung ist auch C.

Zur Aufgabe.

1. Du brauchst kein zweidimensionales Array. Du kannst die Anzahl der 
Buchstasben locker in einer Dimension unterbringen.

int charCount[26]={0};

Dann gehts du einfach mit allen möchglichen Buchstaben über dein String 
und schaust, ob eine Übereinstimmung erfolgt.
1
size_t inputLength = strlen(stringkette);
2
for(char toSearch= 'a'; toSearch<= 'z'; toSearch++){
3
    for(int i=0;i<inputLength;i++){
4
        if(stringkette[i] == toSearch){
5
            charCount[toSearch-'a']++;
6
        }
7
    }
8
}

Grüße,

von Peter II (Gast)


Lesenswert?

nicht"Gast" schrieb:
> 1. Du brauchst kein zweidimensionales Array. Du kannst die Anzahl der
> Buchstasben locker in einer Dimension unterbringen.

aber nur solange es nicht mit UTF8 losgeht.

von Udo S. (urschmitt)


Lesenswert?

Marc Mer schrieb:
> char stringkette[81]={0};
> ...
> for(i = 0; i <= 81; ++i)

Das üben wir aber nochmal!

Wieviele Elemente sind in dem Array?
Welche gültigen Indexe haben sie?
Über wieviele Elemente willst du hier gerade iterieren?

von nicht"Gast" (Gast)


Lesenswert?

Peter II schrieb:
>> 1. Du brauchst kein zweidimensionales Array. Du kannst die Anzahl der
>> Buchstasben locker in einer Dimension unterbringen.
>
> aber nur solange es nicht mit UTF8 losgeht.


Was hat die Kodierung damit zu tun? Ich brauch 26 Einträge (oder das 
doppelte für Groß und Klein getrennt), wenn ich Buchstaben zählen soll 
und Sonderzeichen ignorieren kann. Das einzige, was man dann evtl. 
anpassen muss ist das iterieren über die Suchzeichen und das Speichern 
im Array (nicht bei utf).

Da das aber ein Grundlagenkurs ist, kannst du dir dein Getrolle bitte 
für das Heise Forum aufheben.

von Peter II (Gast)


Lesenswert?

nicht"Gast" schrieb:
> Was hat die Kodierung damit zu tun? Ich brauch 26 Einträge (oder das
> doppelte für Groß und Klein getrennt), wenn ich Buchstaben zählen soll

Wenn deine Welt nur aus 26 Buchstaben besteht ist es ja gut, in anderen 
teilen der Welt sind es mehr.

aber warum so umständlich wenn eine schleife reicht?
1
int charCount[26]={0};
2
3
char* pos = stringkette;
4
while( *pos ) {
5
   char c = tolower( *pos );
6
   if ( c >= 'a' && c <= 'z') {
7
      charCount[ c - 'a' ]++;
8
   }
9
   ++pos;
10
}

von Marc M. (madmarc)


Lesenswert?

Hi,

vielen Dank schon mal für die vielen Antworten und entschuldigt bitte 
meinen Fehler, dass ich C# geschrieben habe anstatt C. Habe meine 
Wissenslücke bereits aufgearbeitet :)!

Verbessert hab ich array stringkette. Es benötigt nur eine Größe von 
[80] (0-79 = 80 Zeichen + Nullzeichen). Ebenso muss das Feld Auswertung 
auf [52][1] vergrößert werden, wenn Groß- und Kleinbuchstaben "sauber" 
ausgegeben werden sollen.

Da es sich um eine Aufgabe handelt, die eine Lösung mit einem 2-D-Feld 
"verlangt", denke ich, dass man zwar die Aufgabe ggf. leichter/schneller 
lösen könnte, mit oben genannten Dimensionen, Zeigern,... jedoch es auch 
über das 2-D-Feld gehen sollte.
Ich denke die Ausgabe in der Konsole sollte wie folgt sein:
Es wurden XX Zeichen eingeben.
a = 2
d = 5
t = 1
z = 1
B = 4
F = 1
M = 3
....
Die Ausgabe habe ich bereits geschrieben, funktioniert jedoch bisher 
nur, wenn ich die Buchstaben/Werte oben im Feld initialisiere...aber 
diese sollen ja eingelesen werden.

Wie bereits erwähnt, bin erstes Semester und gerade die Sprache am 
lernen. Falls ich in dem Forum falsch bin oder die Aufgabe zu "einfach" 
ist, dann lasst es bitte wissen. Danke.

von Peter II (Gast)


Lesenswert?

Marc Mer schrieb:
> vielen Dank schon mal für die vielen Antworten und entschuldigt bitte
> meinen Fehler, dass ich C# geschrieben habe anstatt C. Habe meine
> Wissenslücke bereits aufgearbeitet :)!

darf es auch C++ sein?

von Marc M. (madmarc)


Lesenswert?

Peter II schrieb:

> darf es auch C++ sein?

Das kann ich so nicht beantworten, dass müsste ich erst beim Prof. 
nachfragen. Wie geschrieben, Vorlesung ist C-Programmierung, C++ wird 
ebenfalls angeboten, jedoch nicht im ersten Semester.

von Udo S. (urschmitt)


Lesenswert?

Peter II schrieb:
> darf es auch C++ sein?

im Moment hat er noch genügend mit einfachem C zu kämpfen.

Marc Mad schrieb:
> [80] (0-79 = 80 Zeichen + Nullzeichen)
???

Noch mehr üben!
Wenn ich ein Array definiere:
char a[80];

1. Wieviele Elemente hat das?
2. In welchem Bereich läuft der Index?

Marc Mad schrieb:
> auf [52][1]

Was soll das werden?

von Marc M. (madmarc)


Lesenswert?

Udo Schmitt schrieb:

> Noch mehr üben!
> Wenn ich ein Array definiere:
> char a[80];
>
> 1. Wieviele Elemente hat das?
> 2. In welchem Bereich läuft der Index?
>
> Marc Mad schrieb:
>> auf [52][1]
>
> Was soll das werden?

Ok, also ich habe mir folgendes gedacht:

char stringkette[80]={0};

Es sollen bis max. 80 Zeichen (Buchstaben) von einer Nutzereingabe 
eingelesen werden, wie in Aufgabenstellung. Deshalb habe ich das Feld 
stringkette[80] so definiert. Da vom Speicherplatz 0-79 80 Zeichen der 
Eingabe gespeichert werden könnten und das 80ste Zeichen das Nullzeichen 
‘\0‘ wäre. Da ich nicht möchte, dass irgendetwas noch im Speicher steht, 
habe ich alle Werte mit {0} auf 0 gesetzt. Dies wird mir auch im Stack 
so angezeigt.
Wie viele Elemente der Nutzer eingibt, kann man nicht sagen, es dürfen 
nur nicht mehr als 80 sein. Was bedeutet: im welchen Bereich läuft der 
Index?

char auswertung[52][1]={{0},{0}};

Da im String alle Klein- und Großbuchstaben vorkommen könnten und die 
Anzahl ausgeben werden soll, habe ich mir gedacht, dass ich ein Feld 
benötige welches 51 (nicht 52) Plätze hat, für 26 Klein- und 26 
Großbuchstaben sowie eine Spalte für die Anzahl. Beide wieder auf 0 
gesetzt.

Ist dieser Ansatz falsch?

: Bearbeitet durch User
von Markus H. (markus_h20)


Lesenswert?

Wenn du 80 Zeichen benötigst musst du noch ein Zeichen für /0 vorsehen.
sprich char string[81].
hier wird mit 1 begonnen zu zählen.

In einer Schleife jedoch kannst du nur bis string[80] gehen, da hier mit 
Index 0 begonnen wird.

von Horst S. (Gast)


Lesenswert?

Zeichenketten beinhalten auch Spaces und Satzzeichen. Wenn Du die nach 
dem Ansatz

(charCount[ c - 'a' ]++;)

oben im Array nicht berücksichtigst, schreibt Dir das C-Programm in den 
berühmt-berüchtigten "Irgendwo-Mem".

Das führt zu bööööösen Fehlern.

von Max H. (hartl192)


Lesenswert?

Horst S. schrieb:
> Zeichenketten beinhalten auch Spaces und Satzzeichen. Wenn Du die nach
> dem Ansatz
>
> (charCount[ c - 'a' ]++;)
>
> oben im Array nicht berücksichtigst, schreibt Dir das C-Programm in den
> berühmt-berüchtigten "Irgendwo-Mem".
>
> Das führt zu bööööösen Fehlern.

Und wozu denkst du ist das
1
if(c >= 'a' && c <= 'z')
da?

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.