-3

I have written a program in C that solved Sudoku puzzles. It works perfectly, and prints out the correct solved puzzle, however, just before the program should end, I get a segmentation fault and the program crashes. I am struggling to find where the problem is coming from.

Sorry for the large amount of code, but I thought it could help if you guys saw everything.

(Also sorry if there is any bad C practices, I am very noob.)

#include <stdio.h>
#include <math.h>
#include <stdbool.h>

struct table{
  int cells[9][9];
  bool fixed[9][9];
};

void enterNum(struct table* t);
void solver(struct table g);
void draw(struct table t);
bool checkInput(struct table* t);

int main(){
  setbuf(stdout, NULL);
  struct table t;
  struct table* tp = &t;

  int x, y;
  bool loop = true;
  while(loop == true){
    for(x = 0; x < 9; x++){
      for(y = 0; y < 9; y++){
        t.cells[x][y] = 0;
      }
    }
    draw(t);
    enterNum(tp);
    draw(t);

    if(checkInput(tp)){
      loop = false;
    }else{
      printf("\n Invalid Soduku Puzzle\n");
    }
  }
  solver(t);
  return 0;
}

void draw(struct table t){
  printf("\n%d %d %d | %d %d %d | %d %d %d\n", t.cells[0][0], t.cells[0][1], t.cells[0][2], t.cells[0][3], t.cells[0][4], t.cells[0][5], t.cells[0][6], t.cells[0][7], t.cells[0][8]);
  printf("%d %d %d | %d %d %d | %d %d %d\n", t.cells[1][0], t.cells[1][1], t.cells[1][2], t.cells[1][3], t.cells[1][4], t.cells[1][5], t.cells[1][6], t.cells[1][7], t.cells[1][8]);
  printf("%d %d %d | %d %d %d | %d %d %d\n", t.cells[2][0], t.cells[2][1], t.cells[2][2], t.cells[2][3], t.cells[2][4], t.cells[2][5], t.cells[2][6], t.cells[2][7], t.cells[2][8]);
  printf("---------------------\n");
  printf("%d %d %d | %d %d %d | %d %d %d\n", t.cells[3][0], t.cells[3][1], t.cells[3][2], t.cells[3][3], t.cells[3][4], t.cells[3][5], t.cells[3][6], t.cells[3][7], t.cells[3][8]);
  printf("%d %d %d | %d %d %d | %d %d %d\n", t.cells[4][0], t.cells[4][1], t.cells[4][2], t.cells[4][3], t.cells[4][4], t.cells[4][5], t.cells[4][6], t.cells[4][7], t.cells[4][8]);
  printf("%d %d %d | %d %d %d | %d %d %d\n", t.cells[5][0], t.cells[5][1], t.cells[5][2], t.cells[5][3], t.cells[5][4], t.cells[5][5], t.cells[5][6], t.cells[5][7], t.cells[5][8]);
  printf("---------------------\n");
  printf("%d %d %d | %d %d %d | %d %d %d\n", t.cells[6][0], t.cells[6][1], t.cells[6][2], t.cells[6][3], t.cells[6][4], t.cells[6][5], t.cells[6][6], t.cells[6][7], t.cells[6][8]);
  printf("%d %d %d | %d %d %d | %d %d %d\n", t.cells[7][0], t.cells[7][1], t.cells[7][2], t.cells[7][3], t.cells[7][4], t.cells[7][5], t.cells[7][6], t.cells[7][7], t.cells[7][8]);
  printf("%d %d %d | %d %d %d | %d %d %d\n\n", t.cells[8][0], t.cells[8][1], t.cells[8][2], t.cells[8][3], t.cells[8][4], t.cells[8][5], t.cells[8][6], t.cells[8][7], t.cells[8][8]);

 }

void enterNum(struct table* t){
  int oneone, onetwo, onethree, onefour, onefive, onesix, oneseven, oneeight, onenine, twoone, twotwo, twothree, twofour, twofive, twosix, twoseven, twoeight, twonine, threeone, threetwo, threethree, threefour, threefive, threesix, threeseven, threeeight, threenine, fourone, fourtwo, fourthree, fourfour, fourfive, foursix, fourseven, foureight, fournine, fiveone, fivetwo, fivethree, fivefour, fivefive, fivesix, fiveseven, fiveeight, fivenine, sixone, sixtwo, sixthree, sixfour, sixfive, sixsix, sixseven, sixeight, sixnine, sevenone, seventwo, seventhree, sevenfour, sevenfive, sevensix, sevenseven, seveneight, sevennine, eightone, eighttwo, eightthree, eightfour, eightfive, eightsix, eightseven, eighteight, eightnine, nineone, ninetwo, ninethree, ninefour, ninefive, ninesix, nineseven, nineeight, ninenine;

  char input[50];
  bool loop = true;
  while(loop){
    printf("Enter the numbers in the first line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &oneone, &onetwo, &onethree, &onefour, &onefive, &onesix, &oneseven, &oneeight, &onenine) != 9 || oneone < 0 || oneone > 9 || onetwo < 0 || onetwo > 9 || onethree < 0 || onethree > 9 || onefour < 0 || onefour > 9 || onefive < 0 || onefive > 9 || onesix < 0 || onesix > 9 || oneseven < 0 || oneseven > 9 || oneeight < 0 || oneeight > 9 || onenine < 0 || onenine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }
  loop = true;
  while(loop){
    printf("Enter the numbers in the second line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &twoone, &twotwo, &twothree, &twofour, &twofive, &twosix, &twoseven, &twoeight, &twonine) != 9 || twoone < 0 || twoone > 9 || twotwo < 0 || twotwo > 9 || twothree < 0 || twothree > 9 || twofour < 0 || twofour > 9 || twofive < 0 || twofive > 9 || twosix < 0 || twosix > 9 || twoseven < 0 || twoseven > 9 || twoeight < 0 || twoeight > 9 || twonine < 0 || twonine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }
  loop = true;
  while(loop){
    printf("Enter the numbers in the third line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &threeone, &threetwo, &threethree, &threefour, &threefive, &threesix, &threeseven, &threeeight, &threenine) != 9 || threeone < 0 || threeone > 9 || threetwo < 0 || threetwo > 9 || threethree < 0 || threethree > 9 || threefour < 0 || threefour > 9 || threefive < 0 || threefive > 9 || threesix < 0 || threesix > 9 || threeseven < 0 || threeseven > 9 || threeeight < 0 || threeeight > 9 || threenine < 0 || threenine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }

  loop = true;
  while(loop){
    printf("Enter the numbers in the fourth line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &fourone, &fourtwo, &fourthree, &fourfour, &fourfive, &foursix, &fourseven, &foureight, &fournine) != 9 || fourone < 0 || fourone > 9 || fourtwo < 0 || fourtwo > 9 || fourthree < 0 || fourthree > 9 || fourfour < 0 || fourfour > 9 || fourfive < 0 || fourfive > 9 || foursix < 0 || foursix > 9 || fourseven < 0 || fourseven > 9 || foureight < 0 || foureight > 9 || fournine < 0 || fournine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }

  loop = true;
  while(loop){
    printf("Enter the numbers in the fifth line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &fiveone, &fivetwo, &fivethree, &fivefour, &fivefive, &fivesix, &fiveseven, &fiveeight, &fivenine) != 9 || fiveone < 0 || fiveone > 9 || fivetwo < 0 || fivetwo > 9 || fivethree < 0 || fivethree > 9 || fivefour < 0 || fivefour > 9 || fivefive < 0 || fivefive > 9 || fivesix < 0 || fivesix > 9 || fiveseven < 0 || fiveseven > 9 || fiveeight < 0 || fiveeight > 9 || fivenine < 0 || fivenine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }

  loop = true;
  while(loop){
    printf("Enter the numbers in the sixth line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &sixone, &sixtwo, &sixthree, &sixfour, &sixfive, &sixsix, &sixseven, &sixeight, &sixnine) != 9 || sixone < 0 || sixone > 9 || sixtwo < 0 || sixtwo > 9 || sixthree < 0 || sixthree > 9 || sixfour < 0 || sixfour > 9 || sixfive < 0 || sixfive > 9 || sixsix < 0 || sixsix > 9 || sixseven < 0 || sixseven > 9 || sixeight < 0 || sixeight > 9 || sixnine < 0 || sixnine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }

  loop = true;
  while(loop){
    printf("Enter the numbers in the seventh line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &sevenone, &seventwo, &seventhree, &sevenfour, &sevenfive, &sevensix, &sevenseven, &seveneight, &sevennine) != 9 || sevenone < 0 || sevenone > 9 || seventwo < 0 || seventwo > 9 || seventhree < 0 || seventhree > 9 || sevenfour < 0 || sevenfour > 9 || sevenfive < 0 || sevenfive > 9 || sevensix < 0 || sevensix > 9 || sevenseven < 0 || sevenseven > 9 || seveneight < 0 || seveneight > 9 || sevennine < 0 || sevennine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }

  loop = true;
  while(loop){
    printf("Enter the numbers in the eighth line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &eightone, &eighttwo, &eightthree, &eightfour, &eightfive, &eightsix, &eightseven, &eighteight, &eightnine) != 9 || eightone < 0 || eightone > 9 || eighttwo < 0 || eighttwo > 9 || eightthree < 0 || eightthree > 9 || eightfour < 0 || eightfour > 9 || eightfive < 0 || eightfive > 9 || eightsix < 0 || eightsix > 9 || eightseven < 0 || eightseven > 9 || eighteight < 0 || eighteight > 9 || eightnine < 0 || eightnine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }

  loop = true;
  while(loop){
    printf("Enter the numbers in the ninth line of the puzzle, 0 for blanks:\n");
    if(fgets(input, 50, stdin) == NULL || sscanf(input, "%d %d %d %d %d %d %d %d %d", &nineone, &ninetwo, &ninethree, &ninefour, &ninefive, &ninesix, &nineseven, &nineeight, &ninenine) != 9 || nineone < 0 || nineone > 9 || ninetwo < 0 || ninetwo > 9 || ninethree < 0 || ninethree > 9 || ninefour < 0 || ninefour > 9 || ninefive < 0 || ninefive > 9 || ninesix < 0 || ninesix > 9 || nineseven < 0 || nineseven > 9 || nineeight < 0 || nineeight > 9 || ninenine < 0 || ninenine > 9){
      printf("Incorrect input. Try again:\n");
    }else{
      loop = false;
    }
  }

  t->cells[0][0] = oneone;
  t->cells[0][1] = onetwo;
  t->cells[0][2] = onethree;
  t->cells[0][3] = onefour;
  t->cells[0][4] = onefive;
  t->cells[0][6] = oneseven;
  t->cells[0][5] = onesix;
  t->cells[0][7] = oneeight;
  t->cells[0][8] = onenine;
  t->cells[1][0] = twoone;
  t->cells[1][1] = twotwo;
  t->cells[1][2] = twothree;
  t->cells[1][3] = twofour;
  t->cells[1][4] = twofive;
  t->cells[1][6] = twoseven;
  t->cells[1][5] = twosix;
  t->cells[1][7] = twoeight;
  t->cells[1][8] = twonine;
  t->cells[2][1] = threetwo;
  t->cells[2][0] = threeone;
  t->cells[2][2] = threethree;
  t->cells[2][3] = threefour;
  t->cells[2][4] = threefive;
  t->cells[2][5] = threesix;
  t->cells[2][6] = threeseven;
  t->cells[2][7] = threeeight;
  t->cells[2][8] = threenine;
  t->cells[3][0] = fourone;
  t->cells[3][1] = fourtwo;
  t->cells[3][3] = fourfour;
  t->cells[3][2] = fourthree;
  t->cells[3][4] = fourfive;
  t->cells[3][5] = foursix;
  t->cells[3][6] = fourseven;
  t->cells[3][7] = foureight;
  t->cells[3][8] = fournine;
  t->cells[4][0] = fiveone;
  t->cells[4][1] = fivetwo;
  t->cells[4][2] = fivethree;
  t->cells[4][3] = fivefour;
  t->cells[4][4] = fivefive;
  t->cells[4][6] = fiveseven;
  t->cells[4][5] = fivesix;
  t->cells[4][7] = fiveeight;
  t->cells[4][8] = fivenine;
  t->cells[5][0] = sixone;
  t->cells[5][2] = sixthree;
  t->cells[5][1] = sixtwo;
  t->cells[5][3] = sixfour;
  t->cells[5][4] = sixfive;
  t->cells[5][5] = sixsix;
  t->cells[5][6] = sixseven;
  t->cells[5][7] = sixeight;
  t->cells[5][8] = sixnine;
  t->cells[6][0] = sevenone;
  t->cells[6][1] = seventwo;
  t->cells[6][2] = seventhree;
  t->cells[6][3] = sevenfour;
  t->cells[6][5] = sevensix;
  t->cells[6][4] = sevenfive;
  t->cells[6][6] = sevenseven;
  t->cells[6][8] = sevennine;
  t->cells[6][7] = seveneight;
  t->cells[7][0] = eightone;
  t->cells[7][1] = eighttwo;
  t->cells[7][2] = eightthree;
  t->cells[7][4] = eightfive;
  t->cells[7][3] = eightfour;
  t->cells[7][5] = eightsix;
  t->cells[7][6] = eightseven;
  t->cells[7][7] = eighteight;
  t->cells[7][8] = eightnine;
  t->cells[8][0] = nineone;
  t->cells[8][1] = ninetwo;
  t->cells[8][2] = ninethree;
  t->cells[8][3] = ninefour;
  t->cells[8][4] = ninefive;
  t->cells[8][5] = ninesix;
  t->cells[8][6] = nineseven;
  t->cells[8][7] = nineeight;
  t->cells[8][8] = ninenine;
}

bool checkInput(struct table* t){

  for(int z = 0; z < 9; z ++){
    for(int y = 0; y < 9; y++){
      for(int x = 0; x < 9; x++){
        if(t->cells[y][z] == t->cells[y][x] && t->cells[y][z] != 0 && z != x){
          return false;
        }
      }
    }
  }

  for(int z = 0; z < 9; z ++){
    for(int y = 0; y < 9; y++){
      for(int x = 0; x < 9; x++){
        if(t->cells[z][y] == t->cells[x][y] && t->cells[z][y] != 0 && z != x){
          return false;
        }
      }
    }
  }

  for(int x = 0; x < 3; x++ ){
    for(int y = 0; y < 3; y ++){
      for(int m = 0; m < 3; m++){
        for(int n = 0; n < 3; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 3; x < 6; x++ ){
    for(int y = 0; y < 3; y ++){
      for(int m = 3; m < 6; m++){
        for(int n = 0; n < 3; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 6; x < 9; x++ ){
    for(int y = 0; y < 3; y ++){
      for(int m = 6; m < 9; m++){
        for(int n = 0; n < 3; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 0; x < 3; x++ ){
    for(int y = 3; y < 6; y ++){
      for(int m = 0; m < 3; m++){
        for(int n = 3; n < 6; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 3; x < 6; x++ ){
    for(int y = 3; y < 6; y ++){
      for(int m = 3; m < 6; m++){
        for(int n = 3; n < 6; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 6; x < 9; x++ ){
    for(int y = 3; y < 6; y ++){
      for(int m = 6; m < 9; m++){
        for(int n = 3; n < 6; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 0; x < 3; x++ ){
    for(int y = 6; y < 9; y ++){
      for(int m = 0; m < 3; m++){
        for(int n = 6; n < 9; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 3; x < 6; x++ ){
    for(int y = 6; y < 9; y ++){
      for(int m = 3; m < 6; m++){
        for(int n = 6; n < 9; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  for(int x = 6; x < 9; x++ ){
    for(int y = 6; y < 9; y ++){
      for(int m = 6; m < 9; m++){
        for(int n = 6; n < 9; n ++){
          if(t->cells[x][y] == t->cells[m][n] && x != m && y != n && t->cells[x][y] != 0){
            return false;
          }
        }
      }
    }
  }

  return true;
}

void solver(struct table g){

  struct table* t = &g;

  for(int x = 0; x < 9; x++){
    for(int y = 0; y < 9; y++){
      if(t->cells[x][y] != 0){
        t->fixed[x][y] = true;
      }else{
        t->fixed[x][y] = false;
      }
    }
  }

  for(int x = 0; x < 9; x++){
    for(int y = 0; y < 9; y++){
      if(t->fixed[x][y] == false){
        t->cells[x][y]++;
        while(!checkInput(t)){
            t->cells[x][y]++;
          }
        if(t->cells[x][y] == 10){
          t->cells[x][y] = 0;
          if(y == 0){
            y = 7;
            x = x -2;
            }else{
            y = y - 2;
          }
          while(t->fixed[x][y+1] == true){
            y--;
          }
        }
      }
    }
  }

  printf("Your solved puzzle is: \n");
  draw(g);

}
Vorkos
  • 212
  • 1
  • 11
  • 2
    Use a debugger. When `y` is 9, you'll be accessing out of bounds here: `while(t->fixed[x][y+1] == true)`. It's [undefined behaviour](https://en.wikipedia.org/wiki/Undefined_behavior). – P.P Nov 05 '16 at 18:35
  • Run a debug build in a debugger, and it will catch the crash when it happens. You can then locate where in your code it happens and also examine the values of variables involved to see if they are okay and valid. – Some programmer dude Nov 05 '16 at 18:36
  • `while(t->fixed[x][y+1] == true){ y--; }` ... also `y` can go below zero if the sentinel is not found. – wildplasser Nov 05 '16 at 18:37
  • 1
    If you are on Mac or Linux, you could also try using *valgrind* to find out where the crash happens. Also "works perfectly but crashes" is kinda contradictory :) – hyde Nov 05 '16 at 18:48

1 Answers1

0

Do not cross table boundaries with the y index below 0 or above 8 and add protections to your all while loops eg:

    while  ( (y>=-1) && (y < 8) && (t->fixed[x][y+1] == true) ) {...}

    while  ( (y>= 1) && (y < 8) && (t->fixed[x][y+1] == true) ) {y--;}
sg7
  • 6,108
  • 2
  • 32
  • 40