Unerwünschte Symbole - Mein erstes C-Programm
-
Erstmal vielen Dank für eure schnellen Antworten.
Ich habe jetzt erstmal alle Umlautfunktionen rausgenommen, um mich auf das Wesentliche im Programm zu konzentrieren.Ich poste mal den Code und hoffe, dass 134 Zeilen nicht zu viel sind.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define RATEN 7 #define MAX 100 void WortVerstecken(char *wort1, char *wort2, char const *pm){ int i; int j = strlen(wort1); for(i = 0; i <= j; i++){ // <-- zählt er so nicht einen mehr hoch als nötig... warum macht " i < j " bei der ausgabe probleme if(wort1[i] == ' '){ // leerzeichen suchen wort2[i] = ' '; } else if(strchr(pm, wort1[i])){ // satzzeichen suchen wort2[i] = wort1[i]; } else{ wort2[i] = '-'; // Buchstaben durch "-" ersetzen } } printf("%d\t%d\n", (int)strlen(wort2), i); } int main(void){ char zuratendeswort[MAX] = {0}; char geratenebuchstaben[30] = {0}; char meinbuchstabe; const char *pm = "!?.,"; //Satzzeichen int fehler = 0; int erraten = 0; int count = 0; int i; char *zgr; printf("Satz oder Wort eingeben : "); fgets(zuratendeswort, MAX, stdin); // wort eingeben und zeilenumbruch (\n) durch stringende (\0) ersetzen zgr = strrchr(zuratendeswort, '\n'); *zgr = '\0'; int wortlaenge = strlen(zuratendeswort); char daswort[wortlaenge]; printf("\n%s\n\n", zuratendeswort); // wort in großbuchstaben umwandel und in ein neuen char kopieren for(i=0; i <= wortlaenge; i++){ if(isalpha(zuratendeswort[i])){ daswort[i] = toupper(zuratendeswort[i]); } else{ daswort[i] = zuratendeswort[i]; } } printf("%s\n\n", daswort); // zeigt hinter dem wort irgendwelche zeichen an !!!! char versteckteswort[strlen(daswort)]; // <-- bei 8, 16, 32 usw. zeichen probleme beim erstellen des dummy !!!! // fügt dem dummy den ganzen satz zusätzlich an !!!! // !!!! // char *versteckteswort = malloc(strlen(daswort));// <-- fügt dem dummy ein unerwünschtes symbol an !!!! WortVerstecken(daswort, versteckteswort, pm); // Wort-Dummy erstellen while(strcmp(daswort, versteckteswort) != 0 && fehler != RATEN){ // Schleife verleassen wenn das Wort erraten wurde // oder "MAX" Fehler gemacht wurden printf("===============================================================================\n"); printf("\nBereits verwendete Buchstaben: "); for(i=0; i<(int)strlen(geratenebuchstaben); i++) // Liste der Bereits verwendeten Buchstaben { // Zeigt beim erten aufruf schon Symbole an !!!! printf("%c ", geratenebuchstaben[i]); } printf("\n\n"); printf(" Das Gesuchte Wort: %s\n\n", versteckteswort); printf(" Buchstabe eingeben: "); scanf("%c", &meinbuchstabe); fflush(stdin); // Buchstabe eingeben und in Großbuchstaben umwandeln if(isalpha(meinbuchstabe)){ meinbuchstabe = toupper(meinbuchstabe); } printf("\n===============================================================================\n"); if(!strrchr(geratenebuchstaben, meinbuchstabe)) // überprüfen ob der eingegeben Buchstabe { // noch nicht verwendet wurde. geratenebuchstaben[count] = meinbuchstabe; geratenebuchstaben[count+1] = '\0'; count++; for(i=0; i < strlen(daswort); i++){ if(daswort[i] == meinbuchstabe){ versteckteswort[i] = meinbuchstabe; // gefunden buchstaben in dummy kopieren erraten = 1; } } } else{ printf("\n!!! Den Buchstaben hattest du schon.\t>> %c\n\n", meinbuchstabe); } if(erraten == 0){ fehler++; printf("\n!!! Das war leider falsch.\t\t>> Du hast noch %d versuche.\n\n", RATEN - fehler); } else{ erraten = 0; printf("\n!!! Das war richtig.\n\n"); } } // Spielende: Ergebnis auswerten und passende Nachricht ausgeben if(fehler < 10){ printf("!!! Du hast das Wort erraten.\t>> %s\n\n\n", versteckteswort); } else{ printf("!!! Mehr Glueck beim naechsten mal.\n\n\n"); } return EXIT_SUCCESS; }
Wenn ich jetzt ein Wort eingebe, dessen länge der Malfolge der Acht entspricht, wird beim raten der erst Buchstabe nie gefunden.
-
Zeile 46: Kannste ersetzen durch zuratendeswort[strlen(zuratendeswort) - 1] = '\0';
Zeile 49: Es ist in C üblicher, Variablen am Anfang des Scopes zu deklarieren, da nicht alle Compiler das Schlucken.
Zeile 50: Das ist in C(89) nicht üblich, Arraygrößen müssen konstant sein. (Zur Compilezeit feststehen). Zudem brauchst du strlen() + 1 Platz, und die Variable "wortlaenge" ist sinnlos.Zeile 55: Die Schleife kopiert das '\0' am Ende nicht mit, (was im übrigen auch ein Fehler wäre, da "daswort" zu klein ist). Wie auch immer, du müsstest es mit kopieren um einen gültigen String zu erhalten.
Weiter habe ich erstmal nicht gelesen.
Edit:
Zeile 88: fflush(stdin) ist böse.
-
Danke für deine Hinweise.
Ich werde das Programm jetzt erstmal überarbeiten, und mit feste Arraygrößen arbeiten.
-
Den Zeilenumbruch und die Grossschreibung ein wenig anders zusammen gesetzt.
Zeile 40 bis 65:int i; printf("Satz oder Wort eingeben : "); fgets(zuratendeswort, MAX, stdin); // wort eingeben und zeilenumbruch (\n) durch stringende (\0) ersetzen int wortlaenge = strlen(zuratendeswort); char daswort[wortlaenge]; printf("\n%s\n\n", zuratendeswort); // wort in großbuchstaben umwandel und in ein neuen char kopieren for(i=0; i < wortlaenge-1; i++){ // nur bis \n lesen if(isalpha(zuratendeswort[i])){ daswort[i] = toupper(zuratendeswort[i]); } else{ daswort[i] = zuratendeswort[i]; } } daswort[i] = '\0'; // ihr wisst schon printf("%s\n\n", daswort); // zeigt hinter dem wort irgendwelche zeichen an !!!!
-
Danke dafür...
Das hat mir sehr geholfen. Ich hatte da eine kleinen Gedankenfehler.
Ein Array fängt ja immer bei Null an zu zählen, dass hatte ich in dem Moment nicht berücksichtigt.Mir ist auf gefallen, bei einem kleinen Test, dass auch ohne
daswort[i] = '\0';
das '\n' scheinbar verschwunden ist. Wie kommt das? Und, wurde der String dann trotzdem mit '\0' beendet?
Ich hatte das mit diesem kurzem Programm probiert.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 51 int main(void){ char zew[MAX] = {0}; char dmy[MAX] = {0}; int i; printf("Wort oder Satz eingeben: "); fgets(zew, MAX, stdin); for(i = 0; i < strlen(zew)-1; i++){ dmy[i] = zew[i]; } //dmy[i] = '\0'; printf("%s hat %d zeichen\n", dmy, strlen(dmy)); return EXIT_SUCCESS; }
-
egens schrieb:
Danke dafür...
Das hat mir sehr geholfen. Ich hatte da eine kleinen Gedankenfehler.
Ein Array fängt ja immer bei Null an zu zählen, dass hatte ich in dem Moment nicht berücksichtigt.Mir ist auf gefallen, bei einem kleinen Test, dass auch ohne
daswort[i] = '\0';
das '\n' scheinbar verschwunden ist. Wie kommt das? Und, wurde der String dann trotzdem mit '\0' beendet?
Ich hatte das mit diesem kurzem Programm probiert.
Die Null-Terminierung hast du bei deinem Testprogramm schon gegeben, weil die Arrays sauber initialisiert sind. Und das Newline hast du bei deiner for()-Schleife nicht mitkopiert (wozu soll die überhaupt gut sein?).
-
Darum geht es ja.
Newline sollte nicht mitkopiert werden.Jetzt ist der Groschen gefallen, just in dem Moment wo ich schreiben wollte, dass ich nicht verstehe warum das newlin nicht mitkopiert wurde...
Bei dem String "TEST\n" befindet sich newline im Array an vierter Stelle.
diese for-Schleife ...for(i=0; i < strlen("TEST\n")-1; i++);
... würde aber in diesem Fall nur so lange durchlaufen wie i kleiner ist als 4 und nicht bis 4, wo sich newline befindet. Somit wird es nicht mehr mitkopiert.
Manchmal sieht man den Wald vor lauter Bäumen nicht mehr.
-
egens schrieb:
Darum geht es ja.
Newline sollte nicht mitkopiert werden.Gegenfrage: Warum mußt du die Eingabe überhaupt kopieren - es geht doch wesentlich schneller, im Original-Array das Newline mit '\0' zu überschreiben als alle anderen Zeichen in ein zweites Array zu kopieren.
-
Das ist eigentlich nicht mehr wichtig. Ich habe das Programm schon dahingehend geändert, und der Text wird nicht mehr kopiert. Ich wollte nur wissen, warum ich vorher an dieser Stelle Probleme hatte. Wo mein Fehler war.
Damit ich ihn später nicht wiederhole.
-
So, um zu einem Abschluss zu kommen, hier der Code der ohne Probleme funktioniert.
Danke für eure Hilfe.#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX 51 #define VSH 7 int main(void){ char zew[MAX] = {0}; // Zu eratenes Wort char dmy[MAX] = {0}; // Dummy char bsn[30] = {0}; // Buchstaben char buf[3] = {0}; char ege; // Eingabe int wl = 0; // Wortlänge int zlr = 0; // zähler für Buchstaben int gdn = 0; // gefunden int flr = 0; // fehler int i; printf("Wort oder Satz eingeben: "); fgets(zew, MAX, stdin); wl = strlen(zew); for(i = 0; i < wl-1; i++){ // Dummy erstellen und Wort in Großbuchstaben umwandeln if(isalpha(zew[i])){ dmy[i] = '-'; zew[i] = toupper(zew[i]); } else{ dmy[i] = zew[i]; } } zew[i] = '\0'; while(strcmp(zew, dmy) != 0 && flr < VSH){ printf("===============================================================================\n\n"); printf("Bereits verwendete Buchstaben: "); for(i = 0; i < (int)strlen(bsn); i++){ printf("%c ", bsn[i]); } printf("\n\n"); printf(" Gesuchtes Wort bze. Satz: %s\n\n", dmy); printf(" Buchstabe eingeben: "); scanf("%c", &ege); fflush(stdin); printf("\n\n===============================================================================\n\n"); if(isalpha(ege)){ ege = toupper(ege); } if(!strchr(bsn, ege)){ bsn[zlr] = ege; zlr++; for(i = 0; i < wl-1; i++){ if(zew[i] == ege){ dmy[i] = ege; gdn = 1; } } } else{ printf("!!! Den Buchstaben hattest du schon.\t>> %c\n\n", ege); } if(gdn == 0){ flr++; printf("!!! Das war falsch.\t\t\t>> Noch %d Versuche.\n\n", VSH-flr); } else{ printf("!!! Das war richtig.\n\n"); gdn = 0; } } printf("===============================================================================\n\n"); if(flr < VSH){ printf("!!! Glueckwunsch, Du hast das gesuchte Wort erraten. >> %s\n\n\n", zew); } else{ printf("!!! Du hast leider Verloren. Mehr Glueck beim naechsten Mal.\n\n\n"); } return EXIT_SUCCESS; }
ps.: ja ih weiß fflush(stdin) ist böse
-
Hier noch mal eine Version von mir, vielleicht mal ganz nett für dich zu sehen, wie man das noch hätte machen können. (Jetzt kommt bestimmt gleich wieder einer der eine Verbesserung vorschlägt :D)
int compare(const char *base_str, char *dest_str, char c) { int rval = 0; while (*base_str) { if (*base_str == c) { *dest_str = c; ++rval; } ++base_str; ++dest_str; } return rval; } int main(int argc, char *argv[]) { char secret[0x100]; char word[0x100]; int i, counter = 0, c; printf("Enter secret word: "); fgets(secret, sizeof(secret), stdin); secret[strlen(secret) - 1] = '\0'; for (i = 0; i < strlen(secret); ++i) // geht schöner mit Pointern ;) { secret[i] = toupper(secret[i]); word[i] = '_'; } word[i] = '\0'; while (counter < 10) { printf("Enter char: "); while ((c = getchar()) == '\n') ; if (!compare(secret, word, toupper(c))) ++counter; printf("Actual word: %s\n", word); if (!strcmp(secret, word)) break; } if (counter >= 10) puts("Game over :("); if (counter < 10) puts("You win!"); return 0; }