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.