PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Funktion soll string an main zurückliefern



Gorgoroth
01-05-2005, 00:57
Hallo Leute,

ich schreibe immernoch das Hangmanspiel, jedoch hab ich diesmal versucht, das ganze mit Funktionen zu strukturieren. Leider scheitere ich daran, den Ratebegriff, der in der Funktion ratewort_eingeben eingegeben wird, zurück an main zu liefern, um diesen String dann z.B. an andere Funktionen weiter zu verteilen, die die Elemente des Strings dann z.B. in Striche umwandeln, testen ob der Buchstabe in "tipp" stimmt etc etc.
Hier der Code dazu. Leider seh ich ned, wo da der Fehler ist.

/***** Header-Files *****/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/***** Konstante *****/
#define MAX 80
#define JA 1
#define NEIN 0

/***** Funktionsprototypen *****/
char *ratewort_eingeben(void);
char tipp_speichern(void);
void striche_ausgeben(char *x);

int main(void)
{
char *wort,
tipp;

wort = *ratewort_eingeben();
tipp = tipp_speichern();
//striche_ausgeben(wort);

printf("Variable wort in main ..... %s\n", wort);

//printf("tipp in main ..... %c\n", tipp);

return 0;
}

char tipp_speichern(void)
{
char tipp;

puts("Bitte geben Sie einen Buchstaben ein, den Sie im Wort vermuten.");
do {
tipp = getchar();
} while( isspace( tipp ) );
printf("Sie glauben also, dass \"%c\" im Wort vorkommt.\n", tipp);

return tipp;
}

void striche_ausgeben(char *x)
{
int len,
i;
char strich = '-';
len = (strlen(x) - 1);

for (i = 0; i <= len; i++)
printf("%c", strich);

printf("\n");
}

char *ratewort_eingeben(void)
{
char puffer[MAX],
*y,
*x;

puts("Bitte geben Sie das Ratewort ein.");
scanf("%s", puffer);

x = malloc(strlen(puffer+1));
if (x == NULL)
{
puts("Fehler bei der Speicherreservierung!");
return 1;
}

x = puffer;

printf("Sie haben %s als Ratewort eingegeben.\n\n", x);

return x;
}

Danke schonmal im Vorraus,
Gorgoroth.

chrizel
01-05-2005, 01:46
1. in main muss es "wort = ratewort_eingeben();" heissen. d.h. ohne * ansonsten wuerdest du den pointer auf char ja dereferenzieren wollen zu einem char was wort nicht ist, weil wort einen pointer auf char speichert. (also string)
2. in ratewort_eingeben: Es muss "x = (char *)malloc(strlen(puffer)+1);" heissen. d.h. +1 gehoert ausserhalb von strlen. Zudem sollte fuer strlen string.h includiert werden. Das (char *) mach ich mal aus sauberkeit... auch wenns ohne auch geht.
3. in ratewort_eingeben: x = puffer; Ich denke du willst eigentlich den eingegebenen string von puffer nach x kopieren. Mit dieser Zuweisung kopierst du eigentlich nur den Pointer puffer auf x - der mit malloc angeforderte Speicher wird nicht verwendet. d.h. der vorher von malloc zurueckgegebene Zeiger wird nicht verwendet und x zeigt jetzt auf puffer. Um einen string zu kopieren solltest du die Funktion strcpy verwenden: strcpy(x, puffer);

Also hier eine leicht angepasst Version:


/***** Header-Files *****/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

/***** Konstante *****/
#define MAX 80
#define JA 1
#define NEIN 0

/***** Funktionsprototypen *****/
char *ratewort_eingeben(void);
char tipp_speichern(void);
void striche_ausgeben(char *x);

int main(void)
{
char *wort, tipp;

wort = ratewort_eingeben();
tipp = tipp_speichern();
//striche_ausgeben(wort);

printf("Variable wort in main ..... %s\n", wort);

//printf("tipp in main ..... %c\n", tipp);

return 0;
}

char tipp_speichern(void)
{
char tipp;

puts("Bitte geben Sie einen Buchstaben ein, den Sie im Wort vermuten.");
do {
tipp = getchar();
} while( isspace( tipp ) );
printf("Sie glauben also, dass \"%c\" im Wort vorkommt.\n", tipp);

return tipp;
}

char *ratewort_eingeben(void)
{
char puffer[MAX],
*y,
*x;

puts("Bitte geben Sie das Ratewort ein.");
scanf("%s", puffer);

x = (char *)malloc(strlen(puffer)+1);
if (x == NULL)
{
puts("Fehler bei der Speicherreservierung!");
exit(1);
}

strcpy(x, puffer);

printf("Sie haben %s als Ratewort eingegeben.\n\n", x);

return x;
}

Gorgoroth
01-05-2005, 01:55
Danke sehr! Und auch besten Danke für die Erklärungen :)

locus vivendi
01-05-2005, 11:49
Als korrekt würde ich das so aber immer noch nicht ansehen.
char puffer[MAX],
*y,
*x;

puts("Bitte geben Sie das Ratewort ein.");
scanf("%s", puffer);
Führt zu undefiniertem Verhalten wenn mindestens MAX Zeichen eingeben werden. Der in ratewort_eingeben angeforderte Speicher wird übrigens später nicht freigegeben.

char tipp;

puts("Bitte geben Sie einen Buchstaben ein, den Sie im Wort vermuten.");
do {
tipp = getchar();
} while( isspace( tipp ) );
Das ist ebenfalls gefährlich. Z.b. wenn getchar EOF zurückgibt und "char" auf dem verwendeten System unsigned ist. Dann wird isspace potentiell mit einem ungültigem Argument aufgerufen.

Außerdem ist das Programm stylistisch nicht schön, meiner Meinung nach. Z.b. werden unnötigerweise Variablen immer am Anfang der Funktion deklariert, auch wenn sie noch nicht gebraucht werden. Das "void" in den Parameterlisten ist zumindest auch unnötig. Das ist natürlich beides Geschmackssache. Und die Kommentare sind auch bestenfalls überflüssig. Das es sich um Konstanten und Funktionsprototypen handelt, sieht man ja. Und dann ist ein Kommentar sogar latent falsch, nämlich dieser " /***** Header-Files *****/ ". Nunja, es müssen keine "Files" sein, es sind einfach nur "Header".

Schlussendlich erlaube ich mir noch den Kommentar, dass ich denke, es wäre sinnvoller das ganze in C++ zu implementieren. Dann könnte man z.B. ratewort_eingeben einfacher implementieren.

Nur beispielhaft:


std::string ratewort_eingeben()
{

std::cout << "Bitte geben Sie das Ratewort ein.\n";
std::string wort;
std::cin >> wort;

std::cout << "Sie haben " << wort << " als Ratewort eingegeben.\n\n";

return wort;
}

locus vivendi
01-05-2005, 12:51
Code:
char tipp;

puts("Bitte geben Sie einen Buchstaben ein, den Sie im Wort vermuten.");
do {
tipp = getchar();
} while( isspace( tipp ) );

Das ist ebenfalls gefährlich. Z.b. wenn getchar EOF zurückgibt und "char" auf dem verwendeten System unsigned ist. Dann wird isspace potentiell mit einem ungültigem Argument aufgerufen.
Oder vielmehr wenn "char" signed ist, und EOF ungünstig definiert ist, wird isspace mit ungültigem Argument gerufen. Der Punkt ist jedenfalls, dass EOF nicht zuverlässig erkannt wird.

Gorgoroth
01-05-2005, 13:41
Danke locus vivendi. Mag sein, dass man dieses Programm leichter in C++ realisieren kann, jedoch ist der einzige Grund, warum ich es schreibe, der, C zu lernen ;)

Edit: eine Frage an dich, locus vivendi: Du meinst, die Geschichte mit dem puffer ist gefährlich? Warum? Weil man ihn überschreiben kann, wenn ich mehr als 80 Zeichen eingibt und dann womöglich wichtiger Speicher überschrieben wird?
Falls ja, die Bedenken hatte ich auch schon, aber was kann man da tun?

locus vivendi
01-05-2005, 14:40
Edit: eine Frage an dich, locus vivendi: Du meinst, die Geschichte mit dem puffer ist gefährlich? Warum? Weil man ihn überschreiben kann, wenn ich mehr als 80 Zeichen eingibt und dann womöglich wichtiger Speicher überschrieben wird?
Ja. Das wäre die naheliegendste Konsequenz.

Falls ja, die Bedenken hatte ich auch schon, aber was kann man da tun?
Der einfachste Weg, das Überschreiben des Puffers zu verhindern, ist eine Eingabefunktion zu verwenden, die höchstens eine bestimmte Anzahl Zeichen einliest. Dann ist da aber immer noch das Problem, das der Benutzer vielleicht ein noch längeres Wort hat, welches nicht vollständig gelesen wird (zugegebenermaßen ist die Wahrscheinlichkeit in der deutschen Sprache äußerst gering).
Um Wörter ohne zur Kompilierzeit vorgegeben Länge einlesen zu können, könnte man mehrstufig vorgehen. D.h. erst in einen kleineren Puffer einlesen, und dann je nach Bedarf einen Größeren Puffer anlegen und vom Kleinen in den Großen kopieren. Gegebenfalls wiederholen.

Gorgoroth
01-05-2005, 14:55
Wenn das Programm irgendwann mal fertig ist, dann werde ich mir über das Problem mit dem Puffer den Kopf zerbrechen. Fürs erste wäre das zu viel Aufwand für den Nutzen, da

(zugegebenermaßen ist die Wahrscheinlichkeit in der deutschen Sprache äußerst gering).