I am trying to code minesweeper in C. I started out with assigning the values to a 2D array then print it. I tried everything but it didn't work.
This happens in my sample output:
The code is:
#include <stdio.h>
#include <stdlib.h>
struct Tile {
unsigned char isMine : 1;
char status;
};
int main() {
struct Tile arr[9][9];
unsigned char i;
unsigned char c;
unsigned char count = 10;
srand((unsigned)time(0));
for (i = 0; i < 9; i++) {
for (c = 0; i < 9; i++) {
if(rand() % 81 + 1 < count && arr[i][c].isMine == 0 && count > 0) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
} else {
continue;
}
}
for (i = 0; i < 9; i++) {
for (c = 0; c < 9; c++) {
printf("%c", arr[i][c].status);
}
printf("\n");
}
return 0;
}
Please help.
You never visit any fields in your loops except the 1st column due to incorrect loop header:
for (i = 0; i < 9; i++) {
for (c = 0; i < 9; i++) {
if(rand() % 81 + 1 < count && arr[i][c].isMine == 0 && count > 0) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
} else {
continue;
}
}
This will leave all other fields uninitialized and when you try to print it, strange things may appear.
Also as you only visit each field once (or at least that seems to be your intention), there is no need to check isMine at all. If you initialize properly, it must be 0 anyway.
Which of course requires that you intitialize properly as already mentioned in David's answer.
The condition can be reduced a bit more as the first part (..+1<count) already implies that count>0. No need to check again.
Finally, continue as last instruction of a loop is not really useful.
Your code could look like this:
struct Tile arr[9][9] = {{0}};;
...
for (i = 0; i < 9; i++) {
for (c = 0; c < 9; c++) {
if(rand() % 81 + 1 < count) {
arr[i][c].isMine = 1;
arr[i][c].status = 'X';
count--;
} else {
arr[i][c].status = '.';
}
}
if (count == 0) {
break;
}
}
Initialize the array:
struct Tile arr[9][9] = {{0}};
otherwise you read an uninitialized value (leading to undefined behaviour) in:
} else if (arr[i][c].isMine == 0) {
arr[i][c].status = '.';
}
Related
I am trying to write a program that will take an arbitrary number and flip the bits and add one, and I have written the code, but I keep getting a segmentation fault (core dumped) error. Could someone look at my code and see why that error is occurring. I have attached my code below and the input and output I would like to receive.
#include "stdio.h"
#include "malloc.h" //Needed for malloc, realloc, and free
#define GROW_BY 2
#define MAX_BITS 32
int add_one(int in_array[], int num){
for (int i = 0; in_array[i] != NULL; i++) {
int add_one = in_array[num - i] + 1;
}
return add_one;
}
int main() {
//Declaration and Initialization of Variables
int* array = NULL;
int bit = getchar();
int count = 0;
while (bit != '\n') {
bit = bit - '0';
*array = &bit;
array = (int*)malloc((strlen(bit) + 1) * sizeof(int));
if (array == NULL) {
printf("An error has occurred and the program will now $
return 1;
}
bit = getchar();
}
for (int j = count - 1; j >= 1; j--) {
if (array[j] == '1') {
array = (int*)realloc(array, GROW_BY * sizeof(int));
if (array == NULL) {
printf("An error has occurred and the program w$
}
}
else if (array[j] == '0' ) {
array = (int*)realloc(array, GROW_BY * sizeof(int));
if (array == NULL) {
printf("An error has occurred and the program w$
return 1;
}
}
}
add_one(array, bit);
for (int j = count - 1; j >= 1; j--) {
if (array[j] == '1' && add_one == 1) {
array[j] = '0';
}
else if (array[j] == '0' && add_one == 1) {
array[j] = '1';
int add_one = 0;
}
else {
array[j] = array[j];
}
}
printf("%ls/n", array);
free(array);
return 0;
}
Input: 101011110
Output: 010100010
This program is to find the epsilon closure of all states of an NFA. I have used the stack to get this done.The program gives the right output when I compiled it using gcc and ran it Windows 10(Command Prompt). But when I compiled with the same compiler and ran it in Linux it results in segmentation fault. I have used any dynamic memory allocation for that matter.
I tried to debug using gdb but not able to find the problem. Detected a segmentation fault after a printf("\n") when displaying the transitions matrix.
It would be very helpful for someone could find the fault. Thanks in advance.
The input is read from a file : nfa.txt.
//states
q0 q1 q2
//input_symbols
0 1
//start_state
q0
//final_state
q2
//transitions of the form : intial_state input final_state
q0 0 q0
q0 e q1
q1 1 q1
q1 e q2
q2 2 q2
The output is as follows:
232 is to represent null transition(Φ) and -1 for ε.
States:
q0
q1
q2
Transitions read
232 0 1 2 -1
0 0 232 232 1
1 232 1 232 2
2 232 232 2 232
e-closure(0) : 0 1 2
e-closure(1) : 1 2
e-closure(2) : 2
Please bear with me because it's a fairly long program.
#include <stdio.h>
#include <string.h> //REMEMBER ME WHILE I'M GONE
#include <errno.h>
#include <stdlib.h>
FILE *file;
int numberOfStates = 0;
int flag = 0;
int states[20];
int j = 0;
int i = 0;
int k = 0;
char a[20];
int transitions[4][5];
int visited[10];
int MAXSIZE = 8;
int stack[8];
int top = -1;
int isempty()
{
if(top == -1)
return 1;
else
return 0;
}
int isfull()
{
if(top == MAXSIZE)
return 1;
else
return 0;
}
int pop()
{
int data;
if(!isempty()) {
data = stack[top];
top = top - 1;
return data;
}
else
printf("Could not retrieve data, Stack is empty.\n");
}
int push(int data) {
if(!isfull()) {
top = top + 1;
stack[top] = data;
}
else
printf("Could not insert data, Stack is full.\n");
}
int IsVisited(int edge)
{
for(int i = 0; i < 10; i++)
if(visited[edge] == 1)
return 1;
return 0;
}
void epsilon_closure(int state)
{
int e_closure[10];
for(int i = 0; i < 10; i++ )
{ e_closure[i] = -1;
visited[i] = 0;
}
push(state);
visited[state] = 1;
while(top != -1)
{
int u = pop();
j = 1;
while(j < 5)
{
//if there is an epsilon transition from the state 'u' to 'v'
if(transitions[j][0] == u && transitions[j][4] != 232) //ASCII of Φ = 232
{
if(! IsVisited(transitions[j][4]))
{
visited[transitions[j][4]] = 1;
push(transitions[j][4]);
}
}
j++;
}
}
j = 0;
for(int edge = 0; edge < 10; edge++)
{
if(visited[edge] == 1)
e_closure[j++] = edge;
}
printf("e-closure(%d) : ",state);
for (i = 0; e_closure[i] != -1; ++i)
printf("%d ", e_closure[i]);
printf("\n");
}
int main()
{
file = fopen("nfa.txt","r");
if (file == NULL) {
perror("fopen");
return -1;
}
//Reading the states
while(!feof(file))
{
fscanf(file,"%s",a);
if(strcmp("//states",a) == 0)
flag = 1;
else if(strcmp("//input_symbols",a) == 0)
break;
if (flag == 1 && a[0] != '/')
{
states[i++] = a[1] - '0';
}
numberOfStates = i;
}
//Display the states of the e-NFA
printf("\nStates : \n");
for(i = 0; i < numberOfStates; i++ )
{
printf("q%d\n",states[i]);
}
i = 1;
flag = 0;
//Reading the transition table
for(int i = 0; i < 4; i++){
for(int j = 0; j < 5; j++)
{
transitions[i][j] = 232;
}
}
while(!feof(file))
{
fgets(a,100,file);
if(a[0] == '/')
{
flag = 1;
}
if(flag == 1 && a[0] != '/')
{
j = 0;
//found a way to store the transition table in a matrix
if(a[3] == 'e')
transitions[(a[1] - '0') + 1][4] = a[6] - '0';
else
transitions[(a[1] - '0') + 1][(a[3] - '0') + 1] = a[6] - '0';
if(a[3] != 'e')
transitions[0][a[3] - '0' + 1] = a[3] - '0'; //input
else
transitions[0][4] = -1; // epsilon input
transitions[(a[1] - '0') + 1][0] = a[1] - '0'; //initial state
}
}
printf("\nTransitions read\n");
for(int i = 0; i < 4; i++){
for(int j = 0; j < 5; j++)
{
printf("%d\t",transitions[i][j]);
}
printf("\n"); //detected segmentation fault here
}
//Calling e-closure for all the states
for(k = 0; k < numberOfStates; k++)
{
epsilon_closure(states[k]);
}
return 0;
}
There is a bug here:
int push(int data) {
if(!isfull()) {
top = top + 1;
stack[top] = data;
}
else
printf("Could not insert data, Stack is full.\n");
}
If top == MAXSIZE-1, isfull() will return false, then you increment top to MAXSIZE and assign stack[MAXSIZE] what is out of bounds and invokes UB. Not having checked the complete source code, I could imagine that incrementing top after assigning would be correct or you have to change isfull() to return true if top >= MAXSIZE-1
I am trying to make a loop that makes a pointer point to different elements in an array (Sorting in descending order) and I can't seem to get the comparing correctly since I always get an exception thrown. I also have a loop to print all the pointer's elements to test if the loop worked correctly. Never really used pointers before, but I tried to format them the same way I've seen on other websites when studying pointers. This is the part of code I am talking about:
//What I have included
#define _CRT_SECURE_NO_WARNINGS
#define MAX 5
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
//Variables related to the loops
int nums[MAX], *ptrd[MAX];
//Loops in question (Assume nums[MAX] = {1, 2, 3, 4, 5})
for (int i = 0; i < MAX; i++)
{
for (int j = 0; j < MAX; j++)
{
if (*ptrd[i] < nums[j] && nums[j] <= *ptrd[i - 1])
{
if (i > 0)
{
if (ptrd[i] == ptrd[i - 1])
continue;
}
ptrd[i] = &nums[i];
}
}
}
for (int i = 0; i < MAX; i++)
{
printf("\n%d", *ptrd[i]);
}
Current full code so far (note the code in question here is different):
#define _CRT_SECURE_NO_WARNINGS
#define MAX 5
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
//Variables
char input[20];
int nums[MAX], *ptrd[MAX], *ptra[MAX];
bool isValid;
//Methods
bool checkValidity();
void convertChars();
void resetInput();
int main()
{
printf("Please enter 5 numbers (Separate each by spaces): ");
input:
resetInput();
scanf(" %[^\n]%*c", &input);
isValid = checkValidity();
if (isValid == false)
{
printf("Invalid input. Retry: ");
goto input;
}
convertChars();
for (int i = 0; i < MAX; i++)
{
for (int j = 0; j < MAX; j++)
{
if (*ptrd[i] < nums[j])
{
if (i > 0)
{
if (ptrd[i] == ptrd[i - 1])
continue;
if (nums[j] <= *ptrd[i - 1])
ptrd[i] = &nums[i];
}
else
ptrd[i] = &nums[i];
}
}
}
for (int i = 0; i < MAX; i++)
{
printf("\n%d", (*ptrd)[i]);
}
getchar();
return 0;
}
bool checkValidity()
{
bool multNum = false;
int chars = 0;
for (int i = 0; i < 20; i++)
{
if (!isdigit(input[i]))
{
if (input[i] == ' ' && multNum == true || input[i] == NULL && multNum == true)
chars += 1;
if (input[i] != ' ' && input[i] != NULL)
{
printf("\nIncorrect characters\n");
return false;
}
if (input[i] == ' ' && multNum == false)
{
printf("\nToo many spaces at at once\n");
return false;
}
if (input[i] == ' ' && multNum == true || input[i] == NULL && multNum == true)
multNum = false;
}
else if (isdigit(input[i]))
{
multNum = true;
}
}
if (chars != 5)
{
printf("\nIncorrect amount of nums (%d)\n", chars);
return false;
}
else
return true;
}
void convertChars()
{
int placeHolder, nums_ = 0, done = 0;
for (int i = 0; i < 20 && done < 5; i++)
{
if (isdigit(input[i]))
{
placeHolder = input[i] - '0';
nums_ = (nums_ * 10) + placeHolder;
}
else
{
nums[done] = nums_;
nums_ = 0;
done += 1;
}
}
}
void resetInput()
{
for (int i = 0; i < 20; i++)
{
input[i] = NULL;
}
}
You didn't initialize *ptrd[MAX], which results in an undefined behavior. Run your code with gdb, and it crashes with following output:
(gdb) run
Starting program: /home/pringles/Desktop/a.out
Please enter 5 numbers (Separate each by spaces): 3 2 1 5 6
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400719 in main () at test.c:37
37 if (*ptrd[i] < nums[j])
By printing the elements in ptrd, you can see all the elements point to 0x0:
(gdb) print ptrd
$1 = {0x0, 0x0, 0x0, 0x0, 0x0}
I am in the process of creating hangman in C language, but there is one problem that I cannot quite grasp. When a user correctly guesses one of the letters that the word that is being guessed has, the program replaces all of previously guessed letters to the one user just put. What is the source of this problem?
#include<stdio.h>
#include <stdlib.h>
int main()
{
srand(time(NULL));
int x = 0, isCompleted, matchFound, numberOfTries = 7;
char letterGuess[1];
int randomIndex = rand()%14;
const char *wordArray[14];
const char *guessedWord[10];
const char *usedLetters[17];
for (int k = 0; k < 10; k++) {
guessedWord[k] = "_";
}
wordArray[0] = "butonierka";
wordArray[1] = "centyfolia";
wordArray[2] = "chiroplast";
wordArray[3] = "cmentarzyk";
wordArray[4] = "chrustniak";
wordArray[5] = "budowniczy";
wordArray[6] = "cholewkarz";
wordArray[7] = "cornflakes";
wordArray[8] = "brzydactwo";
wordArray[9] = "germanofil";
wordArray[10] = "lichtarzyk";
wordArray[11] = "lutowniczy";
wordArray[12] = "mikrocysta";
wordArray[13] = "tryskawiec";
const char *wordToGuess = wordArray[randomIndex];
for(int i = 0; i < 10; i++) {
printf(" %s ", guessedWord[i]);
}
printf("\n");
while(numberOfTries != 0 && isCompleted != 10) {
matchFound = 0;
isCompleted = 0;
printf("Please give a lowercase letter\n");
printf("Left tries: %d\n", numberOfTries);
scanf("%s", &letterGuess);
for (int z = 0; z < 17; z++) {
if (usedLetters[z] == letterGuess[0]) {
matchFound = 1;
}
}
if (letterGuess[0] >= 'a' && letterGuess[0] <= 'z' && matchFound == 0) {
usedLetters[x] = letterGuess[0];
x++;
for (int j = 0; j < 10; j++) {
if (letterGuess[0] == wordArray[randomIndex][j])
guessedWord[j] = letterGuess;
matchFound = 1;
}
}
if (matchFound == 0) {
numberOfTries--;
}
for(int z = 0; z < 10; z++) {
printf(" %s ", guessedWord[z]);
}
printf("\n");
} else {
if (matchFound == 1) {
printf("You've already given such letter!!\n");
} else {
printf("Wrong input, please try again!\n");
}
}
for (int k = 0; k < 10; k++) {
if (guessedWord[k] != "_") {
isCompleted++;
}
}
if (isCompleted == 10) {
printf("You have correctly guessed a word! Congrats!!\n");
}
printf("\n\n");
}
printf("The word was: %s\n", wordArray[randomIndex]);
printf("Game over!!\n");
}
The problem is that you're storing letterGuess, rather than individual characters. So each time letterGuess is updated with a new guess, all references to it change. Also, letterGuess is too short, leaving no room for the terminating null character.
The best solution is to make letterGuess a char (or an int), not an array, and to make guessedWord a char [] rather than a char *[]. There is no reason to use strings for single characters. That will solve the string-sharing problem.
iam new to c program and facing difficulty in debugging programs.In the below code test case 2 is not running.I have found that the error is in reading interger n in the second test case.someone please hep me with this issue.Also please recommend me with some tools that can be ued for debugging c programs using terminal.Thanks for help
#include <stdio.h>
#include <stdlib.h>
int read(){
int r = 0;
char c = getchar_unlocked();
while(c >= '0' && c <= '9'){
r = r*10 + c - 48 ;
c = getchar_unlocked();
}
return r;
}
void main(){
int t = 0;
t = read();
int rr = 0;
for(rr = 0;rr < t;rr++){
int i,n = 0;
n = read();
int *p = (int *)calloc(n,sizeof(int));
for(i = 0;i < n;++i){
*(p+i) = getchar_unlocked() - 48;
}
int no,nz = 0;
for(i = 0;i < n;++i){
if(*(p+i) == 0){nz += 1;}
if(*(p+i) == 1){no += 1;}
}
int k = 0;
if(((no)%2 == 0) && ((nz)%2) == 0){
k = -1;
}
if(((no)%2 == 0) && ((nz)%2) == 1){
k = 0;
}
if(((no)%2 == 1) && ((nz)%2) == 0){
k = 1;
}
if(((no)%2 == 1) && ((nz)%2) == 1){
k = 1;
}
int result = 0;printf("%d\n",5556);
if(k == 1){
for(i = 0;i < n;++i){
if(*(p+i) == 1){
result = i+1 ;
break;
}
}
}
if(k == 0){
for(i = 0;i < n;++i){
if(*(p+i) == 0){
result = i+1 ;
break;
}
}
}
printf("%d\n",result);
}
}
Your strategy to read an integer is flawed. You don't have the logic to skip whitespaces. I would change the function name to read_int and change its implementation to
int read(){
int n;
if ( scanf("%d", &n) != 1 )
{
// Deal with the error
}
return n;
}
Also, change
*(p+i) = getchar_unlocked() - 48;
to
*(p+i) = read_int();
or a more intuitive version:
p[i] = read_int();
With those changes, I am able to read and process the numbers. But I still get the wrong output. I'll let you figure the logic error in your code.
Additional Comments
main is expected to return an int. If your compiler didn't complain about that, it's time to up the warning level. I use -Wall by default.
When you are in the process of debugging your code, it's always good to test the code that reads the input to make sure that there is no error in reading the input.
Here's what I did to your code:
#include <stdio.h>
#include <stdlib.h>
int read_int(){
int n;
if ( scanf("%d", &n) != 1 )
{
// Deal with the error.
}
return n;
}
int main(){
int t = 0;
int rr = 0;
t = read_int();
printf("t = %d\n", t);
for(rr = 0;rr < t;rr++){
int i,n = 0;
n = read_int();
printf("n = %d\n", n);
int *p = (int *)calloc(n,sizeof(int));
for(i = 0;i < n;++i){
p[i] = read_int();
printf("p[%d] = %d\n", i, p[i]);
}
int no,nz = 0;
for(i = 0;i < n;++i){
if(*(p+i) == 0){nz += 1;}
if(*(p+i) == 1){no += 1;}
}
int k = 0;
if(((no)%2 == 0) && ((nz)%2) == 0){
k = -1;
}
if(((no)%2 == 0) && ((nz)%2) == 1){
k = 0;
}
if(((no)%2 == 1) && ((nz)%2) == 0){
k = 1;
}
if(((no)%2 == 1) && ((nz)%2) == 1){
k = 1;
}
int result = 0;
// printf("%d\n",5556);
if(k == 1){
for(i = 0;i < n;++i){
if(*(p+i) == 1){
result = i+1 ;
break;
}
}
}
if(k == 0){
for(i = 0;i < n;++i){
if(*(p+i) == 0){
result = i+1 ;
break;
}
}
}
printf("%d\n",result);
}
return 0;
}