0

I'm recently working on simple chess game on the terminal using C, but I've ran into a small issue in regard to taking user input.

The following function takes in a 3-Dimensional array containing current chess piece placements, a pointer to a buffer that'll contain the user input, and the size of this buffer which I set to 7.

void next_move(char board[8][8][4], char* move, size_t buff_size){
 
         char * move_1 = (char )malloc(sizeof(char)3);
         char * move_2 = (char )malloc(sizeof(char)3);
         char delim[]=" ";
 
         getline(&move,&buff_size,stdin);
 
         move_1=strtok(move,delim);
         move_2=strtok(NULL,delim);
 
         if(*move_1 == '\0'){
                 printf("invalid move !");
                 return ;
         }
 
         printf("%s%s\n",move_1,move_2);
          if(!check_move(board, move_1, move_2)){
                 printf("valid move !\n");
 
         }
}

The function check_move takes in both moves inputted by the user and verifies if they're valid chess moves (E.g "Nb1 Nc3").

My issue lies in the fact that when the user inputs no character or a string of characters not containing a space (the delimeter defined in strtok) it results in a segmentation fault when I try to do the check:

if(*move_1 == '\0')

Which is used mainly to handle the exception in the case that the move_1 and move_2 pointers are null.

I have two questions:

  1. How can I check if a char pointer is null ? (I have already tried using move_1 == NULL)
  2. Why the does the code continue execution and returns if I set the conditional statement to if(*move_1 != 0). Although this causes all input (even if it's the correct format) to not be valid.
King
  • 3
  • 1
  • curious,, why a 3D array for a chess board? Writing 3D chess? – yano Jan 05 '22 at 19:46
  • 2
    `sizeof(char)3` -- is this typo present in your actual code? Please take care to provide a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). Your casts are also incorrect (and [not necessary](https://stackoverflow.com/q/605845/2505965)). Reassigning the buffers to the return values of `strtok` will surely leak memory. – Oka Jan 05 '22 at 19:47
  • Change `if(*move_1 == '\0')` to `if(move_1 == '\0')` – stark Jan 05 '22 at 19:48
  • Also, if you get NULL for move_1, you can't call strtok for move_2. – stark Jan 05 '22 at 19:49
  • Yeah, you'll get better answers if you can provide a [mcve] because then we don't have to guess about what might be going wrong, and we can get your code working perfectly on our own machines before submitting it as an answer. – David Grayson Jan 05 '22 at 19:57
  • Don't you get a warning about this`char * move_1 = (char )malloc(sizeof(char)3);` ?Something like *making pointer from integer*. You should not cast the result of `malloc` etc. and in your case you did even make an incorrect cast. – Gerhardh Jan 05 '22 at 20:24
  • The char casting was merely a typo, it's `(char *)malloc(sizeof(char)3)` but I'll be sure to remove the cast, thank you @Oka – King Jan 05 '22 at 20:36
  • @yano I'm using unicode to print out chess pieces. Using only a 2D array would only allow for one char (byte) to be written which isn't what I need. – King Jan 05 '22 at 20:38
  • ah ok. You're already well down that road, and should be fine I'm sure, but IMHO consider creating an `enum ChessPieces {EMPTY, /* rest of chess pieces */}`, then create an 8x8 2D array of that type. Perhaps a lookup table mapping enum value to name, complimenting a `printBoard` function. If you're determined to use unicode chars, another possibility would be to use 2D array of [wide character types, `wchar_t`](https://en.wikipedia.org/wiki/Wide_character). Just looks a bit odd to use a 3D data structure for a 2D game. – yano Jan 06 '22 at 06:41
  • I didn't think of those other ways tbh, using enums would be much better :). Thank you for the additional input! – King Jan 06 '22 at 14:10

2 Answers2

0

Question 1

It sounds like maybe move is NULL, but your first call to strtok is supposed to have a non-NULL pointer. Therefore, right after you call getline, I think you should check to make sure move is not NULL. It would also be a good idea to check that move_1 and move_2 are not NULL. You can do these checks with code like this:

getline(&move,&buff_size,stdin);
if (move == NULL) {
  // handle this case, probably with an early return
}

Note that the code above only shows a check for move, but I think you should probably do the same thing for move_1 and move_2, right after you assign to them, and before you use them or derefence them. (Some of these checks might turn out to be unnecessary upon further investigation, but for now I think the priority is to just fix all the segmenation faults so your program can run without crashing.)

Question 2

It sounds like you changed your code to the following and it started declaring all your input as invalid:

if(*move_1 != '\0'){
  printf("invalid move !");
  return;
}

Well, the explanation for that is simple. You are telling your compiler that if the first character of the move_1 string is not a null-termination character, that it should print "invalid move !" and return. Therefore, whenever move_1 is non-empty, it will do that. Maybe you meant to use == (equal) instead of != (not equals).

David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • Thanks a lot for the prompt reply :) The issue was indeed in the move_2 pointer being NULL. I was sure that the issue was with the if statement that I didn't bother checking that the move_2 pointer gets called without being checked in a later function call. The logic behind the second question is also cleared. – King Jan 05 '22 at 20:03
-1

If you mean by entering no characters that you are pressing enter that means your condition should be like: if(*move_1 == '\n'), since the Enter in a new line feed to the command line which is '\n' escape character.
I wish I can see your full project and work together to complete it...

ahmed deeb
  • 19
  • 5
  • This would only handle the exception of no input being fed, without checking if move_2 is null which would lead to a segmentation fault in the case of a string without a space. – King Jan 05 '22 at 21:06