E
Eric Lilja
Hello, consider the following complete program:
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
static int has_char(const char *, const char);
static void handle_guess(const char *, char *, const char);
int
main()
{
const char * words[] =
{
"hello", "usenet", "breakfast"
};
const char *actual = NULL;
char *current = NULL;
srand(time(NULL));
actual = words[rand() % 3];
current = calloc(strlen(actual) + 1, sizeof(char));
assert(current);
memset(current, '?', strlen(actual));
while(1)
{
char c = '\0';
if(!has_char(current, '?'))
break;
printf("The word is: %s\n", current);
printf("Type a letter: ");
c = getc(stdin);
getc(stdin);
handle_guess(actual, current, tolower(c));
}
printf("Congratulations! The word was: %s\n", current);
free(current);
return EXIT_SUCCESS;
}
static int
has_char(const char *str, const char c)
{
unsigned short i = 0;
for(i = 0; i < strlen(str); ++i)
if(str == c)
return 1;
return 0;
}
static int
find_position(const char *str, const char c, const unsigned short start)
{
unsigned short i = start;
if(start > strlen(str))
return -1;
for(i = start; i < strlen(str); ++i)
if(str == c)
return i;
return -1;
}
static void
handle_guess(const char *actual, char *current, const char c)
{
int position = 0;
assert(strlen(actual) == strlen(current));
if((position = find_position(actual, c, 0)) == -1)
{
printf("No match for the letter %c, sorry.\n", c);
return;
}
if(current[position] != '?')
{
printf("You already guessed the letter %c\n", c);
return;
}
current[position] = c;
while((position = find_position(actual, c, position + 1)) != -1)
{
assert(current[position] == '?');
current[position] = c;
}
}
It maintains a list of words and randomly selects a word from the list when
the program is started. The word is printed to the screen, but all
characters have been replaced with a '?'. The user is asked to guess a
letter in the word, and he if he guesses correctly the '?'s hiding that
particular letter is replaced with the letter itself. This continues until
the entire word has been revealed.
My problem is that the code for obtaining user input isn't very robust.
Say the user presses <tab>the_letter<enter>, it doesn't work anymore.
Whatever I type next, the character passed to handle_guess() is "messed up".
Here's a screen dump from such a session:
$ ./guess_word.exe
The word is: ?????????
Type a letter: b
The word is: b????????
Type a letter: a
The word is: b??a??a??
Type a letter: s <---- Here I typed <tab>s<Enter>
No match for the letter , sorry.
The word is: b??a??a??
Type a letter: i
No match for the letter
, sorry.
The word is: b??a??a??
Type a letter: t
No match for the letter
, sorry.
As you can see, it remains in a broken state because of that <tab>.
How can improve the code for dealing with user input so I can counter this
problem?
Any other comments regarding the code are welcome also.
/ E
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
static int has_char(const char *, const char);
static void handle_guess(const char *, char *, const char);
int
main()
{
const char * words[] =
{
"hello", "usenet", "breakfast"
};
const char *actual = NULL;
char *current = NULL;
srand(time(NULL));
actual = words[rand() % 3];
current = calloc(strlen(actual) + 1, sizeof(char));
assert(current);
memset(current, '?', strlen(actual));
while(1)
{
char c = '\0';
if(!has_char(current, '?'))
break;
printf("The word is: %s\n", current);
printf("Type a letter: ");
c = getc(stdin);
getc(stdin);
handle_guess(actual, current, tolower(c));
}
printf("Congratulations! The word was: %s\n", current);
free(current);
return EXIT_SUCCESS;
}
static int
has_char(const char *str, const char c)
{
unsigned short i = 0;
for(i = 0; i < strlen(str); ++i)
if(str == c)
return 1;
return 0;
}
static int
find_position(const char *str, const char c, const unsigned short start)
{
unsigned short i = start;
if(start > strlen(str))
return -1;
for(i = start; i < strlen(str); ++i)
if(str == c)
return i;
return -1;
}
static void
handle_guess(const char *actual, char *current, const char c)
{
int position = 0;
assert(strlen(actual) == strlen(current));
if((position = find_position(actual, c, 0)) == -1)
{
printf("No match for the letter %c, sorry.\n", c);
return;
}
if(current[position] != '?')
{
printf("You already guessed the letter %c\n", c);
return;
}
current[position] = c;
while((position = find_position(actual, c, position + 1)) != -1)
{
assert(current[position] == '?');
current[position] = c;
}
}
It maintains a list of words and randomly selects a word from the list when
the program is started. The word is printed to the screen, but all
characters have been replaced with a '?'. The user is asked to guess a
letter in the word, and he if he guesses correctly the '?'s hiding that
particular letter is replaced with the letter itself. This continues until
the entire word has been revealed.
My problem is that the code for obtaining user input isn't very robust.
Say the user presses <tab>the_letter<enter>, it doesn't work anymore.
Whatever I type next, the character passed to handle_guess() is "messed up".
Here's a screen dump from such a session:
$ ./guess_word.exe
The word is: ?????????
Type a letter: b
The word is: b????????
Type a letter: a
The word is: b??a??a??
Type a letter: s <---- Here I typed <tab>s<Enter>
No match for the letter , sorry.
The word is: b??a??a??
Type a letter: i
No match for the letter
, sorry.
The word is: b??a??a??
Type a letter: t
No match for the letter
, sorry.
As you can see, it remains in a broken state because of that <tab>.
How can improve the code for dealing with user input so I can counter this
problem?
Any other comments regarding the code are welcome also.
/ E