2

I was creating a word guessing game that reads a text file line per line until it finds a random word and stores it in a string (word). Then the user enters letters until all the letters of the stored word are revealed.

So far it works perfectly but every time it's the very first word that is read some unknown characters get stored at the beginning of char word[20].

Note that I use C mobile app and it uses clang 6.0 compiler I think. So does the error come from my code or it come from their app? (which I love).

Here is the FULL, clearer code:

//guess the right word

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

#define TRUE 1
#define FALSE 0
#define NB_OF_WORDS 3 //number of words in text file

main() {
    char begin, word[20] = { 0 }, guessedletter;
    int num, rightletter, success;
    int i = 0;
    int show[20] = { 0 };//shown letters

    FILE *ressource = NULL;
    srand(time(NULL));

    if ((ressource = fopen("ressource.txt", "r")) == NULL) {
        fprintf(stderr, "Error ressource.txt");//open in read only mode
        exit(EXIT_FAILURE);
    }

    printf("Welcome to Word Guess, a word guessing contest.\n"
           "You have to find the letters of a word and guess what word it is.\n"
           "Begin? (y/n)\n");

    while ((begin = getchar()) == 'y') { //game loop
        /*reinitializations*/
        fseek(ressource, 3, SEEK_SET);//replaces rewind(ressource)
        success = FALSE;
        rightletter = 0;
        num = 0;
        num = rand() % NB_OF_WORDS; //random number between 0 and NB-1
        for (i = 0; i < 20; i++) {
            show[i] = FALSE;
            word[i] = 0;
        }
        i = 0;
        /*end of reinitializations*/

        while (i <= num) {//reads line by line until random word is stored
            if (fgets(word, 20, ressource) == NULL) {
                fprintf(stderr, "fgets did not work");
                exit(EXIT_FAILURE);
            }
            i++;
        }

        printf("%s", word);//here is just for testing if the read word is well read. Which isn't the case if num=0 

        for (i = 0; i < 20; i++)
            if (word[i] == '\n')
                word[i] = '\0';//adds zero character to show where the string ends
        while (!success) { //guessing loop
            printf("\nWrite a letter: ");
            scanf("%c", &guessedletter);
            printf("\n");

            for (i = 0; word[i] != '\0'; i++) { //compares entered letter to letter from string. If they match...
                if (word[i] == guessedletter) {
                    if (!show[i])
                        rightletter++;//avoids letters entered twice from increasing count
                    show[i] = TRUE;
                }
                if (show[i])
                    printf("%c", word[i]);//...a letter is revealed...
                else
                    printf("*");//else it stays hidden
            }
            if (rightletter == strlen(word))
                success=TRUE;//if all the right letters found (same number of letters found as number of letters in the words) you win
        }

        printf("\nCongratulations you have won!\nDo you want to replay? (y/n)");
        getchar();//clears newline character
    }

    fclose(ressource);
    return 0;
}

When num=0, I get a weird sign before the printed word as if the first characters of the text file were not supposed to be there...

Moreover during the guessing game if the word to guess (word[20]) is "annoying" let's say and that it's the first word from "ressource.txt" (num=0). The word will print like so on the screen once I guessed all the letters: ***annoying. Which does not happen with ANY other words from the list.

I'm new to this site and post from my phone... sorry for any mistakes.

EDIT: removed fgetc for fgets. Still get several unknown characters if fgets reads first line.

EDIT 2: added the whole code, translated mot[20] into word[20], added error testing

EDIT 3: Replacing rewind(ressource); by fseek(ressource, 3, SEEK_SET); solved the problem. Which means there are indeed three unknown characters at the beginning of the text file

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Don't mix your input methods. What is that `while(begin=='y')` peeping in at the top? – Weather Vane Jul 21 '18 at 21:09
  • A scanf was called before the loop: scanf("%c", &begin); if you type yes the loop starts and restarts if you keep entering 'y' (yes) – Edge Of Light Jul 21 '18 at 21:43
  • 1
    Please see [scanf() leaves the newline char in the buffer](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer). That is waiting for `fgets` to collect, as well as your `scanf` not filtering whitespace (as shown in the link). – Weather Vane Jul 21 '18 at 21:44
  • I tried replacing scanf by getchar to avoid pesky new line characters and such... to no avail. However when I move the cursor three characters farther with fgetc(ressource) it starts at the beginning of the first word. But in the text file I just wrote one word per line. But this fgetc suggests three characters exist that I never wrote. I know there's EOF at the end of a file but is there a possiblity of hidden characters at the beginning? – Edge Of Light Jul 21 '18 at 22:18
  • 3
    Don't mix your input methods. If you are using `fgets` in the main loop, use it everywhere. Your phrase about "moving the cursor forwards" is nonsense. An input stream does not have a "cursor". – Weather Vane Jul 21 '18 at 22:19
  • But fgetc reads from the file doesn't it? I mean every time you call fgetc it will read the next character from input which is FILE *ressource here. Other wise you would always read the first character from the file. – Edge Of Light Jul 21 '18 at 23:32
  • Replacing rewind(ressource) by fseek(ressource, 3, SEEK_SET) worked! Thank you. – Edge Of Light Jul 22 '18 at 11:27
  • 2
    That file must be starting with the Unicode BOM. I bet these (unmentioned) characters are lowercase and with some accents, right? Check if the text editor you are using can save your file without a BOM. – Jongware Jul 22 '18 at 11:36
  • the latest, posted code, causes the compiler to output 4 warning messages. Always enable the warnings when compiling, then fix those warnings. – user3629249 Jul 22 '18 at 19:49

1 Answers1

2

There are multiple problems in the posted code:

  • You only posted a fragment of code, the rest of the function could cause problems that cannot be analysed from what you posted. Please post the complete code to a minimal program exhibiting the problem.
  • You do not test for end of file in the while loop. If you try to skip more lines than are present in the file, this loop will run indefinitely.
  • You do not test the return value of fgets(): if by chance you skipped the full contents of the file in the preceding while loop, fgets() will fail and return NULL, leaving mot in an undetermined state, causing unexpected behavior in the subsequent printf.

EDIT: the modified code still does not check the return value of fgets().

EDIT: thank you for posting the full code, but modifying the question this way makes this answer and the comments irrelevant.

Your dictionary file ressource.txt seems to start with a BOM (Byte Order Mark) encoded in UTF-8. I am guessing it contains French words including some with accented letters such as reculées and encodées... Your text editor saved it encoded in UTF-8 with an extra code-point at the beginning for other programs to determine this encoding easily. The problem with that is your program does not handle UTF-8. It assumes each byte read from stdin represents a single character. It might by chance match some words with accented letters, but will more likely fail to find them.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • the latest/modified code does not cleanly compile! Please correct the code – user3629249 Jul 22 '18 at 19:50
  • @user3629249: the OP's latest code still has a few compilation warnings, I only changed the layout, not the code itself. To execute his program, you need a dictionary file `ressource.txt` (pardon my French), which he did not provide and which starts with a UTF-8 BOM sequence, causing the *funny* characters in the output. – chqrlie Jul 22 '18 at 21:31