Kruskal Algorithm, exited with code=code=3221225477 - c

#define MAX_VERTICES 10000
#define MAX_EDGES 50000000
#define HEAP_EMPTY(n) (!n)
#define LINE_SIZE 100
#define HEAP_FULL(n) (n == MAX_EDGES-1)
typedef struct {
int weight;
int node1;
int node2;
} element;
element min_heap[MAX_EDGES];
int parent_array[MAX_VERTICES];
element delete_min_heap(int *n) {
/* delete element with the highest key from the heap */
int parent, child;
element item, temp;
if(HEAP_EMPTY(*n)) {
fprintf(stderr, "The heap is empty");
exit(1);
}
/* save value of the element with the largest key */
item = min_heap[1];
/* use the last element in the heap to adjust heap */
temp = min_heap[(*n)--];
parent = 1;
child = 2;
while(child <= *n) {
/* find the larger child of the current parent */
if((child < *n) && (min_heap[child].weight > min_heap[child+1].weight)) child++;
if(temp.weight <= min_heap[child].weight) break;
/* move to the next lower level */
min_heap[parent] = min_heap[child];
parent = child;
child *= 2;
}
min_heap[parent] = temp;
return item;
}
void insert_min_heap(element item, int *n) {
int i;
if(HEAP_FULL(*n)) {
fprintf(stderr, "The heap is full.\n");
exit(1);
}
i = ++(*n);
while((i != 1) && (item.weight < min_heap[i/2].weight)) {
min_heap[i] = min_heap[i/2];
i /= 2;
}
min_heap[i] = item;
}
int simpleFind(int i) {
for( ; parent_array[i] >= 0; i = parent_array[i])
;
return i;
}
void weightedUnion(int i, int j) {
int temp = parent_array[i] + parent_array[j];
if(parent_array[i] > parent_array[j]) {
parent_array[i] = j;
parent_array[j] = temp;
} else {
parent_array[j] = i;
parent_array[i] = temp;
}
}
void main(int argc, char **argv) { //argc = argument 개수 argv argument list
//if(argc != 2) {
//printf("No input file is given or Two many input files are given.\n");
//exit(0);
//}
clock_t start = clock();
FILE *fp1 = fopen("input_large.txt", "r"); //replace to argv[1]
if(fp1 == NULL) {
printf("The input file does not exist.\n");
exit(0);
}
char *command_line;
char buffer[LINE_SIZE];
int cost;
int n_connected;
start = clock();
FILE *f = fopen("hw3_result.txt", "w+");
int line_num= 0;
int num_edges;
int num_vertices;
int n_heap = 0;
while (!feof(fp1)) { //한줄 씩 입력받기
element edge;
command_line = fgets(buffer, sizeof(buffer), fp1);
if(line_num == 0) {num_vertices = atoi(command_line);}
else if(line_num == 1) {num_edges = atoi(command_line);}
else {
int vertex_from = atoi(strtok(command_line, " "));
int vertex_to = atoi(strtok(NULL, " "));
int weigth = atoi(strtok(NULL, " "));
edge.node1 = vertex_from;
edge.node2 = vertex_to;
edge.weight = weigth;
insert_min_heap(edge, &n_heap);
}
line_num++;
}
fclose(fp1);
int i = 0;
for(i = 0; i< num_vertices; i++) { parent_array[i]=-1;}
element edge = delete_min_heap(&n_heap);
int j = 0;
cost = 0;
n_connected =0;
while((n_heap >= 0) && (n_connected != num_vertices)) {
int node1 = edge.node1;
int node2 = edge.node2;
if(j == 0) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected += 2;
j++;
}
else if ( simpleFind(node1) != simpleFind(node2)) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected++;
}
edge = delete_min_heap(&n_heap);
printf("%d %d\n", n_connected, n_heap);
}
printf("END\n");
printf("COST%d\n", cost);
printf("num vertices %d connected %d\n", num_vertices, n_connected);
if(n_connected < num_vertices) printf("DISCONNECTED\n");
if(n_connected == num_vertices) printf("CONNECTED\n");
fclose(f);
clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("output written to hw3_result.txt\n");
printf("running time :%lf\n", time_spent);
}
I tried to implement Kruskal's Algorithm, but I faced some problems. The format of the input file is like this.
7
9
0 1 28
0 5 10
1 2 16
1 6 14
2 3 12 //source vertex destination vertex weight
3 4 22
3 6 18
4 5 25
4 6 24
The first line is the number of vertices and the second is number of edges. There is no problem when running small input file, but when the input file is very large, the program is exited with code=3221225477.
This code is to find where the code is exited
while((n_heap >= 0) && (n_connected != num_vertices)) {
int node1 = edge.node1;
int node2 = edge.node2;
if(j == 0) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected += 2;
j++;
}
else if ( simpleFind(node1) != simpleFind(node2)) {
weightedUnion(node1, node2);
cost += edge.weight;
//printf("%d %d %d\n",node1, node2, edge.weight);
n_connected++;
}
edge = delete_min_heap(&n_heap);
**printf("%d %d\n", n_connected, n_heap);** //here
}
The result is like this.
...
1657 4998343 //num of connected vertices num of heap's remaining element
1658 4998342
1659 4998341
1660 4998340
1661 4998339
1662
After deleting 1661 element in heap, for some reasons, program doesn't work any more.

Related

Selection sort not working as expected (C language)

I have to sort an array of structs with selection sort, after I read them from a file.txt.
My algorithm is not working as expected, but it always avoid to sort them and it print the struct in decreasing order.
Example of file.txt :
P0 "ANTONIO" 2000 4
P1 "BARTOLOMEO" 1995 6
P2 "CARLO" 2020 1
P3 "DEMETRIO" 1960 2
P4 "ETTORE" 1920 3
P5 "FRANCESCO" 1950 5
Input: 2 5 3 1 6 4
Output: 4 6 1 3 5 2
What am I doing wrong?
Code below:
#include <stdio.h>
#include <stdlib.h>
#define N 7
struct persona
{
char codice[10];
char nome[30];
int anno[10];
int reddito[10];
};
int main()
{
FILE* fp;
fp = fopen("Testo.txt", "r");
struct persona* persona = malloc(sizeof(struct persona) * N);
int i = 0;
int j = 0;
if (fp != NULL)
{
while (i < N-1)
{
fscanf(fp, "%s %s %s %s",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
i++;
}
}
else
{
perror("Errore");
}
fclose(fp);
for(i=0; i<N-2; i++)
{
int min = persona[i].reddito;
for(j=i+1; j<N-1; j++)
{
if(persona[j].reddito < persona[i].reddito)
{
min = persona[j].reddito;
}
persona[N] = persona[j];
persona[j] = persona[i];
persona[i] = persona[N];
}
}
for(i=0; i<N-1;i++)
{
printf("%s\t %s\t %s\t %s\n",
persona[i].codice,
persona[i].nome,
persona[i].anno,
persona[i].reddito);
}
}
You have 6 lines in the file, but you have defined N as 7. It should be updated to 6.
while (i < N-1)
You are reading the first N-2, that is, 5 lines from the file. The 6th line is not being read. Same goes for other loops in the code using N.
int anno[10];
int reddito[10];
You do not need integer array to read the numeric fields in file, an integer should suffice.
As mentioned by #WhozCraig in the comments, the selection sort algorithm is incorrect. Here's the updated code for reference:
#include <stdio.h>
#include <stdlib.h>
#define N 6
typedef struct persona
{
char codice[10];
char nome[30];
int anno;
int reddito;
} PERSONA;
int main()
{
FILE *fp;
if ((fp = fopen("file.txt", "r")) == NULL)
{
perror("\nFile not found");
exit(1);
}
PERSONA *persona = malloc(sizeof(struct persona) * N);
int i = 0, j;
while (i < N)
{ if (fscanf(fp, "%s %s %d %d", persona[i].codice, persona[i].nome, &persona[i].anno, &persona[i].reddito) == EOF) {
break;
}
i++;
}
fclose(fp);
PERSONA temp;
/* selection sort */
for (i = 0; i < N - 1; i++)
{
int jMin = persona[i].reddito;
for (j = i + 1; j < N; j++)
{
if (persona[j].reddito < persona[jMin].reddito)
{
jMin = j;
}
}
if (jMin != i)
{
temp = persona[i];
persona[i] = persona[jMin];
persona[jMin] = temp;
}
}
for (i = 0; i < N; i++)
{
printf("\n%s\t %s\t %d\t %d", persona[i].codice, persona[i].nome, persona[i].anno, persona[i].reddito);
}
}
Further improvements:
You could also calculate the number of lines in the file in the code instead of relying on a hardcoded value N.
The statement to check sets only the min only if this statement is true
if(persona[j].reddito < persona[i].reddito)
try using the qsort function
int cmpfunc (const void * a, const void * b) {
struct persona *p1 = (struct persona *)a;
struct persona *p2 = (struct persona *)b;
if(p1->reddito < p2->reddito) return -1;
if(p1->reddito > p2->reddito) return 1;
return 0;
}
and instead of the for loop, use
qsort(persona, N, sizeof(struct persona), cmpfunc);

Heapsort - Struct of Array - C

I'm trying to Heapsort (sort by Alphabetical Order the name of the phone) a structure of char array read from a txt file. My algorithm works for integer but when I change to 'char' type it don't show any result nor any error
Therefore I really dont know what's wrong with my code. Please help, I'm new to this.
My txt file
iPhone_XR 128 6.1 599
Galaxy_s20 256 5.8 599
oppo_find_x 128 4.7 429
iPhone_SE 128 4.0 349
My code
#include <stdio.h>
struct phone
{
char a[100];
char b[100];
char c[100];
char d[100];
};
struct phone array[100];
void swap(char *e, char *f)
{
char temp = *e;
*e = *f;
*f = temp;
}
void heapify(char arr[], int n, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest])
largest = left;
if (right < n && arr[right] > arr[largest])
largest = right;
if (largest != i)
{
swap(&arr[i], &arr[largest]);
heapify(arr, n, largest);
}
}
void heapSort(char arr[], int size)
{
for (int i = size / 2 - 1; i >= 0; i--)
heapify(arr, size, i);
for (int i = size - 1; i >= 0; i--) {
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
int main(void)
{
int size;
char ch;
int count = 0;
char A[1000];
FILE *myfile = fopen("phonedb.txt", "r");
if (myfile == NULL) {
printf("Cannot open file.\n");
return 1;
}
else {
do //count lines
{
ch = fgetc(myfile);
if (ch == '\n') count++;
} while (ch != EOF);
rewind(myfile);
// scan all the line inside the text
int i;
for (i = 0; i < count; i++) {
fscanf(myfile, "%s %s %s %s\n", array[i].a, array[i].b, array[i].c, array[i].d);
printf("%s %s %s %s\n", array[i].a, array[i].b, array[i].c, array[i].d);
}
}
heapSort(A, count);
printf("\nYour sorted list\n");
for (int i=0; i<size; i++)
{
printf("%s\n", array[i].a);
}
return 0;
}
Your program has lot of errors and some unnecessary use of char arrays.
But since you are sorting your data using phone names which is a string,
direct comparison won't work as it's not a primitive data type. You need to use library function strcmp() from <string.h> library.
Here's my working code.
#include<stdio.h>
#include<string.h>
struct phone
{
char phoneName[100];
int second,fourth;
float third;
};
struct phone array[100];
void swap(struct phone *e, struct phone *f)
{
struct phone temp = *e;
*e = *f;
*f = temp;
}
void heapify(struct phone arr[], int n, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && strcmp(arr[left].phoneName, arr[largest].phoneName)>0)
largest = left;
if (right < n && strcmp(arr[right].phoneName, arr[largest].phoneName)>0)
largest = right;
if (largest != i)
{
swap(&arr[i], &arr[largest]);
heapify(arr, n, largest);
}
}
void heapSort(struct phone arr[], int size)
{
for (int i = size / 2 - 1; i >= 0; i--)
heapify(arr, size, i);
for (int i = size - 1; i >= 0; i--) {
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
int main()
{
int size;
char ch;
int count = 0;
FILE *myfile = fopen("phonedb.txt", "r");
if (myfile == NULL) {
printf("Cannot open file.\n");
return 1;
}
else {
do //count lines
{
ch = fgetc(myfile);
if (ch == '\n') count++;
} while (ch != EOF);
rewind(myfile);
// scan all the line inside the text
int i;
for (i = 0; i < count; i++) { // using floating point with 2 precision.
fscanf(myfile, "%s %d %f %d\n", array[i].phoneName, &array[i].second, &array[i].third, &array[i].fourth);
printf("%s %d %0.2f %d\n", array[i].phoneName, array[i].second, array[i].third, array[i].fourth);
}
}
heapSort(array, count);
printf("\nYour sorted list\n");
for (int i=0; i<count; i++)
{
printf("%s %d %0.3f %d\n", array[i].phoneName,array[i].second,array[i].third,array[i].fourth);
}
return 0;
}
And Here's the output:
iPhone_XR 128 6.10 599
Galaxy_s20 256 5.80 599
oppo_find_x 128 4.70 429
iPhone_SE 128 4.00 349
Your sorted list
Galaxy_s20 256 5.80 599
iPhone_SE 128 4.00 349
iPhone_XR 128 6.10 599
oppo_find_x 128 4.70 429

Tic-Tac-Toe user input looping endlessly when alphabetical character entered

So I am making a tic tac toe game in C and I am having a problem where I am asking the user to undo their move by pressing 2. Each time it is their turn, they can either undo a move or continue to select there next turn by selecting another key.
It works how it should but I have a problem where if the user enters an alphabetical character, the program just repeatedly loops through saying that this is not a number when it checks my GetHumanMove function. Does anyone know how to make it stop doing this and just say this is not a number once without it looping the program?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
//Tic-Tac-Toe game in C
//20/03/2019
//5x5 Board with 4 in a row to win. Also has playable AI that randomly blocks human moves.
//Also has replay function using a doubly linked list
/*
int board[49] = {
;,;, ;, ;, ;, ;, ;,
;,1, 2, 3, 4, 5 ,;,
;,6, 7, 8, 9, 10,;,
;,11,12,13,14,15,;,
;,16,17,18,19,20,;,
;,21,22,23,24,25,;,
;,;, ;, ;, ;, ;, ;,
}
*/
struct node
{
int side;
int move;
int place;
struct node * prev;
struct node * next;
};
void append(struct node **, int, int, int);
void display(struct node *);
void delete(struct node **, int);
//Constants of pieces, border and empty places
enum { NOUGHTS, CROSSES, BORDER, EMPTY };
//Constants for human/computer win or draw
enum { HUMANWIN, COMPWIN, DRAW };
const int directions[4] = { 1, 7, 6, 8 };
int moveCount = 0;
//Values of original places to play
const int ConvertTo49[25] = {
8, 9, 10,11,12,
15,16,17,18,19,
22,23,24,25,26,
29,30,31,32,33,
36,37,38,39,40
};
void append(struct node ** list, int side, int move, int place)
{
struct node *temp , *current = *list;
if(*list == NULL)
{
*list = (struct node *) malloc(sizeof(struct node));
(*list) -> prev = NULL;
(*list) -> side = side;
(*list) -> move = move;
(*list) -> place = place;
(*list) -> next = NULL;
}
else
{
while(current -> next != NULL)
current = current -> next;
temp = (struct node *) malloc(sizeof(struct node));
temp -> side = side;
temp -> move = move;
temp -> place = place;
temp -> next = NULL;
temp -> prev = current;
current -> next = temp;
}
}
void delete(struct node ** list, int num)
{
struct node *temp = *list;
while(temp != NULL)
{
if(temp -> move == num)
{
if(temp == *list)
{
*list = (*list) -> next;
(*list) -> prev = NULL;
}
else
{
if(temp -> next == NULL)
temp -> prev -> next = NULL;
else
{
temp -> prev -> next = temp -> next;
temp -> next -> prev = temp -> prev;
}
free(temp);
}
return ;
}
temp = temp -> next;
}
printf("Element %d not found in the supplied list \n\n", num);
}
//Loop through a direction until a border square is hit
int GetNumForDir(int startSq, const int dir, const int *board, const int us)
{
int found = 0;
while(board[startSq] != BORDER)
{
if(board[startSq] != us)
{
break;
}
found++;
startSq += dir;
}
return found;
}
//Loop through directions and find four in a row
int FindFourInARow(const int *board, const int ourIndex, const int us)
{
int dirIndex = 0;
int dir = 0;
int countFour = 1;
for(dirIndex = 0; dirIndex < 4; ++dirIndex)
{
dir = directions[dirIndex];
countFour += GetNumForDir(ourIndex + dir, dir, board, us);
countFour += GetNumForDir(ourIndex + dir * -1, dir * -1, board, us);
if(countFour == 4)
{
break;
}
countFour = 1;
}
return countFour;
}
//Set up board structure
void InitialiseBoard(int *board)
{
//index variable
int index;
//set whole board to border squares initially
for(index = 0; index < 49; ++index)
{
board[index] = BORDER;
}
//Set up empty squares for placing pieces
for(index = 0; index < 25; ++index)
{
board[ConvertTo49[index]] = EMPTY;
}
}
//Print the board
void PrintBoard(const int *board)
{
//index variable
int index;
//Set pieces and places
char pceChars[] = "OX| ";
printf("\n\n\n");
//Loop through and only draw the actual playable squares, leaving out the border squares
for(index = 0; index < 25; ++index)
{
//Put lines inbetween places
if(index==1 || index==2 || index==3 || index==4 ||
index==6 || index==7 || index==8 || index==9 ||
index==11 || index==12 || index==13 || index==14 ||
index==16 || index==17 || index==18 || index==19 ||
index==21 || index==22 || index==23 || index==24)
{
printf(" |");
}
//Put space at start to space out board from edge of screen
if(index==0)
{
printf(" ");
}
//Print new line every 5 places
if(index!= 0 && index==5 || index==10 || index==15 || index==20)
{
printf("\n");
printf(" -------------------");
printf("\n");
printf(" ");
}
//Print each playable piece
printf(" %c", pceChars[board[ConvertTo49[index]]]);
}
printf("\n\n");
}
//Check if board has empty spaces
int HasEmpty(const int *board)
{
int index;
for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY) return 1;
}
return 0;
}
//Function for making move of current player
void MakeMove(int *board, const int sq, const side)
{
//set board place that either player decides
board[sq] = side;
}
void UndoMove(int *board, int sq, int side)
{
//set board place that either player decides
board[sq] = side;
}
//Help the computer find a winning move
int GetWinningMove(int *board, const int side)
{
int ourMove = -1;
int winFound = 0;
int index = 0;
for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY)
{
ourMove = ConvertTo49[index];
board[ourMove] = side;
if(FindFourInARow(board, ourMove, side) == 4)
{
winFound = 1;
}
board[ourMove] = EMPTY;
if(winFound == 1)
{
return ourMove;
}
ourMove = -1;
};
}
return ourMove;
}
//Get computer player move
int GetComputerMove(int *board, const int side)
{
int index;
int numFree = 0;
int availableMoves[25];
int randMove = 0;
//Set random number to randomly run a function
int randFunction = 0;
randFunction = (rand() % 2);
//Go for the winning move
randMove = GetWinningMove(board, side);
if(randMove != -1)
{
return randMove;
}
//If random function is 1, stop any winning move from the human
if(randFunction == 1)
{
randMove = GetWinningMove(board, side ^ 1);
if(randMove != -1)
{
return randMove;
}
}
randMove = 0;
//Loop through all squares and put piece in random place
for(index = 0; index < 25; ++index)
{
if(board[ConvertTo49[index]] == EMPTY)
{
availableMoves[numFree++] = ConvertTo49[index];
};
}
randMove = (rand() % numFree);
return availableMoves[randMove];
}
//Get human player move
int GetHumanMove(const int *board)
{
//Array for user input
int userInput;
char term;
//Start moveOK at 0
int moveOK = 0;
int move = -1;
//Loop through until move being made is valid
while(moveOK == 0)
{
printf("\n");
//Ask user for input of 1-9
printf("Please enter a place on the board to make your move, from 1 to 25: ");
//Make sure that user doesnt enter long string with number on the end that eventaully passes tests in the while loop
scanf("%d%c", &userInput, &term);
if(term != '\n')
{
move = -1;
printf("This is not a number\n");
continue;
}
//Check if input is in proper range
if(userInput < 1 || userInput > 25)
{
move = -1;
printf("Invalid Range\n");
continue;
}
//decrement move to get the array location of the playable places
userInput--;
//Check if place selected is already taken
if(board[ConvertTo49[userInput]] != EMPTY)
{
move = -1;
printf("Square not available\n");
continue;
}
//Set move ok to 1 after passing all the tests
moveOK = 1;
}
//Print move being made and return it
printf("\nHuman making Move at square: %d\n",(userInput+1));
return ConvertTo49[userInput];
}
//Run Game function
void RunGame()
{
struct node *list;
list = NULL;
//Display
printf("\n\n Noughts And Crosses Game:");
printf("\n =========================");
//game over variable
int gameOver = 0;
//Start on noughts side
int side = NOUGHTS;
//Record last move
int lastMoveMade = 0;
//Create new board
int board[49];
//Count of first move
int initialMove = 0;
//Initialise the Board
InitialiseBoard(&board[0]);
//Print the board to screen
PrintBoard(&board[0]);
//While game isn't over
while(!gameOver)
{
initialMove++;
//Human
if(side==NOUGHTS)
{
//Ask to undo move after first move played
if(initialMove > 1)
{
while(list -> prev != NULL)
list = list -> prev;
int undo;
printf("\n\nWould you like to undo your move? \nEnter 2 to undo or any other key/s to continue: ");
scanf("%d", &undo);
if( undo == 2)
{
while(list -> next != NULL)
list = list -> next;
char pceChars[] = "OX| ";
//printf(" %c", pceChars[board[ConvertTo49[index]]]);
int count = 2;
while(count != 0)
{
UndoMove(&board[0], list -> place, EMPTY);
list = list -> prev;
delete(&list, list -> next -> move);
moveCount--;
count--;
}
PrintBoard(&board[0]);
}
}
//Make new move for human
lastMoveMade = GetHumanMove(&board[0]);
MakeMove(&board[0], lastMoveMade, side);
moveCount++;
int humanMove;
//Find the position the computer is making on the 5x5 board
for(humanMove = 0; humanMove < 25; ++humanMove)
{
if(ConvertTo49[humanMove] == lastMoveMade)
{
break;
}
}
append(&list, 0, moveCount, lastMoveMade);
side = CROSSES;
}
//Computer
else
{
//Make move for computer
lastMoveMade = GetComputerMove(&board[0], side);
MakeMove(&board[0], lastMoveMade, side);
int compMove;
//Find the position the computer is making on the 5x5 board
for(compMove = 0; compMove < 25; ++compMove)
{
if(ConvertTo49[compMove] == lastMoveMade)
{
break;
}
}
printf("\nComputer making move at square: %d", compMove+1);
moveCount++;
append(&list, 1, moveCount, lastMoveMade);
side = NOUGHTS;
PrintBoard(&board[0]);
}
//If three in a row exists, game over
if(FindFourInARow(board, lastMoveMade, side ^ 1) == 4)
{
gameOver = 1;
if(side == NOUGHTS)
{
printf("\nGame Over!\n");
printf("Computer Wins! :(\n");
}
else
{
PrintBoard(&board[0]);
printf("\nGame Over!\n");
printf("Human Wins! :D\n");
}
}
//If no more moves, game is a draw
if(!HasEmpty(board))
{
PrintBoard(&board[0]);
printf("\n\nGame Over!\n");
gameOver = 1;
printf("It's a draw! :/\n");
}
}
/*
*
* Match Replay
*
*/
int answer;
printf("\n\nWould you like to replay the match? \nEnter 1 to replay or any other key/s to quit: ");
scanf("%d", &answer);
if(answer == 1)
{
InitialiseBoard(&board[0]);
while ( list != NULL )
{
MakeMove(&board[0], list -> place, list -> side);
PrintBoard(&board[0]);
char who[7];
if(list -> side == 0)
{
strcpy(who, "NOUGHTS");
//who = "NOUGHTS";
}
else
{
strcpy(who, "CROSSES");
//who = "CROSSES";
}
int moveMade;
//Find the position the computer is making on the 5x5 board
for(moveMade = 0; moveMade < 25; ++moveMade)
{
if(ConvertTo49[moveMade] == list -> place)
{
break;
}
}
printf ("\nMove:%2d Side:%8s Place: %d\n", list -> move, who, moveMade+1);
Sleep(2000);
list = list -> next ;
}
}
else
{
printf("\nGood Game! See ya!\n");
getch();
}
}
int main()
{
//Create random number
srand(time(NULL));
//Call Run Game to play
RunGame();
return 0;
}
Input that doesn't match your format doesn't get consumed by scanf. It remains in the input stream. So when you type a letter it fails to match the number you wanted %d and stays in the input stream.
scanf("%d%c", &userInput, &term);
Instead of scanf, it would be simpler to use getline to consume the entire line of input. And then parse the result with sscanf (the string-based version of the function) or another method.
char *line = NULL;
size_t len = 0;
while ((read = getline(&line, &len, stdin)) != -1) {
// Do something with line
int scanned = sscanf(line, "%d%c", &userInput);
if (scanned == EOF || scanned != 2) {
printf("Line failed to match\n");
}
}
Just read the manual page:
The format string consists of a sequence of directives which describe
how to process the sequence of input characters. If processing of a
directive fails, no further input is read, and scanf() returns. A
"failure" can be either of the following: input failure, meaning that
input characters were unavailable, or matching failure, meaning that
the input was inappropriate (see below).
You do not check the return value of scanf(). So you try to scan the same non-digit as digit all the time.

Error condition, how to implement it?

So what my codes does at the moment is quite simple. It receives an input like this:
5 4
1 2
2 3
3 4
4 5
The first line of the input represents the number of Ids and the number of relations. The following line are those relations. The program sorts these pairs, for example: 1 comes before 2, 2 comes before 3 and so on. In this case the outup will be 1 2 3 4 5.
In case of contradictive input, such as:
4 4
1 2
2 3
3 2
3 4
It returns "Incoerente".
My current problem is my input is "non conclusive" such as:
4 4
1 2
3 1
3 4
4 2
In this case the program doesnt really know where to place the 4 (after or before the 1?). My program right now (with the input above) will print "3 1 2", and ignores the 4 for some reason. When this situation apears I want to print "OTHERERROR".
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
void create_graph();
void add(int vertex);
int del();
int isEmpty();
int find_indegree_of_vertex(int vertex);
int total_vertices;
int adjacent_matrix[MAX][MAX];
int queue[MAX];
int front = -1;
int rear = -1;
FILE *myFile;
int main(){
myFile = fopen("input.txt", "r");
int i;
int numberArray[2];
for(i=0;i<2;i++)
fscanf(myFile, "%1d", &numberArray[i]);
int N = numberArray[0];
int L = numberArray[1];
int vertex, count, topological_sort[MAX], indegree[MAX];
create_graph(N, L);
for(i = 0; i < total_vertices; i++){
indegree[i] = find_indegree_of_vertex(i);
if(indegree[i] == 0){
add(i);
}
}
count = 0;
while(!isEmpty() && count < total_vertices){
vertex = del();
topological_sort[++count] = vertex;
for(i = 0; i < total_vertices; i++){
if(adjacent_matrix[vertex][i] == 1){
if(adjacent_matrix[i][vertex] == 1){
printf("INCOERENTE !!!!!!!!!!!!!!!\n");
}
adjacent_matrix[vertex][i] = 0;
indegree[i] = indegree[i] - 1;
if(indegree[i] == 0){
add(i);
}
}
}
}
if(count < total_vertices){
printf("Incoerente\n");
exit(1);
}
printf("Topological Order of Vertices\n");
for(i = 1; i <= count; i++){
printf("%3d", topological_sort[i]+1);
}
printf("\n");
return 0;
}
void add(int vertex){
if(rear == MAX - 1){
printf("Queue Overflow\n");
}
else{
if (front == -1) {
front = 0;
}
rear = rear + 1;
queue[rear] = vertex ;
}
}
int isEmpty(){
if(front == -1 || front > rear ){
return 1;
}
else{
return 0;
}
}
int del(){
int element;
if (front == -1 || front > rear){
printf("Queue Underflow\n");
exit(1);
}
else{
element = queue[front];
front = front+1;
return element;
}
}
int find_indegree_of_vertex(int vertex){
int count, total_indegree = 0;
for(count = 0; count < total_vertices; count++){
if(adjacent_matrix[count][vertex] == 1){
total_indegree++;
}
}
return total_indegree;
}
void create_graph(int N, int L){
int count, maximum_edges, origin_vertex, destination_vertex;
total_vertices = N;
maximum_edges = L;
int integers[MAX];
int i =0;
int num;
while(fscanf(myFile, "%d", &num) > 0) {
integers[i] = num;
i++;
}
i=0;
printf("1a linha :%d %d\n", N, L);
for(count = 1; count <= maximum_edges; count++){
origin_vertex = integers[i]-1;
destination_vertex = integers[i+1]-1;
printf("pares a ser avaliados :%d %d\n", origin_vertex+1, destination_vertex+1);
if(origin_vertex > total_vertices || destination_vertex > total_vertices || origin_vertex < 0 || destination_vertex < 0){
printf("Edge Co-ordinates are Invalid\n");
count--;
}
else
adjacent_matrix[origin_vertex][destination_vertex] = 1;
if(count == maximum_edges){
break;
}
i+=2;
}
}

How do I fix a Segmentation Fault error in my C code

I am working on writing a code for the game, Mancala, and testing along the way. So far, I am getting an error that says:
Segmentation Fault (core dumped)
I'm not sure how to fix it and keep it running.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void move_clockwise(int board[], int pos, int player_1);
void move_count_clock(int board[], int pos, int player_1);
void mancala_board(int board[]);
int *current1;
int *current2;
int board[30], player_1, sum, position, direction, i, n, play, initPos, curPos, pos;
//======================================================================
int main(void)
{
int board[30];
board[0] = 4;
board[1] = 4;
board[2] = 4;
board[3] = 4;
board[4] = 4;
board[5] = 4;
board[6] = 0;
board[7] = 4;
board[8] = 4;
board[9] = 4;
board[10] = 4;
board[11] = 4;
board[12] = 4;
board[13] = 0;
printf("Welcome to Mancala\n");
printf("\n\n 5 4 3 2 1 0 \n");
printf("BLUE\n");
printf("=====[%d] [%d] [%d] [%d] [%d] [%d]-----\n", board[5], board[4], board[3], board[2], board[1], board[0]);
printf("|%d| |%d|\n", board[6], board[13]);
printf("-----[%d] [%d] [%d] [%d] [%d] [%d]=====\n", board[7], board[8], board[9], board[10], board[11], board[12]);
printf(" RED\n");
printf(" 6 7 8 9 10 11 \n\n");
sum=board[6]+board[13];
player_1=first_player();
while(sum!=48)
{
while (player_1 == 1)
{
printf("Player RED\n");
printf("Pick a position corresponding to the integer: ");
scanf("%d", position);
while (position!=6 || position!=7 || position!=8 || position!=9 || position!=10 || position!=11)
{
printf("\nInvalid input, you have to select a bowl from your side.\nPlease select another position");
scanf("%d",&position);
}
printf("Would you like to move clockwise or counter-clockwise?");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
while(direction!=1 && direction!=2)
{
printf("\nInvalid input, you have to select an integer corresponding to the given options.\n");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
}
if (direction==1)
{
position+=1;
move_clockwise(board, position, player_1);
}
if(direction==2)
{
position=+1;
move_count_clock(board, position, player_1);
}
player_1-=1;
mancala_board(board);
}
if (player_1 == 0)
{
printf("Player BLUE\n");
printf("Pick a position corresponding to the integer: ");
scanf("%d", position);
while (position!=0 || position!=1 || position!=2 || position!=3 || position!=4 || position!=5)
{
printf("\nInvalid input, you have to select a bowl from your side.\nPlease select another position");
scanf("%d",&position);
}
printf("Would you like to move clockwise or counter-clockwise?");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
while(direction!=1 && direction!=2)
{
printf("\nInvalid input, you have to select an integer corresponding to the given options.\n");
printf("\n1. Clockwise \n2. Counter-Clockwise");
scanf("%d",&direction);
}
if (direction==1)
{
position+=1;
move_clockwise(board, position, player_1);
}
if(direction==2)
{
position=+1;
move_count_clock(board, position, player_1);
}
player_1+=1;
mancala_board(board);
}
sum=board[6]+board[13];
}
}
//======================================================================
int first_player(void)
{
//to determine who will be player 1
play=rand()%2;
return (play);
}
//======================================================================
//Display current board
void mancala_board(int board[])
{
printf("\n\n 5 4 3 2 1 0 \n");
printf("BLUE\n");
printf("=====[%d] [%d] [%d] [%d] [%d] [%d]-----\n", board[5], board[4], board[3], board[2], board[1], board[0]);
printf("|%d| |%d|\n", board[6], board[13]);
printf("-----[%d] [%d] [%d] [%d] [%d] [%d]=====\n", board[7], board[8], board[9], board[10], board[11], board[12]);
printf(" RED\n");
printf(" 6 7 8 9 10 11 \n\n");
}
//======================================================================
//allow player to move again if late marble lands in mancala
//void move_again(int board[], int pos, int player_1)
//{
//}
//======================================================================
//captures the marbles across the current position if player's
//last marble lands on their own bowl with no marbles in
//void capture()
//{
//}
//======================================================================
void move_clockwise(int board[], int pos, int player_1)
{
initPos = pos;
n=board[pos];
pos+=1;
for (i = 0; i < n ; i++)
{
curPos +=1;
board[curPos]+=1;
if (curPos == 14)
curPos -=14;
else if (curPos >= 28)
curPos -= 28;
if (player_1 == 0)
{
current1 = &(board[curPos]);
if (current1 == &(board[6]))
{
current1 = &(board[7]);
current1 += 1;
}
}
if (player_1 == 1)
{
current2 = &(board[curPos]);
if (current2 == &(board[13]))
{
current2 = &(board[0]);
current2 += 1;
}
}
}
board[initPos] = 0;
}
//======================================================================
void move_count_clock(int board[], int pos, int player_1)
{
initPos = pos;
n=board[pos];
pos+=1;
for (i = 0; i < n ; i++)
{
curPos +=1;
board[curPos]+=1;
if (curPos == 14)
curPos -=14;
else if (curPos >= 28)
curPos -= 28;
if (player_1 == 0)
{
current1 = &(board[curPos]);
if (current1 == &(board[6]))
{
current1 = &(board[7]);
current1 += 1;
}
}
if (player_1 == 1)
{
current2 = &(board[curPos]);
if (current2 == &(board[13]))
{
current2 = &(board[0]);
current2 += 1;
}
}
}
board[initPos] = 0;
}
Maybe you want to separate the code in smaller pieces and test each piece. Or maybe this can help you: http://ericlippert.com/2014/03/05/how-to-debug-small-programs/
To put & inside scanf is correct suggestion, I think that was meant in the comment.
Anyway, this is also weird:
while (position!=6 || position!=7 || position!=8 || position!=9 || position!=10 || position!=11)
{
scanf("%d",&position);
}
what do you expect above? It will always enter that loop, and never come out, since
if position is 6 it can't be 7 hence due to OR the statement will be true.

Resources