-1

I’m trying to make a hangman game. Everything’s fine but the program passes the scanf. I don’t know why. You can try it on your own. Btw word.txt is a file so just create one and write a word into it.

Here is my code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char word[10];
char choice;

#define GAME_OVER 0
#define CHAR "_ "
#define draw_board() printf("\n"); for(int i = 0; i < strlen(word); i++) {printf(CHAR); if(i == strlen(word) - 1){printf("\n");}}
#define choice() printf("Your Choice? "); scanf("%c", &choice); if(strstr(word, &choice) != NULL){printf("ok");}

int main(void) {
    FILE *file = fopen("word.txt", "r");
    if(!file) {
        printf("file dosent exsist\n");
        exit(1);
    }
    fscanf(file, "%s", &word);
    int len = strlen(word);
    if(len < 4 || len > 10) {
        printf((len > 10) ? "the word is too long\n" : "the word is too short\n");
        exit(1);
    }
    while(!GAME_OVER) {
        draw_board();
        choice();
    }
    return  0;
}

Thanks for your time

user438383
  • 5,716
  • 8
  • 28
  • 43
  • 2
    Your `fscanf` is fine. Your use of macros to create your functions is a bit unorthodox. Your use of `strstr` is incorrect. You are using it on a pointer to a single character which is not a null terminated string. Try `strchr` instead. – lurker Oct 02 '21 at 14:22
  • 2
    Add a leading space to your scanf format: `scanf(" %c", &choice);` it will skip whitespace. Also use `strchr` instead of `strstr`. BTW: use functions instead of the `draw_board()` and `choice()` macros it will make the code way more readable. – dlivshen Oct 02 '21 at 14:24
  • 1
    Also change the name of `char choice`. Having that variable be the same name as your choice function is confusing and will be an error when you convert your macro properly to a function. – lurker Oct 02 '21 at 14:29
  • Thank you all it worked. But can someone explain what is the difference between %c and adding a space? – Guven Kerem Oct 02 '21 at 14:33
  • 1
    The length test `if(len < 4 || len > 10)` will allow a string length of 10 but that will overflow `char word[10]` (with terminator). I suggest `fscanf(file, "%9s", word)` and/or increase the array length. Note too the removal of `&` for an array parameter. – Weather Vane Oct 02 '21 at 14:35
  • From [scanf ref](https://www.cplusplus.com/reference/cstdio/scanf/): Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none). – dlivshen Oct 02 '21 at 14:36
  • Why the space? The `scanf` conversion stops at the first character it cannot convert, which is typically (but not necessarily) a space or a newline, and that character remains in the input buffer. It will be read by the *next* `scanf()`. Format specifiers `%d` and `%s` and `%f` automatically filter such leading whitespace characters, but `%c` and `%[]` and `%n` do not. You can instruct `scanf` to do so by adding a space just before the `%`. – Weather Vane Oct 02 '21 at 14:37
  • Got it, Thanks! – Guven Kerem Oct 02 '21 at 14:41

1 Answers1

0

Your "problem" is due to stdlib (scanf, getchar, gets and others) is initially buffer-oriented, or line-oriented. It means that the support routines will first read and entire line before the input reading functions effectively return with a single char read. In practice, when you read a single char, scanf will return that char only after one entire line is ready, and will read without pausing until the line is fully read one char at time and then will wait you type (supposing the input is from kb) until ENTER.

That's an extensive subject, I advise you some literature regarding buffered and unbuffered IO in C, and you can check the manuals about setvbuf() and fflush() library calls.

In addition, there are some errors in your program:

  • fscanf(file, "%s", &word); // &word results in char (*)[] type, that's wrong. The correct is: fscanf(file, "%s", word);
  • strstr(word, &choice) // &choice really results in char *, wich is correct for strstr, but in this case strstr's second parameter must be pointer to a string (pointer to the first char in a zero-delimited array). You should not look for a (sub)string in a string, but for a char in a string. It means you should use strchr instead of strstr: strchr(word, choice)

Some suggested readings:

regards