Zeichenkette auf Unzulässige Zeichen Prüfen

Hotte93

Grünschnabel
Hey Com,

ich habe ein kleines Problem.
Und zwar muss ich die Anzahl von vorkommenden Buchstaben einer Zeichenkette bestimmen.
Die zu zählenden Buchstaben sind aber auf [A,B,C,D,E,F] beschränkt.
Bei jedem anderen eingegebenen Wert soll ein Fehler ausgegeben werden.
Nach einiger Recherche bin ich auf eine String-Funktion (strcmp) gestoßen die 2 Strings miteinander vergleicht.
Also habe ich zusätzlich einen Prüf-String erstellt um den eingegeben Code mit diesem zu vergleichen.
Leider weiß ich nicht genau wie ich das programmier-technisch umsetzten kann.
Im Anhang mein bisheriger Versuch.

C#:
#include <iostream>
#include <stdio.h>
#include <string.h>


/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main() {

char zeichenkette [200];
char pruefziffern   [6]= {'A','B','C','D','E','F'};

int i;
int p;
int x=0;
int y=0;
int a=0;
int b=0;
int c=0;
int d=0;

    printf("Geben Sie die Zeichenkette ein ");
    scanf("%s", &zeichenkette[i]);
   
   

       
    p= strncmp(zeichenkette, pruefziffern, i);   
       

   
    if(p!=0){
       
        printf("Unzulaessige Zeichen");
    }
    else{

   
    for(i=0; i<zeichenkette[i]; i++){
    

       
     
    if(zeichenkette[i] =='A'){
       
        x=x+1;
    }
    else if(zeichenkette[i] == 'B'){
        y=y+1;
    }
   
    else if(zeichenkette[i] == 'C'){
       
        a=a+1;
    }
   
    else if(zeichenkette[i] == 'D'){
       
        b=b+1;
    }
   
    else if(zeichenkette[i] == 'E'){
        c=c+1;
    }
   
    else if(zeichenkette[i] == 'F'){
       
        d=d+1;
    }
   
   
     printf("A(%d) B(%d) C(%d) D(%d) E(%d) F(%d)", x, y, a, b, c, d);
   



}
   

 
   
}
   
           
   
   
return 0;   
   
   
}

Wäre schön wenn mir jemanden helfen könnte.

MfG
Hotte
 
Zuletzt bearbeitet:
Hi

strcmp und ähnliche Funktionen helfen dabei nicht. strcmp kann dir sagen, ob zwei Strings gleich oder nicht sind, aber nicht ob ungültige Buchstaben drin sind.

Was mir auffällt, der Reihe nach:

Bei C-Programmen gibts kein <iostream> - Include, weg damit.

Code:
char pruefziffern   [6]= {'A','B','C','D','E','F'};
...
int x=0;
int y=0;
int a=0;
int b=0;
int c=0;
int d=0;
Warum gehört x zu A, und a zu C usw.? Wenn das Programm größer wird kennt sich da keiner aus. Außerdem,. was ist wenn es 100 gültige Zeichen gibt? ... Man könnte auch ein Array nehmen. Außerdem hilft es für später, die Größe auch irgendwo abfragbar zu haben.
Code:
const int size = 6;
char erlaubteBuchstaben[size]= {'A','B','C','D','E','F'};
...
int anzahl[size];
for(i = 0; i < size; i++) anzahl[i] = 0;

Das Einlesen:
Code:
printf("Geben Sie die Zeichenkette ein ");
scanf("%s", &zeichenkette[i]);
kann so nicht funktionieren. Scanf für Strings ist sowieso schlecht: Was ist, wenn man mehr als 200 Buchstaben eingibt? Scanf prüft das nicht. Besser so:
Code:
printf("Geben Sie die Zeichenkette ein ");
fgets(zeichenkette, 200, stdin);

Das strncmp und if/else danach kann wie gesagt ausgelassen werden.

Code:
for(i=0; i<zeichenkette[i]; i++)
Warum sollte die Länge in zeichenkette[i] stehen? Tut sie nicht. Hier ist jetzt aber eine str-Funktion hilfreich: strlen.
Code:
for(i = 0; i < strlen(zeichenkette); i++)

Bei
Code:
if(zeichenkette[i] == 'A'){ 
    x=x+1;
}
verwendest du das Array mit den gültigen Buchstaben ja gar nicht.
Code:
for(int n = 0; n < size; n++)
{
    if(zeichenkette[i] == erlaubteBuchstaben[n]){ 
        //variable erhöhen
    }
}
Jeden erlaubten Buchstaben also durchgehen, mit einer eigenen Schleife, und mit dem aktuellen Eingabebuchstaben vergleichen.
Das Variablenerhöhen noch, da es ja jetzt ein Array gibt ... 6 (size) gültige Buchstaben, und 6 ints zum Zählen im Array ... da kann man daher einfach den Arrayindex n weiterverwenden: Wenn zeichenkette[i] gleich wie der n-te erlaubte Buchstabe ist, dann wird das n-te int in Anzahl erhöht:
Code:
for(int n = 0; n < size; n++)
{
    if(zeichenkette[i] == erlaubteBuchstaben[n]){ 
        anzahl[n] = anzahl[n] + 1;
        /*oder auch anzahl[n]++; */
    }
}
 
C++:
int anzahl[size];
Leichte Verbesserung: Da nur die Natürlichen Zahlen (und nicht die Ganzen Zahlen) gebraucht werden, scheint "unsigned int" besser geeignet.

kann so nicht funktionieren.
Korrekt.

Scanf für Strings ist sowieso schlecht: Was ist, wenn man mehr als 200 Buchstaben eingibt? Scanf prüft das nicht.
Es gibt sogar 2 Arten, das zu prüfen: Zum einen gibt es die Length-Specifier, zum anderen das nigelnagelneue Posix 2008/2013: http://stackoverflow.com/a/1621973
C++:
//1
char string[200];
scanf("%199s", string); //Liest höchstens 199 Zeichen, also muss der Array mindestens 200 Zeichen fassen.

//2
char* out = NULL;
scanf("%ms", &out);    //Holt sich den Platz, den es braucht. Länge ist variabel.

/* !!! UNBEDINGT AUFRUFEN !!! */
free(out);

Ansonsten hat sheel eigentlich alles gesagt, was es zu sagen gibt.

Gruss
cwriter
 
Unbewusst fall ich immer auf C89 zurück, sorry :(
Und die zweite Variante ist mir ganz neu :D Danke, wieder was dazugelernt
 
Vielen Dank für die Antwort!
Das Programm ist jetzt etwas übersichtlicher :)


Code:
int i;
int n;
int x;
int y;
int a;
int b=0;
int c;
int d=0;

Die integer waren unten für die Ausgabe gedacht.

Jetzt erschließt sich mir aber noch nicht wie ich eine Fehlermeldung ausgebe wenn ein ungültiges Zeichen vorkommt.
So wie es jetzt läuft werden diese Zeichen einfach übersehen und nur die erlaubten Buchstaben werden addiert.

MfG
Hotte
 
Hi

Jetzt erschließt sich mir aber noch nicht wie ich eine Fehlermeldung ausgebe wenn ein ungültiges Zeichen vorkommt.
Nun, entweder ist das Zeichen erlaubt oder nicht (Tertium non datur).
Es gibt also ein paar Möglichkeiten:
C++:
//1
if(A) {

}
else if(B) {

}
...
else {
    //Nicht erlaubt
    printf("Hochkriminelles Zeichen entdeckt!");
}

//2: Kann nur Konstanten überprüfen. Also nix mit lustig (Array mit gültigen Zeichen)
switch(zuPrüfenderWert)
{
    case 'A':
        ...
        break;
    case 'B':
        ...
        break;
    case ...
 
    default:
        //Nicht definiertes Zeichen
        break;

};

//3: Optimiert für ASCII-Buchstaben
if((unsigned int)(zuPrüfenderWert - 'A') <= 5)
{
    //Also wenn das Zeichen im Bereich A-F ist, nimm an und handle es spezifisch, bspw. mit:
    zähler[zuPrüfenderWert - 'A']++;
}
else {
    //Also wenn es ein Buchstabe oder eine Zahl ist, die nicht zwischen 65-71 liegt (nicht definiert ist)
    printf("Hochkriminelles Zeichen entdeckt!");
}

Ich würde dir die if-else if-else Verzweigung empfehlen. Die ist auch mit Abstand die am meisten benutzte.

Du wirst feststellen, dass sich dieser Code nicht kompilieren lässt, damit du es selbst probieren kannst. Wenn es nicht geht, einfach ungeniert (wenn möglich mit schön eingerücktem Code) nachfragen :)

Gruss
cwriter

/EDIT: Möglicherweise habe ich deine Frage falsch verstanden. Was willst du genau? Eine Fehlermeldung kannst du ja mit printf() ausgeben, diese Funktion hast du aber schon benutzt...?
Mit einem ...else am Ende deiner Else-if-Liste kannst du alle noch nicht behandelten (ergo ungültigen) Antworten behandeln, also immer einen Fehler ausgeben. Wenn du direkt abbrechen willst, kannst du ein einfaches return verwenden.
Sorry, ich verstehe wirklich nicht, was dir nicht klar ist. Kannst du die Frage vielleicht ein bisschen erläutern?
 
Zuletzt bearbeitet:
Zurück