Minimax going in order(Tic Tac Toe) - c

I'm currently trying to make use of the Minimax Algorithm and create a "Unbeatable Computer Player". I'm banging my head with this one for hours now and I cant seem to figure out why the "Computer" is going in order and not making the right decisions. Does anybody have an idea? maybe something sticks out for you I can't put my finger on what's wrong honestly. I bet it has something to do with the recursive call but I'm lost here.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
char BOARD[9][4];
void createBoard(){
for(int i = 0;i < 9;i++){
strcpy(BOARD[i], "[]");
}
strcpy(BOARD[6], "[X]");
strcpy(BOARD[1], "[O]");
strcpy(BOARD[3], "[X]");
}
void printBoard(){
printf("\n\n");
for(int i = 0;i < 9;i++){
printf("%s", BOARD[i]);
if((i + 1) % 3 == 0){
printf("\n");
}
}
printf("\n\n");
}
void makeMove(char* player, int position){
char playerFinal[5];
strcpy(playerFinal, "[");
strcat(playerFinal, player);
strcat(playerFinal, "]");
if(strcmp(BOARD[position], "[]") == 0){
strcpy(BOARD[position], playerFinal);
}
}
bool movesLeft(){
for(int i = 0;i < 9;i++){
if(strcmp(BOARD[i], "[]") == 0){
return true;
}
}
return false;
}
char* isWinner(){
for(int i = 0;i < 9;i = i + 3){
if(strcmp(BOARD[i], BOARD[i + 1]) == 0 && strcmp(BOARD[i + 1], BOARD[i + 2]) == 0){
if(strcmp(BOARD[i], "[X]") == 0){
return "X";
}
else if(strcmp(BOARD[i], "[O]") == 0){
return "O";
}
}
}
for(int i = 0;i < 3;i++){
if(strcmp(BOARD[i], BOARD[i + 3]) == 0 && strcmp(BOARD[i + 3], BOARD[i + 6]) == 0){
if(strcmp(BOARD[i], "[X]") == 0){
return "X";
}
else if(strcmp(BOARD[i], "[O]") == 0){
return "O";
}
}
}
if(strcmp(BOARD[0], BOARD[4]) == 0 && strcmp(BOARD[4], BOARD[8]) == 0){
if(strcmp(BOARD[0], "[X]") == 0){
return "X";
}
else if(strcmp(BOARD[0], "[O]") == 0){
return "O";
}
}
if(strcmp(BOARD[2], BOARD[4]) == 0 && strcmp(BOARD[4], BOARD[6]) == 0){
if(strcmp(BOARD[2], "[X]") == 0){
return "X";
}
else if(strcmp(BOARD[2], "[O]") == 0){
return "O";
}
}
if(!movesLeft()){
return "tie";
}
return "";
}
int minimax(bool isMaximizing){
char* winner = isWinner();
printf("Function Called\n");
printf("%s", winner);
if(strcmp(winner, "O") == 0){
return 10;
}
if(strcmp(winner, "X") == 0){
return -10;
}
if(strcmp(winner, "tie") == 0){
return 0;
}
if(isMaximizing){
int score;
int bestScore = -1000000;
for(int i = 0;i < 9;i++){
if(strcmp(BOARD[i], "[]") == 0){
makeMove("O", i);
score = minimax(false);
strcpy(BOARD[i], "[]");
if(score > bestScore){
bestScore = score;
}
}
}
return bestScore;
}
else{
int score;
int bestScore = 1000000;
for(int i = 0;i < 9;i++){
if(strcmp(BOARD[i], "[]") == 0){
makeMove("X", i);
score = minimax(true);
strcpy(BOARD[i], "[]");
if(score < bestScore){
bestScore = score;
}
}
}
return bestScore;
}
}
void bestMove(){
int bestScore = -1000;
int position;
for(int i = 0;i < 9;i++){
if(strcmp(BOARD[i], "[]") == 0){
int score;
makeMove("O", i);
score = minimax(false);
strcpy(BOARD[i], "[]");
printf("Position %d\n", i);
printf("Best Score %d\n", bestScore);
printf("Score %d\n", score);
if(score > bestScore){
bestScore = score;
position = i;
}
}
}
makeMove("O", position);
}
int main(){
int position;
createBoard();
printBoard();
bool player = true;
char* winner = "";
while(strcmp(winner, "") == 0){
if(player){
printf("Its the Players Turn\nChoose a Position: ");
scanf("%d", &position);
makeMove("X", position -1);
player = false;
winner = isWinner();
}
else{
printf("Its the Computers Turn");
bestMove();
player = true;
winner = isWinner();
}
printBoard();
}
printf("The Winner is: %s\n", winner);
return 0;
}

Related

Connect four game, if statement

Here is code for my connect four game for exam. There are seven columns, if a number above 7 is entered it should say "Move not allowed", but if 0 is entered it should save the game.
When I enter 0 it says "Move not allowed". There is a code to save the game when 0 is entered but it says "Move not allowed" and doesn't go there. Can someone help?
#include <stdio.h>
#include <string.h>
typedef struct gameState{
int id;
char board[6][7];
int numberOfMoves;
char player1Name[20];
char player2Name[20];
}GameState;
void ShowMenu() {
printf("\n\n\n1. New Game \n");
printf("2. Load Game \n");
printf("3. Exit \n\n");
printf("Choose: ");
}
void ReadPlayerNames(char player1Name[20], char player2Name[20]) {
printf("\nName of first player:");
scanf("%s", player1Name);
printf("\nName of second player:");
scanf("%s", player2Name);
}
void PrintBoard(char board[6][7])
{
char header[] = " 1 2 3 4 5 6 7 ";
char border[] = "|---|---|---|---|---|---|---|";
printf("%s\n", header);
printf("%s\n", border);
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 7; j++)
{
printf("| %c ", board[i][j]);
}
printf("|\n");
printf("%s\n", border);
}
}
void ClearBoard(char board[6][7]) {
for (int i = 0; i < 6; i++){
for (int j = 0; j < 7; j++) {
board[i][j] = ' ';
}
}
}
// 1 - X wins, 2 - O wins, 0 - still playing
int CheckDiagonals(char board[6][7], int i, int j, int goUpRight){
int connectedO = 0;
int connectedX = 0;
while(i >= 0){
if (board[i][j] != ' '){
if (board[i][j] == 'X'){
connectedX++;
connectedO = 0;
if (connectedX == 4){
if (goUpRight = 0){
board[i][j] = 'Y'; //checking if x won, putting Y on places of x
board[i + 1][j + 1] = 'Y';
board[i + 2][j + 2] = 'Y';
board[i + 3][j + 3] = 'Y';
} else {
board[i][j] = 'Y';
board[i + 1][j - 1] = 'Y';
board[i + 2][j - 2] = 'Y';
board[i + 3][j - 3] = 'Y';
}
return 1;
}
} else {
connectedO++;
connectedX = 0;
if (connectedO == 4){
if (goUpRight = 0){
board[i][j] = 'Y';
board[i + 1][j + 1] = 'Y'; //checking if o won, putting Y on places of o
board[i + 2][j + 2] = 'Y';
board[i + 3][j + 3] = 'Y';
} else {
board[i][j] = 'Y';
board[i + 1][j - 1] = 'Y';
board[i + 2][j - 2] = 'Y';
board[i + 3][j - 3] = 'Y';
}
return 2;
}
}
} else {
connectedO = 0;
connectedX = 0;
}
i--;
if (goUpRight == 1){
j++;
}else{
j--;
}
}
return 0;
}
// 1 - X wins, 2 - O wins, 0 - still playing
int CheckRowsOrCols(char board[6][7], int rows){
int connectedO = 0;
int connectedX = 0;
int brI = 6;
int brJ = 7;
if (rows == 0){
brI = 7;
brJ = 6;
}
for (int i = 0; i < brI; i++){
for (int j = 0; j < brJ; j++) {
int pI = i, pJ = j;
if (rows == 0){
pI = j;
pJ = i;
}
if (board[pI][pJ] != ' '){
if (board[pI][pJ] == 'X'){
connectedX++;
connectedO = 0;
if (connectedX == 4){
if (rows == 0){
board[pI][pJ] = 'Y';
board[pI - 1][pJ] = 'Y';
board[pI - 2][pJ] = 'Y';
board[pI - 3][pJ] = 'Y';
} else {
board[pI][pJ] = 'Y';
board[pI][pJ - 1] = 'Y';
board[pI][pJ - 2] = 'Y';
board[pI][pJ - 3] = 'Y';
}
return 1;
}
} else {
connectedO++;
connectedX = 0;
if (connectedO == 4){
if (rows == 0){
board[pI][pJ] = 'Y';
board[pI - 1][pJ] = 'Y';
board[pI - 2][pJ] = 'Y';
board[pI - 3][pJ] = 'Y';
} else {
board[pI][pJ] = 'Y';
board[pI][pJ - 1] = 'Y';
board[pI][pJ - 2] = 'Y';
board[pI][pJ - 3] = 'Y';
}
return 2;
}
}
} else {
connectedO = 0;
connectedX = 0;
}
}
}
return 0;
}
// 1 - X wins, 2 - O wins, 0 - still playing
int CheckForWinner(char board[6][7]) {
int rezultat = CheckRowsOrCols(board, 1);
if (rezultat != 0){
return rezultat;
}
rezultat = CheckRowsOrCols(board, 0);
if (rezultat != 0){
return rezultat;
}
for (int i = 0; i < 6; i++){
rezultat = CheckDiagonals(board, i, 0, 1);
if (rezultat != 0){
return rezultat;
}
}
for (int j = 0; j < 7; j++){
rezultat = CheckDiagonals(board, 5, j, 1);
if (rezultat != 0){
return rezultat;
}
rezultat = CheckDiagonals(board, 5, j, 0);
if (rezultat != 0){
return rezultat;
}
}
for (int i = 0; i < 6; i++){
rezultat = CheckDiagonals(board, i, 6, 0);
if (rezultat != 0){
return rezultat;
}
}
return 0;
}
void SaveGame(char board[6][7], int movesPlayed, char player1Name[20], char player2Name[20]){
printf("\n\n\nEnter ID for your game: ");
int id;
scanf("%d", &id);
GameState state;
state.id = id;
for (int i = 0; i < 6; i++){
for (int j = 0; j < 7; j++){
state.board[i][j] = board[i][j];
}
}
state.numberOfMoves = movesPlayed;
strcpy(state.player1Name, player1Name);
strcpy(state.player2Name, player2Name);
FILE *filePointer;
filePointer = fopen("SavedGames.dat", "ab");
if (filePointer == NULL){
printf("\nGames not found!");
return;
}
fwrite(&state, sizeof(state), 1, filePointer);
fclose(filePointer);
printf("\nGame with ID:%d saved!", id);
}
int MakeMove(char board[6][7], int movesPlayed, char player1Name[20], char player2Name[20]) {
char sign = 'X';
if (movesPlayed % 2 == 1){
sign = 'O';
}
int column;
while (1){
printf("\nChoose the column player %c(0 for save and exit): ", sign);
column;
scanf("%d", &column);
if (column >= 0 && column <= 7 && board[0][column-1] == ' '){
break;
}
printf("\nMove not allowed!\n");
}
if (column != 0){
for (int i = 6; i >= 0; i--) {
if (board[i][column-1] == ' ') {
board[i][column-1] = sign;
printf("\n\n\n");
break;
}
}
}else {
SaveGame(board, movesPlayed, player1Name, player2Name);
return 1;
}
return 0;
}
void PlayGame(char board[6][7], char player1Name[20], char player2Name[20], int movesPlayed){
while (1){
PrintBoard(board);
if (MakeMove(board, movesPlayed, player1Name, player2Name) == 1){
break;
}
movesPlayed++;
int result = CheckForWinner(board);
if (result != 0){
PrintBoard(board);
if (result == 1){
printf("\nX wins\n\n\n");
} else {
printf("\nO wins\n\n\n");
}
break;
}
if (movesPlayed == 42){
PrintBoard(board);
printf("\nTie!\n\n\n");
break;
}
}
}
void ListAllSavedGames(){
FILE *filePointer;
filePointer = fopen("SavedGames.dat", "rb");
if (filePointer == NULL){
printf("\nGames not played yet!");
return;
}
GameState state;
while(fread(&state, sizeof(state), 1, filePointer) == 1){
printf("\n%d, X: %s, O: %s, %d", state.id, state.player1Name, state.player2Name, (42 - state.numberOfMoves));
}
fclose(filePointer);
}
void ListAllPlayerGames(){
char playerName[20];
printf("\nName of player: ");
scanf("%s", playerName);
FILE *filePointer;
filePointer = fopen("SavedGames.dat", "rb");
if (filePointer == NULL){
printf("\nGames not played yet!");
return;
}
GameState state;
while(fread(&state, sizeof(state), 1, filePointer) == 1){
if (strcmp(playerName, state.player1Name) == 0 || strcmp(playerName, state.player2Name) == 0){
printf("\n%d, X: %s, O: %s, %d", state.id, state.player1Name, state.player2Name, (42 - state.numberOfMoves));
}
}
fclose(filePointer);
}
int ShowTheBoard(){
int ID;
printf("\nEnter ID: ");
scanf("%d", &ID);
FILE *filePointer;
filePointer = fopen("SavedGames.dat", "rb");
if (filePointer == NULL){
printf("\nGames not played yet!");
return;
}
int IDfound = 0;
GameState state;
while(fread(&state, sizeof(state), 1, filePointer) == 1){
if (ID == state.id){
IDfound = 1;
printf("\nX: %s, O: %s", state.player1Name, state.player2Name);
PrintBoard(state.board);
}
}
fclose(filePointer);
if (IDfound == 0){
return 1;
}
return 0;
}
int LoadAGame(){
int ID;
printf("\nEnter ID: ");
scanf("%d", &ID);
FILE *filePointer;
filePointer = fopen("SavedGames.dat", "rb");
if (filePointer == NULL){
printf("\nGames not played yet!");
return;
}
int IDfound = 0;
GameState state;
while(fread(&state, sizeof(state), 1, filePointer) == 1){
if (ID == state.id){
IDfound = 1;
PlayGame(state.board, state.player1Name, state.player2Name, state.numberOfMoves);
}
}
fclose(filePointer);
if (IDfound == 0){
return 1;
}
return 0;
}
void ShowLoadMenu(){
int returnToMainMenu = 0;
while (returnToMainMenu == 0){
printf("\n\n\n1. List all saved games\n");
printf("2. List all saved games for a particular player\n");
printf("3. Show the board of one of the saved games\n");
printf("4. Load a game\n");
printf("5. Return to main menu\n");
printf("Choose: ");
int choice;
scanf("%d", &choice);
switch(choice){
case 1:
ListAllSavedGames();
break;
case 2:
ListAllPlayerGames();
break;
case 3:
while (ShowTheBoard() == 1){
printf("ID not valid!");
}
break;
case 4:
while (LoadAGame() == 1){
printf("ID not valid!");
}
returnToMainMenu = 1;
break;
case 5:
returnToMainMenu = 1;
break;
default:
printf("Wrong choice, try again!");
}
}
}
int main(){
int endOfProgram = 0;
while (endOfProgram == 0){
char board[6][7];
char player1Name[20];
char player2Name[20];
int movesPlayed = 0;
ShowMenu();
int choice;
scanf("%d", &choice);
switch(choice){
case 1:
ClearBoard(board);
ReadPlayerNames(player1Name, player2Name);
PlayGame(board, player1Name, player2Name, movesPlayed);
break;
case 2:
ShowLoadMenu();
break;
case 3:
printf("Goodbye!");
endOfProgram = 1;
break;
default:
printf("Wrong choice, try again!");
}
}
}
Culprit is likely to be inside MakeMove:
if (column >= 0 && column <= 7 && board[0][column-1] == ' ') {
break;
}
if you pass 0 as column, the first 2 tests will indeed succeed (both 0 >= 0 and 0 <= 7 are true). But third one tries to use board[0][-1]. -1 is not a valid index and you are invoking UB.
If column is 0, you should not test anything else, so your test should be:
if (column == 0 || (column > 0 && column <= 7
&& board[0][column-1] == ' ')) {
break;
}

Eclipse Console Does't Output Anything

When I run my code, the console doesn't output anything. When I go into "debug as c application mode" and step into the makeBoard() method that is supposed to print stuff nothing is shown on the console. I can't work on this project if the console doesn't work.
Whenever I run my code with only makeBoard() in the int main(void) method, the console outputs what it's supposed to. However, when I add the rest of my code in the int main(void) method, nothing is shown in the console window.
I am very new to C and the eclipse IDE. Do I need to download something?
The makeBoard() method:
void makeBoard(){
printf("Row A: ");
for(int i = 0; i< rowAcounter; i++)
{
printf("O");
}
printf("\n");
printf("Row B: ");
for(int i = 0; i< rowBcounter; i++)
{
printf("O");
}
printf("\n");
printf("Row C: ");
for(int i = 0; i< rowCcounter; i++)
{
printf("O");
}
printf("\n");
}
My complete int main method and the rest of my program:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void makeBoard();
void nextTurn(int player);
void prompt(int turn);
_Bool isGameOver();
void done(int currentTurn);
void test();
void update();
int rowAcounter = 3;
int rowBcounter = 5;
int rowCcounter = 8;
int currentPlayer = 0; // 0= player 1's turn, 1
= player 2's turn
char firstIn;
char secondIn;
_Bool flag = 0;
int main(void){
makeBoard();
while(isGameOver() == 0){
prompt(currentPlayer);
update();
nextTurn(currentPlayer);
if(flag == 1){
break;
}
makeBoard();
}
done(currentPlayer);
return 0;
}
the rest of my code:
void update(){
poll: scanf(" %c%c", &firstIn, &secondIn);
int checkFirst = firstIn - 'A';
if((checkFirst < 0) || (checkFirst > 2))
{
printf("\n Try again, you ape.");
goto poll;
}
int checkSecond = secondIn - '0';
if((checkSecond < 0 ) || (checkSecond > 8)){
printf("\n Try again, you fricker.");
goto poll;
}
else if(checkFirst == 0){ // the player chose row A
if(checkSecond > 3){
printf("\n Try again, you frick.");
goto poll;
}
else{
rowAcounter = rowAcounter - checkSecond;
}
}
else if(checkFirst == 1){ // the player chose row B
if(checkSecond > 5){
printf("\n Try again, you headass.");
goto poll;
}
else{
rowBcounter = rowBcounter - checkSecond;
}
}
else{ // the player chose row C
if(checkSecond > 8)
{
printf("\n Try again!");
goto poll;
}
else{
rowCcounter = rowCcounter - checkSecond;
}
}
if(isGameOver() == 1){
flag = 1;
}
}
void nextTurn(int player){
if(player == 0){
player = 1;
}else
{
player = 0;
}
}
void prompt(int turn){
if(turn == 0){
printf("Player 1, make your move:");
}
else{
printf("Player 2, make your move:");
}
}
_Bool isGameOver(){
if((rowAcounter == 0) && (rowBcounter == 0) && (rowCcounter == 0)){
return 1;
}
else{
return 0;
}
}
void done(int currentTurn){
if(currentTurn == 0){
puts("Player 1 wins!");
}
else{
puts("Player 2 wins!");
}
}

Moving characters in 2d array

I tried to create a 8 x 8 checkers game. I am trying to move the hyphen ' _ ' in the 2d array to select the character 'X' that I want. I have created the if statement for detecting the hyphen ' _ ' but seem that my code isn't working, I really need help. I am new to programming.
#include <stdio.h>
void gameboard(char board[8][8])
{
int x, y;
for(x=0; x<8; x++)
{
for(y=0; y<8; y++)
{
printf("=---=");
}
printf("\n\n");
for(y=0;y<8;y++)
{
printf("| %c |",board[x][y]);
}
printf("\n\n");
}
for(x=0;x<8;x++)
{
printf("=---=");
}
}
void character(char board[8][8])
{
int x,y;
for(x=0;x<8;x++){
for(y=0;y<8;y++){
if(x<3){
if(x%2 == 0){
if(x%2 == 0){
board[x][y] = 'O';
}
if(y%2==1){
board[x][y]= ' ';
}
}
if(x%2 == 1){
if(y%2 == 0){
board[x][y] = ' ';
}
if(y%2 ==1){
board[x][y]= 'O';
}
}
}
if((x==3) || (x==4)){
board[x][y] = ' ';
}
if(x>4)
{
if(x%2 == 0){
if(y%2 == 0){
board[x][y] = 'X';
}
if(y%2 ==1){
board[x][y]= ' ';
}
}
if(x%2 == 1){
if(y%2 == 0){
board[x][y] = ' ';
}
if(y%2 ==1){
board[x][y]= 'X';
}
}
if(x==5 && y ==1)
{
if(x%2 == 1){
if(y%2 == 1){
board[x][y] = '_';
}
}
}
}
}
}
}
void playgame(char board[8][8])
{
int x=0, y=0, a, b, c=0,input;
char token;
printf("\n\n---START GAME---\n");
if(token == '_')
{
printf("Please select your token : ");
}
for(a=0; a<8; a++)
{
for(b=0; b<8; b++)
{
if(board[a][b] == token & c == 0)
{
x = a;
y = b;
c++;
}
}
}
printf("1 to go right\n");
printf("2 to go left\n");
printf("3 to go up left\n");
printf("4 to go up right\n");
printf("5 to go down left\n");
printf("6 to go down right\n");
printf("7 to select token\n");
fflush(stdin);
scanf("%i", &input);
if(input == 1)
{
board[x][y+2] = token;
y++;
}
else if(input == 2)
{
board[x][y-2] = token;
y--;
}
else if(input == 3)
{
board[x-1][y-1] = token;
x--;
y--;
}
else if(input == 4)
{
board[x-1][y+1] = token;
x--;
y++;
}
else if(input == 5)
{
board[x+1][y-1] = token;
x++;
y--;
}
else if(input == 6)
{
board[x+1][y+1] = token;
x++;
y++;
}
else
{
board[x][y] = token;
}
}
int main()
{
char bx[8][8];
gameboard(bx);
playgame(bx);
return 0;
}
You have to initialize the array, then use switch statement to calculate the new position based on input.
Save the old position and swap the content of the new cell with that of the old cell in the saved position.
int main()
{
char board[8][8];
int x, y;
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++)
board[x][y] = '.';
board[0][0] = '_';
int xpos = 0;
int ypos = 0;
while (1)
{
system("cls||clear");
//print board
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
printf("%c", board[x][y]);
printf("\n");
}
printf("Menu\n 1 left \n2 right \n3 up \n4 down \n");
int savex = xpos;
int savey = ypos;
int move = 0;
scanf("%d", &move);
char c;
while ((c = getchar()) != '\n' && c != EOF);
switch (move)
{
case 1: if (xpos > 0) xpos--; break;
case 2: if (xpos < 7) xpos++; break;
case 3: if (ypos > 0) ypos--; break;
case 4: if (ypos < 7) ypos++; break;
}
//swap position:
board[savex][savey] = '.';
board[xpos][ypos] = '_';
}
return 0;
}

How to distinguish new line from EOF while reading from file

I am trying to build a program that could add up binary numbers, of arbitrary length, separated by a whitespace. I don't want to be limited by a maximum number length, therefore I'm doing everything without built-in number types, only chars. I read the numbers from a file. I perform everything on stack.
I can't loop the part where I read and add numbers. My guess is that it's because I can't find a way to distinguish new line from EOF. The program works this way: I read first number and save it into first stack, then I read second number and save in second stack. Then I add it up, save into third stack and transfer it to first stack. I read next number, save it into second stack, add up and so on. So I basically want to loop the second reading and summing. Here is the source code part:
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&a , c)){
clearStack(&a);
printf("alloc error");
return 0;
}
}else{
clearStack(&a);
printf("error1");
return 0;
}
}
if( a.size == 0 ){
printf("error2");
return 0;
}
while (!feof(ifp)) {
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&b , c)){
clearStack(&a);
clearStack(&b);
printf("alloc error");
return 0;
}
}
else{
//clearStack(&a);
//clearStack(&b);
printf("error3");
//return 0;
}
}
if( b.size == 0 ){
if (a.size == 0){
printf("error4");
}
}
topA = a.size;
topB = b.size;
carry = 0;
while( topA > 0 || topB > 0) {
if ( ( topA > 0 ) ){
topA--;
if(a.data[topA] == '1'){
x = 1;
}else{
x = 0;
}
}else{
x = 0;
}
if ( ( topB > 0 ) ){
topB--;
if(b.data[topB] == '1'){
y = 1;
}else{
y = 0;
}
}else{
y = 0;
}
sum = x + y + carry;
if (sum == 2 || sum == 3){
carry = 1;
}else{
carry = 0;
}
if (sum == 1 || sum == 3) {
c = '1';
}else{
c = '0';
}
if(!push(&output , c)){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
if (carry == 1) {
if(!push(&output , '1')){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
clearStack(&a);
for (i=0; i < output.size; i++){
push(&a , output.data[i]);
}
clearStack(&b);
clearStack(&output);
} /*end of EOF while*/
For some reason, although it reads multiple times, it reads wrong and works only for 2 numbers. The file looks like this: "1 1", but when its "1 1 1" it will just add first 2 numbers. I don't know where am I making a mistake. Below I attach the whole source code. I invoke the program in console like this: ./program file. I know that the case is poorly described but can't do it in a better manner, I will add comments if anything is needed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct stack {
char *data;
int size;
};
int push(struct stack * s, char c){
char * newData = (char *)realloc( s->data , (s->size + 1) * sizeof(char));
if( newData ){
s->data = newData;
s->data[s->size]=c;
s->size++;
return 1;
}else{
return 0;
}
}
/* not needed */
char pop(struct stack * s){
if(s->size > 0){
char result = s->data[s->size-1];
char * newData = (char *)realloc( s->data , s->size - 1);
if( newData ){
s->data = newData;
s->size--;
return result;
}else{
return 0;
}
}
else{
return 0;
}
}
struct stack newStack(){
struct stack s;
s.data = NULL;
s.size = 0;
return s;
}
void clearStack(struct stack * s){
free(s->data);
s->data = NULL;
s->size = 0;
}
int main (int argc, char const * argv[])
{
struct stack a = newStack();
struct stack b = newStack();
int topA, topB, x , y, carry, sum,i , start;
struct stack output = newStack();
char c;
FILE *ifp;
if(argc!=2){printf("Usage: ./a.out input_file."); return(1);}
if(!(ifp = fopen(argv[1], "r"))){printf("Unable to open input file!"); return(2);}
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&a , c)){
clearStack(&a);
printf("alloc error");
return 0;
}
}else{
clearStack(&a);
printf("error1");
return 0;
}
}
if( a.size == 0 ){
printf("error2");
return 0;
}
while (!feof(ifp)) {
while( !isspace(c=(char)getc(ifp))) {
if( c == '0' || c == '1'){
if(!push(&b , c)){
clearStack(&a);
clearStack(&b);
printf("alloc error");
return 0;
}
}
else if (c == '\0' || c == ' ' || c == '\n'){
}
else{
//clearStack(&a);
//clearStack(&b);
printf("error3");
//return 0;
}
}
if( b.size == 0 ){
if (a.size == 0){
printf("error4");
//return 0;
}
}
topA = a.size;
topB = b.size;
carry = 0;
while( topA > 0 || topB > 0) {
if ( ( topA > 0 ) ){
topA--;
if(a.data[topA] == '1'){
x = 1;
}else{
x = 0;
}
}else{
x = 0;
}
if ( ( topB > 0 ) ){
topB--;
if(b.data[topB] == '1'){
y = 1;
}else{
y = 0;
}
}else{
y = 0;
}
sum = x + y + carry;
if (sum == 2 || sum == 3){
carry = 1;
}else{
carry = 0;
}
if (sum == 1 || sum == 3) {
c = '1';
}else{
c = '0';
}
if(!push(&output , c)){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
if (carry == 1) {
if(!push(&output , '1')){
clearStack(&a);
clearStack(&b);
clearStack(&output);
printf("alloc error");
return 0;
}
}
clearStack(&a);
for (i=0; i < output.size; i++){
push(&a , output.data[i]);
}
clearStack(&b);
clearStack(&output);
} /*end of EOF while*/
for (i=a.size - 1; i >= 0; i--){
if(a.data[i] == '1' || start){
start=1;
printf("%c", a.data[i]);
}
}
printf("\n");
clearStack(&a);
//clearStack(&b);
//clearStack(&output);
return 0;
}

Printing string pointers in c

So, essentially I have two files:
File 1:
//
// main.c
// frederickterry
//
// Created by Rick Terry on 1/15/15.
// Copyright (c) 2015 Rick Terry. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int size (char *g) {
int ofs = 0;
while (*(g+ofs) != '\0') {
++ofs;
}
return ofs;
}
int parse(char *g) {
// Setup
char binaryConnective;
int negated = 0;
// Looking for propositions
int fmlaLength = size(g);
if(fmlaLength == 0) {
return 1;
}
if(fmlaLength == 1) {
if(g[0] == 'p') {
return 1;
} else if (g[0] == 'q') {
return 1;
} else if (g[0] == 'r') {
return 1;
} else {
return 0;
}
}
// Now looking for negated preposition
if(fmlaLength == 2) {
char temp[100];
strcpy(temp, g);
if(g[0] == '-') {
negated = 1;
int negatedprop = parse(g+1);
if(negatedprop == 1) {
return 2;
}
}
}
// Checking if Binary Formula
char arrayleft[50];
char arrayright[50];
char *left = "";
char *right = "";
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int binarypresent = 0;
if(fmlaLength != 1 && fmlaLength != 2) {
if(g[0] == '-') {
int negatedBinary = parse(g+1);
if(negatedBinary == 1 || negatedBinary == 2 || negatedBinary == 3) {
return 2;
} else {
return 0;
}
}
int i = 0;
int l = 0;
int p = strlen(g);
for(l = 0; l < strlen(g)/2; l++) {
if(g[l] == '(' && g[p-l-1] == ')') {
i++;
}
}
for(int q = i; q < strlen(g); q++) {
if(g[q] == '(') {
numLeft++;
} else if(g[q] == ')') {
numRight++;
}
arrayleft[q] = g[q];
//printf("%c", arrayleft[i]);
//printf("%s", left);
if((numRight == numLeft) && (g[q+1] == 'v' || g[q+1] == '>' || g[q+1] == '^')) {
arrayleft[q+1] = '\0';
bclocation = q+1;
binaryConnective = g[q+1];
binarypresent = 1;
// printf("The binary connecive is: %c\n", binaryConnective);
break;
}
}
if(binarypresent == 0) {
return 0;
}
int j = 0;
for(int i = bclocation+1; i < strlen(g)-1; i++) {
arrayright[j] = g[i];
j++;
}
arrayright[j] = '\0';
left = &arrayleft[1];
right = &arrayright[0];
//printf("Printed a second time, fmla 1 is: %s", left);
int parseleft = parse(left);
// printf("Parse left result: %d\n", parseleft);
if(parseleft == 0) {
return 0;
}
int parseright = parse(right);
if(parseright == 0) {
return 0;
}
// printf("Parse right result: %d\n", parseleft);
if(negated == 1) {
return 2;
} else {
return 3;
}
}
return 0;
}
int type(char *g) {
if(parse(g) == 1 ||parse(g) == 2 || parse(g) == 3) {
if(parse(g) == 1) {
return 1;
}
/* Literals, Positive and Negative */
if(parse(g) == 2 && size(g) == 2) {
return 1;
}
/* Double Negations */
if(g[0] == '-' && g[1] == '-') {
return 4;
}
/* Alpha & Beta Formulas */
char binaryConnective;
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int binarypresent = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
bclocation = i+1;
binaryConnective = g[i+1];
binarypresent = 1;
break;
}
}
}
/* Connective established */
if(binaryConnective == '^') {
if(g[0] == '-') {
return 3;
} else {
return 2;
}
} else if(binaryConnective == '>') {
if(g[0] == '-') {
return 2;
} else {
return 3;
}
} else if (binaryConnective == 'v') {
if(g[0] == '-') {
return 2;
} else {
return 3;
}
}
}
return 0;
}
char bin(char *g) {
char binaryConnective;
char arrayLeft[50];
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
int j = 0;
arrayLeft[j++] = g[i];
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
arrayLeft[i+1] = '\0';
bclocation = i+1;
binaryConnective = g[i+1];
return binaryConnective;
}
}
}
return binaryConnective;
}
char *partone(char *g) {
char binaryConnective;
char arrayLeft[50];
char arrayRight[50];
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
int j = 0;
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
arrayLeft[j] = g[i];
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
arrayLeft[j+1] = '\0';
bclocation = i+1;
binaryConnective = g[i+1];
break;
}
}
j++;
}
int m = 0;
for(int k = bclocation+1; k < strlen(g)-1; k++) {
arrayRight[m] = g[k];
m++;
}
arrayRight[m] = '\0';
char* leftSide = &arrayLeft[0];
// printf("%s\n", leftSide);
// printf("%s\n", rightSide);
int k = 0;
k++;
return leftSide;
}
char *parttwo(char *g) {
char binaryConnective;
char arrayLeft[50];
char arrayRight[50];
int numLeft = 0;
int numRight = 0;
int bclocation = 0;
int i = 0;
if(g[0] == '(') {
i++;
}
if(g[0] == '-') {
i++;
if(g[1] == '(') {
i++;
}
}
int j = 0;
for(i; i < strlen(g); ++i) {
if(g[i] == '(') {
numLeft++;
} else if(g[i] == ')') {
numRight++;
}
arrayLeft[j] = g[i];
if(numRight == numLeft) {
if(g[i+1] == 'v' || g[i+1] == '>' || g[i+1] == '^') {
arrayLeft[j+1] = '\0';
bclocation = i+1;
binaryConnective = g[i+1];
break;
}
}
j++;
}
int m = 0;
int n = size(g) - 1;
if(g[strlen(g)-1] != ')') {
n++;
}
for(int k = bclocation+1; k < n; k++) {
arrayRight[m] = g[k];
m++;
}
arrayRight[m] = '\0';
char* leftSide = &arrayLeft[0];
char* rightSide = &arrayRight[0];
// printf("%s\n", leftSide);
// printf("%s\n", rightSide);
return rightSide;
}
char *firstexp(char *g) {
char* left = partone(g);
char leftArray[50];
int i = 0;
for(i; i < strlen(left); i++) {
leftArray[i] = left[i];
}
leftArray[i] = '\0';
char binConnective = bin(g);
int typeG = type(g);
if(typeG == 2) {
if(binConnective == '^') {
return &leftArray;
} else if(binConnective == '>') {
return &leftArray;
}
} else if(typeG == 3) {
if(binConnective == 'v')
return &leftArray;
}
char temp[50];
for(int i = 0; i < strlen(leftArray); i++) {
temp[i+1] = leftArray[i];
}
temp[0] = '-';
char* lefttwo = &temp[0];
if(typeG == 2) {
if(binConnective == 'v') {
return lefttwo;
}
} else if(typeG == 3) {
if(binConnective == '>' || binConnective == '^') {
return lefttwo;
}
}
return "Hello";
}
char *secondexp(char *g) {
// char binaryConnective = bin(g);
// char* right = parttwo(g);
// char rightArray[50];
// int i = 0;
// for(i; i< strlen(right); i++) {
// rightArray[i+1] = right[i];
// }
// rightArray[i] = '\0';
// int typeG = type(g);
// if(type(g) == 2) {
// if(binaryConnective == '^') {
// return &rightArray;
// }
// } else if(type(g) == 3) {
// if(binaryConnective == 'v' || binaryConnective == '>') {
// return &rightArray;
// }
// }
return "Hello";
}
typedef struct tableau tableau;
\
\
struct tableau {
char *root;
tableau *left;
tableau *right;
tableau *parent;
int closedbranch;
};
int closed(tableau *t) {
return 0;
}
void complete(tableau *t) {
}
/*int main(int argc, const char * argv[])
{
printf("Hello, World!\n");
printf("%d \n", parse("p^q"));
printf("%d \n", type("p^q"));
printf("%c \n", bin("p^q"));
printf("%s\n", partone("p^q"));
printf("%s\n", parttwo("p^q"));
printf("%s\n", firstexp("p^q"));
printf("Simulation complete");
return 0;
}*/
File 2:
#include <stdio.h>
#include <string.h> /* for all the new-fangled string functions */
#include <stdlib.h> /* malloc, free, rand */
#include "yourfile.h"
int Fsize = 50;
int main()
{ /*input a string and check if its a propositional formula */
char *name = malloc(Fsize);
printf("Enter a formula:");
scanf("%s", name);
int p=parse(name);
switch(p)
{case(0): printf("not a formula");break;
case(1): printf("a proposition");break;
case(2): printf("a negated formula");break;
case(3): printf("a binary formula");break;
default: printf("what the f***!");
}
printf("\n");
if (p==3)
{
printf("the first part is %s and the second part is %s", partone(name), parttwo(name));
printf(" the binary connective is %c \n", bin(name));
}
int t =type(name);
switch(t)
{case(0):printf("I told you, not a formula");break;
case(1): printf("A literal");break;
case(2): printf("An alpha formula, ");break;
case(3): printf("A beta formula, ");break;
case(4): printf("Double negation");break;
default: printf("SOmewthing's wrong");
}
if(t==2) printf("first expansion fmla is %s, second expansion fmla is %s\n", firstexp(name), secondexp(name));
if(t==3) printf("first expansion fmla is %s, second expansion fmla is %s\n", firstexp(name), secondexp(name));
tableau tab;
tab.root = name;
tab.left=0;
tab.parent=0;
tab.right=0;
tab.closedbranch=0;
complete(&tab);/*expand the root node then recursively expand any child nodes */
if (closed(&tab)) printf("%s is not satisfiable", name);
else printf("%s is satisfiable", name);
return(0);
}
If you look at the first file, you'll see a method called * firstexp(char * g).
This method runs perfectly, but only if another method called * secondexp(char * g) is commented out.
If * secondexp(char * g) is commented out, then *firstexp runs like this:
Enter a formula:((pvq)>-p)
a binary formula
the first part is (pvq) and the second part is -p the binary connective is >
A beta formula, first expansion fmla is -(pvq), second expansion fmla is Hello
((pvq)>-p) is satisfiableProgram ended with exit code: 0
otherwise, if *secondexp is not commented out, it runs like this:
Enter a formula:((pvq)>-p)
a binary formula
the first part is (pvq) and the second part is -p the binary connective is >
A beta formula, first expansion fmla is \240L, second expansion fmla is (-
((pvq)>-p) is satisfiable. Program ended with exit code: 0
As you can see, the outputs are completely different despite the same input. Can someone explain what's going on here?
In the commented-out parts of secondexp and in parttwo, you return the address of a local variable, which you shouldn't do.
You seem to fill a lot of ad-hoc sized auxiliary arrays. These have the problem that they might overflow for larger expressions and also that you cannot return them unless you allocate them on the heap with malloc, which also means that you have to free them later.
At first glance, the strings you want to return are substrings or slices of the expression string. That means that the data for these strings is already there.
You could (safely) return pointers into that string. That is what, for example strchr and strstr do. If you are willing to modify the original string, you could also place null terminators '\0' after substrings. That's what strtok does, and it has the disadvantage that you lose the information at that place: If you string is a*b and you modify it to a\0b, you will not know which operator there was.
Another method is to create a struct that stores a slice as pointer into the string and a length:
struct slice {
const char *p;
int length;
};
You can then safely return slices of the original string without needing to worry about additional memory.
You can also use the standard functions in most cases, if you stick to the strn variants. When you print a slice, you can do so by specifying a field width in printf formats:
printf("Second part: '%.*s'\n", s->length, s->p);
In your parttwo() function you return the address of a local variable
return rightSide;
where rightSide is a pointer to a local variable.
It appears that your compiler gave you a warning about this which you solved by making a pointer to the local variabe arrayRight, that may confuse the compiler but the result will be the same, the data in arrayRight will no longer exist after the function returns.
You are doing the same all over your code, and even worse, in the secondexp() function you return a the address of a local variable taking it's address, you are not only returning the address to a local variabel, but also with a type that is not compatible with the return type of the function.
This is one of many probable issues that your code may have, but you need to start fixing that to continue with other possible problems.
Note: enable extra warnings when compiler and listen to them, don't try to fool the compiler unless you know exactly what you're doing.

Resources