1.8k Aufrufe
Gefragt in Anwendungen(Java,C++...) von
Hey Leute,

ich bin dabei C zu lernen und die Aufgabe lautet nun, Strings per Index einzulesen. Ich habe viel rumprobiert und verzweifle nun langsam an dieser für euch sicher einfachen Aufgabe.

Aufgabe 1
Erstellen Sie ein Unterprogramm, welches Sie in case ‘1‘ aufrufen, dasein Array
(szString_1Roh[]), nach vorheriger Prüfung auf Gültigkeit des eingegebenen Zeichens, Element für Element befüllt.

Elementauswahl über Index

Gültige Zeichen sind [0-9], [a-z] und [A-Z]

Die Eingabe soll bei Eingabe <RETURN> beendet werden

Geben Sie nach erfolgreichem durchlauf Ihres Unterprogramms den eingelesenen
String aus (siehe VORGABE zur Ausgabe in “APP_main.c“).

Hinweis:
Die Prüfung auf Gültigkeit eines Zeichens können Sie wiederum in ein
Unterprogramm ausgliedern. (Hab ich bisher noch nicht gemacht)

Wie wird das Ende eines Strings erkannt?
Ablauf innerhalb case ‘1‘ siehe Struktogramm zu Aufgabe 0


Mein Code sieht folgendermaßen aus:

Arraydeklaration u.s.w.:

#define ZIFFERN_MAX 100
uint8_t szString_1Roh[ZIFFERN_MAX];


Aufruf der Funktion:
switch(ucMenue)
{
case '1':
//string_fuellen_index();
break;


Die Funktion an sich:
void string_fuellen_index()
{
i=0;
printf("Bitte geben Sie eine Zeichekette ein: ");

do
{
if ( (Key >= 'A') && (Key <= 'Z') || (Key >= '0') && (Key <= '9') || (Key >= 'a') && (Key <= 'z') )
{
scanf("%c", szString_1Roh);
//szString_1Roh[i] = getchar();
//i++;
}

}
while(szString_1Roh[i] != '\0');


Ich hoffe ihr könnt mir helfen. :)
Das alles klappt in soweit nicht, dass ich entweder die Zeichen eingeben kann, aber wenn ich dann Enter drücke passiert nichts. Oder das Programm stürzt ab, je nachdem wie ichs schreibe.

Liebe Grüße
Döner

4 Antworten

0 Punkte
Beantwortet von Experte (3.2k Punkte)
Ist das Problem in der string_fuellen_index() oder kommt er da garnicht erst hin?
Ich gehe mal davon aus, dass sie schon aufgerufen wird, aber selbst fehlerhaft ist.

1. i=0; ist nur eine Zuweisung. i muss auch erstellt werden: int i = 0;
2. Was ist Key? diese (char?) Variable wird nur geprüft, aber nie zugewiesen.
3. scanf widerspricht der Aufgabenstellung ;) scanf macht viel alleine. Du sollst aber den harten Weg 'zu Fuß' gehen.
4. da i++ auskommentiert ist, bleibt i immer 0;
5. Du prüfst nur, ob ein Nullchar eingelesen wurde, nicht aber, ob das array bereits voll ist. Sowas führt zu memory-leaks.
6. Wenn das Array mit Nullen initialisiert wurde und das erste Zeichen nicht gültig ist, bricht die Methode ab, ohne etwas zu lesen.

Folgende Hinweise:
1. getchar ist schon der richtige Weg.
2. Ein Zeichen muss erst aus STDIN geholt werden, damit es auf gültigkeit geprüft werden kann.
2a. Verwende doch eine temporäre variable, dann bist du flexibler.
3. Die Prüfung, ob das letzte Zeichen im array eine 0 ist, ist in einigen Situationen nicht ganz sinnvoll. Schau mal hier nach, was getchar überhaupt zurückgibt, und versuche, eine andere Abrruchbedingung zu finden.
4. Beachte Fehler Nr. 5.

Ich hoffe, ich habe nichts vergessen und ich hab mich klar ausgedrückt.
Wenn das nicht hilft und du noch nicht weiterkommst, sag einfach bescheid ;)

Ele
0 Punkte
Beantwortet von doenercola Einsteiger_in (9 Punkte)
Das unglaubliche ist wahr geworden... Dank Dir hab ich es nun endlich geschafft! :D

Hier ist erstmal mein Code:

void string_fuellen_index()
{
i=0;
fflush(stdin);
printf("Bitte geben Sie eine Zeichekette ein: ");
do
{
Taste = getchar();
if ( (Taste >= 'A') && (Taste <= 'Z') || (Taste >= '0') && (Taste <= '9') || (Taste >= 'a') && (Taste <= 'z') )
szString_1Roh[i] = Taste;
i++;
if(i > 99)
{
printf("Bitte maximal nur %d Zeichen eingeben!\n", ZIFFERN_MAX);
}
}
while(Taste != '\n') ;
printf("\n1. Aufgabe - Eingelesener String:\n\t[%s]\n",szString_1Roh);

//printf("\n1. Aufgabe - Eingelesener String:\n\t[%s]\n",szString_1Roh);
}


Das mit fflush(stdin) soll unsauber sein, für meine Zwecke reicht es erstmal allemal, da vor dem Aufrufen der Prozedur der Benutzer eine Auswahl treffen muss, und somit bereits einmal Enter gedrückt hat.

Zu Deinen Hinweisen:
1. i hab ich als globale Variable deklariert gehabt, war nicht in dem Ausschnitt mit drin. :)
2. Key ist meine jetzige "Taste"Variable
3. Ja, leider ist das so, aber so lernt mans wenigstens :D
4. Da hatte ich das selbe Problem wie bei 2. --> Chaos in meinem Kopf und im Quellcode durch vieles rumprobieren, so dass ich selbst nicht mehr wusste wann was funktionierte und wann nicht
5. Die Abfrage hab ich jetzt eingefügt und sie funktioniert soweit, Ziffern_Max ist eine Konstante und in dem Fall auf 100 gesetzt.
6. Was meinst Du da genau? Das Array wurde zuvor noch nicht mit Werten belegt und wenn doch, wieso würde es da abbrechen? :)

Ganz liebe Grüße und ein herzliches Danke nochmal!

Döner
0 Punkte
Beantwortet von doenercola Einsteiger_in (9 Punkte)
Okay, die Abfrage wegen den Maximal 100 Zeichen funktioniert noch nicht ganz, ich bastel noch etwas rum. :)
0 Punkte
Beantwortet von Experte (3.2k Punkte)
Das ist doch schön :)

1. Achso. Ist in diesem Fall aber nicht nötig. Globale Variablen sind zu vermeiden, wo auch immer möglich.
2. Ja, hab ich mir nacher auch so gedacht, macht ja auch Sinn. Wo ist die Edit-Funktion, wenn man sie braucht?^^
4. Kennt man ;) Wird mit der Zeit aber auch besser/einfacher.
6. Nur weil du einer Variablen (oder halt nem Array) keinen Wert zuweist, heißt es nicht, dass keiner drinsteht. Speicher wird ja nicht ständig auf 0 gesetzt. Eine nicht initialisierte Variable kann also alles enthalten, und bei jedem Start etwas anderes.
Ausgehend von deiner Originalfunktion: Schlägt nun die Prüfung fehl, wird das erste Byte nicht überschrieben, enthält also weiterhin den 'zufälligen' Wert von vorher. Dieser wird nun in der while-Schleife gegen 0 geprüft. Hatte er vorher zufällig 0, wird halt abgebrochen. Ich hoffe, das ist nun verständlich ;)
Deine korrigierte Funktion hat das Problem nicht mehr, da du in jedem Fall das zuletzt gelesene Zeichen einliest.

Folgendes fällt mir noch auf:
1. i wird für jedes gelesene Zeichen inkrementiert, wahrscheinlich nur Klammern vergessen
2. Doch, die Abfrage funktioniert schon, nur die dann ausgeführte Aktion nicht ;) Du gibst nur einen Hinweis aus, machst aber sonst nichts. break z.B. könnte man machen.
3. Achso, hatte ich in A1 vergessen, ist mir erst später aufgefallen, als ich mal versucht hab, selber was zu schreiben. Dein String ist nach dem Einlesen nicht Nullterminiert. Das sollte man noch ändern, sowas kann (=wird sehr wahrscheinlich) zu ganz unschönen Ausgaben führen, wenn das Programm nicht grade im Debugger läuft.

Wie gesagt hatte ich ja mal was geschrieben, wie ich das machen würde:
//ich hab den string mal s genannt. ist kuerzer :)

#define ZIFFERN_MAX 100
char s[ZIFFERN_MAX];

void string_fuellen_index()
{
int i=0;
char c; //temporaere Variable
printf("Bitte eine Zeichenkette eingeben: ");
do
{
c=getchar();
if((c >= 'A' && c <= 'Z')||(c >= 'a' && c <= 'z')||(c >= '0' && c <= '9'))
{
s[i]=c; //Zeichen gueltig: in den String kopieren
++i; //und die Position erhoehen
}
//else: kopiere das Zeichen nicht in den String
} while(c!=0 && c!=EOF && i<ZIFFERN_MAX-1)
//wenn 0 oder EOF zurueckgegeben wurde oder der
//String bis auf ein Element (daher -1) voll ist,
//breche ab
s[i]=0; //Da eine 0 nicht in das Array geschrieben wird, da das
//Zeichen im Bereich A-Z, a-z, 0-9 liegen muss, wird hier noch
//die 0 an den String angehaengt
}

Muss aber dazu sagen, dass ich das nicht getestet habe. Es könnten sogar Syntaxfehler drin sein. Meine Funktion sieht deiner sehr ähnlich, wenn man mal vom Längenabbruch und der Prüfung auf \n bzw. EOF, sowie fflush(stdin) absieht. Da ist deines aber wahrscheinlich richtig, da ich mir bei diesen Sachen nie sicher bin und das auch erst n paar mal ausprobieren muss und es, wie gesagt, nicht getan hab^^

Ele
...