Home > Enterprise >  segmentation fault while executing C hangman program with file pointer
segmentation fault while executing C hangman program with file pointer

Time:09-30

I made a hangman program using C programming language. It compiles(gcc) without an error, but it when I try to execute the program(./a.out), it gives me segmentation fault. I believe that it is due to the use of file pointer, because before adding the file pointer, it worked perfectly fine. After adding a file pointer to keep track of the score, it kept giving me segmentation fault. It compiles(gcc) without an error, but it when I try to execute the program(./a.out), it gives me segmentation fault. I need to know what exactly is causing the segmentation fault.

Here is the file pointer section of my code

// if the hero(word) was guessed correctly 
if (count == strlen(words[r])) {
   print_screen(words[r], answered, typed, state);
   printf("Congratulation! You have guessed the hero %s correctly!\n", words[r]);
    
   score  ;
   score_out_fp = fopen("ow_hangman_saved_score.data", "w"); // write
   fprintf(score_out_fp, "%d", score);
   fclose(score_out_fp);
   sleep(3);
   break;
}
// if over the threshold, break out of the loop(game over)
if (state >= 7) {
   print_screen(words[r], answered, typed, state);
   printf("Game over...\n");

   score--;
   score_out_fp = fopen("ow_hangman_saved_score.data", "w"); // write
   fprintf(score_out_fp, "%d", score);
   fclose(score_out_fp);
   sleep(3);
   break;
}

This is the entire code in case if it is not caused by the use of file pointer:

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

char *words[32] = {    "dva",
    "orisa",
    "reinhardt",
    "roadhog",
    "sigma",
    "winston",
    "wreckingball",
    "zarya",
    "ashe",
    "bastion",
    "doomfist",
    "echo",
    "genji",
    "hanzo",
    "junkrat",
    "mccree",
    "mei",
    "pharah",
    "reaper",
    "soldier",
    "sombra",
    "symmetra",
    "torbjorn",
    "tracer",
    "widowmaker",
    "ana",
    "baptiste",
    "brigitte",
    "lucio",
    "mercy",
    "moira",
    "zenyatta"};

void hangman_state(int state)
{
    if (state == 1) {
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("  nothing \n");
        printf("  happened\n");
        printf("          \n");
        printf("  yet...  \n");
        printf("          \n");
        printf("          \n");
        printf("6 guesses left\n");
    }
    else if (state == 2) {
        printf("    00    \n");
        printf("   0  0   \n");
        printf("    00    \n");
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("5 guesses left\n");
    }
    else if (state == 3) {
        printf("    00    \n");
        printf("   0  0   \n");
        printf("    00    \n");
        printf("    00    \n");
        printf("    00    \n");
        printf("    00    \n");
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("4 guesses left\n");
    }
    else if (state == 4) {
        printf("    00    \n");
        printf("   0  0   \n");
        printf("    00    \n");
        printf("   000    \n");
        printf("  0 00    \n");
        printf(" 0  00    \n");
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("3 guesses left\n");
    }
    else if (state == 5) {
        printf("    00    \n");
        printf("   0  0   \n");
        printf("    00    \n");
        printf("   0000   \n");
        printf("  0 00 0  \n");
        printf(" 0  00  0 \n");
        printf("          \n");
        printf("          \n");
        printf("          \n");
        printf("2 guesses left\n");
    }
    else if (state == 6) {
        printf("    00    \n");
        printf("   0  0   \n");
        printf("    00    \n");
        printf("   0000   \n");
        printf("  0 00 0  \n");
        printf(" 0  00  0 \n");
        printf("    0     \n");
        printf("   0      \n");
        printf(" 00       \n");
        printf("Final attempt\n");
    }
    else if (state == 7) {
        printf("    00    \n");
        printf("   0  0   \n");
        printf("    00    \n");
        printf("   0000   \n");
        printf("  0 00 0  \n");
        printf(" 0  00  0 \n");
        printf("    00    \n");
        printf("   0  0   \n");
        printf(" 00    00 \n");
        printf("You died...\n");
    }
}
// answered and typed can be replaced as int; char is used to save memory
void print_screen(char *word, char *answered, char *typed, int state)
{
    system("clear");
    for (int i = 0; i < strlen(word); i  ) {
        if (answered[i]) {
            printf(" %c ", word[i]);
        }
        else {
            printf(" _ ");
        }
    }
    printf("\n\n");

    for (int i = 0; i < 26; i  ) {
        if (typed[i]) {
            printf(" _ ");
        }
        else {
            printf(" %c ", 'A'   i);
        }
    }
    printf("\n\n");

    printf("-------------------------------------------------------------------------\n");
    hangman_state(state);
}

void input_ch(char *key, char *word, char *answered, char *typed, int state)
{
    struct termios ot, nt;

    tcgetattr(STDIN_FILENO, &ot);
    nt = ot;
    nt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &nt);

retry:
    print_screen(word, answered, typed, state);
    *key = getchar();
    if (*key < 'a' || *key > 'z') {
        printf("Type an alphabetical character\n");
        sleep(1);
        goto retry;
    }

    if (typed[*key - 'a']) {
        printf("The character has been guessed already\n");
        sleep(1);
        goto retry;
    }

    typed[*key - 'a'] = 1;

    tcsetattr(STDIN_FILENO, TCSANOW, &ot);
}

int main(void) {
    int r;
    srand(time(0));
    int state = 1;
    FILE *score_in_fp = NULL; // 0
    FILE *score_out_fp = NULL;
    int score;

    // file pointer
    // "r" for read, "w" for write
    score_in_fp = fopen("ow_hangman_saved_score.data", "r"); // read
    // Ex) fscanf(file_pointer_variable, "string", &string);
    fscanf(score_in_fp, "%d", &score);
    fclose(score_in_fp);

    printf("Current score: %d\n", score);
        sleep(3);
    // score_out_fp = fopen("ow_hangman_score.txt", "w"); // write
    // fprintf(score_out_fp, "The score is %d", &score);
    // fclose(score_out_fp);


    while(1) {
        r = rand() %32;

        // guessing a character
        char guess = 0;
        char answered[strlen(words[r])];
        char typed[26] = {0,};
        memset(answered, 0x0, strlen(words[r]));
        state = 1;

        while(1) {

            input_ch(&guess, words[r], answered, typed, state);

            int hit = 0;
            for (int i = 0; i < strlen(words[r]); i  ) {
                if (words[r][i] == guess) {
                    answered[i] = 1;
                    hit = 1;
                }
            }
            if (!hit) {
                state  ;
            }

            int count = 0;
            for (int i = 0; i < strlen(words[r]); i  ) {
                if (answered[i]) {
                    count  ;
                }
            }

// if the hero(word) was guessed correctly 
            if (count == strlen(words[r])) {
                print_screen(words[r], answered, typed, state);
                printf("Congratulation! You have guessed the hero %s correctly!\n", words[r]);

                score  ;
                score_out_fp = fopen("ow_hangman_saved_score.data", "w"); // write
                fprintf(score_out_fp, "%d", score);
                fclose(score_out_fp);
                sleep(3);
                break;
            }

            // if over the threshold, break out of the loop
            if (state >= 7) {
                print_screen(words[r], answered, typed, state);
                printf("Game over...\n");

                score--;
                score_out_fp = fopen("ow_hangman_saved_score.data", "w"); // write
                fprintf(score_out_fp, "%d", score);
                fclose(score_out_fp);
                sleep(3);
                break;
            }
        }
    }

    return 0;
}

Sorry if I didn't provide sufficient information or if I didn't articulate my question very well. This is my first time asking a question in stack overflow. Thank you so much for everyone who attempts to help me out with this problem :)

CodePudding user response:

Without the file ow_hangman_saved_score.data in the current directory the program will crash in fscanf(score_in_fp, "%d", &score); as previous fopen() fails with NULL:

score_in_fp = fopen("ow_hangman_saved_score.data", "r");
if(!score_in_fp) {
  // handle error
}

You should check the error irregardless but you can also use "a" instead of "r" if you want a new file created if it's missing.

  •  Tags:  
  • c
  • Related