Segfault on disease simulator - c

I am trying to program a disease simulator in C. For some reason after around 20-25 iterations of the while(1) loop, it segfaults. It is completely random. I have been trying to fix this problem for several hours, so any help would be much appreciated.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct space {
int type;
int x, y;
} space_t;
space_t space[40][40];
int main(){
bool infected = false;
int i = 0;
int x = 0;
int y = 0;
srand(time(NULL));
while(i < 1600){
space[x][y].x = x;
space[x][y].y = y;
if(rand() % 9 == 0 && !infected){
space[x][y].type = 1;
infected = true;
}
if(rand() % 20 == 8){
space[x][y].type = 2;
}
x++;
i++;
if(x == 40){
x = 0;
y++;
}
}
system("clear");
int count;
int inf = 0;
while(1){
x = 0;
y = 0;
i = 0;
while(i < 1600){
if(space[x][y].type == 1){
inf++;
}
if(space[x][y].type == 1 && rand() % 9 > 4){
if(rand() % 9 > 4){
space[x+(rand() % 3)][y].type = 1;
} else {
space[x+(-(rand() % 3))][y].type = 1;
}
} else if(space[x][y].type == 1 && rand() & 9 > 4){
if(rand() % 9 > 4){
space[x][y+(rand() % 3)].type = 1;
} else {
space[x][y+(-(rand() % 3))].type = 1;
}
}
if(space[x][y].type == 1){
printf("[I]");
} else if(space[x][y].type == 2){
printf("[D]");
} else printf("[ ]");
x++;
i++;
if(x == 40){
printf("\n");
x = 0;
y++;
}
}
count++;
printf("%d\n", count);
printf("%d\n", inf);
sleep(1);
system("clear");
}
return 0;
}

Code generates random offsets for an index but does not insure in proper range.
if(space[x][y].type == 1 && rand() % 9 > 4){
if(rand() % 9 > 4){
// Nothing forces `x+(rand() % 3)` in legal index range.
space[x+(rand() % 3)][y].type = 1;
} else {
space[x+(-(rand() % 3))][y].type = 1;
}
}
Instead
if(space[x][y].type == 1 && rand() % 9 > 4) {
int r = rand();
if(r % 9 > 4) {
int offset = x + r%3;
if (offset < 40) space[offset][y].type = 1;
} else {
int offset = x - r%3;
if (offset >= 0) space[offset][y].type = 1;
}
}
... // similar change for next block
Note: later on code, certainly rand() & 9 should be rand() % 9 (% not &).

Related

cs50: pset1: credit: Stuck, all cards entered invalid

Been working on this problem set for the past few hours and I thought I was doing pretty well, but when I ran it, doesn't really work as expected.
Kinda stuck at the moment, can anyone offer some insight?
EDIT
Sorry guys, I'll provide a little more insight on the problem because too little info is provided for it in my post. So basically I have to implement the Luhn's algorithm. According to Luhn’s algorithm, you can determine if a credit card number is (syntactically) valid as follows:
Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.
Add the sum to the sum of the digits that weren’t multiplied by 2.
If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0), the number is valid!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("type a credit card number: ");
char ccnum[17];
fgets(ccnum, 17, stdin);
int ccnumber[15];
int n = strlen(ccnum);
for (int i = 0; i<16; i++)
{
ccnumber[i] = ccnum[i] -'0';
}
int ccnumber_m[7];
for (int i = 0; i < 16; i+=2)
{
ccnumber_m[i] = ccnumber[i]*2;
}
int sum = 0;
for (int i = 0; i < 8; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
printf("%d\n", sum);
}
for (int i = 1; i < 16; i+=2)
{
sum += ccnumber[i];
}
if (sum%10 == 0)
{
if ( (n == 15) && (ccnumber[0] == 34 || ccnumber[0] == 37))
{
printf("AMEX\n");
}
else if ((n == 16) && (ccnumber[0] == 51 || ccnumber[0] == 52 ||ccnumber[0] == 53 || ccnumber[0] == 54 || ccnumber[0] == 55))
{
printf("MASTERCARD\n");
}
else if ((n == 13 || n == 16) && ccnumber[0] == 4)
{
printf("VISA\n");
}
}
else
{
printf("INVALID\n");
}
}
I've added a printf to my sum variable to see where the program is failing and that's where things seem to be screwing up. Every time I run it, different values of sum appear?!
Thanks in advance.
Okay guys, found the solution. Yes I messed up most of my loops and the array ranges and the conditions were all over the place. Did some tweaks to my code overall and after a few more hours, the code works as expected. Here's the updated code.
Pretty sure the code could be more succinct and could be solved much faster. Will take a look at it tomorrow again in order to brainstorm more ideas and find ways to solve it faster.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("type a credit card number: ");
char ccnum[17];
fgets(ccnum, 17, stdin);
int ccnumber[15];
int n = strlen(ccnum);
int counter = 0;
for (int i = 0; i < n; i++)
{
ccnumber[i] = ccnum[i] -'0';
if (ccnumber[i] >= 0)
{
counter ++;
}
}
int sum = 0;
if (counter == 16)
{
int ccnumber_m[7];
int index = 0;
for (int i = counter - 2; i > -1 ; i-=2, index++)
{
ccnumber_m[index] = ccnumber[i]*2;
}
for (int i = 0; i < 8; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
}
for (int i = 1; i < counter + 1; i+=2)
{
sum += ccnumber[i];
}
}
else if (counter == 15)
{
int ccnumber_m[6];
int index = 0;
for (int i = counter-2; i > 0; i-=2, index++)
{
ccnumber_m[index] = ccnumber[i]*2;
}
for (int i = 0; i < 7; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
}
for (int i = 0; i < counter + 1; i+=2)
{
sum += ccnumber[i];
}
}
else if(counter == 13)
{
int ccnumber_m[5];
int index = 0;
for (int i = counter-2; i > 0; i-=2, index++)
{
ccnumber_m[index] = ccnumber[i]*2;
}
for (int i = 0; i < 6; i++)
{
if (ccnumber_m[i] > 9)
{
sum += (ccnumber_m[i] % 10) + 1;
}
else
{
sum += ccnumber_m[i];
}
}
for (int i = 0; i < counter + 1; i+=2)
{
sum += ccnumber[i];
}
}
else
{
printf("INVALID\n");
return 0;
}
if (sum%10 == 0)
{
if ((counter == 15) && ((ccnumber[0] == 3 && ccnumber[1] == 4) || (ccnumber[0] == 3 && ccnumber[1] == 7)))
{
printf("AMEX\n");
}
else if ((counter == 16) && ((ccnumber[0] == 5 && ccnumber[1] == 1) || (ccnumber[0] == 5 && ccnumber[1] == 2) || (ccnumber[0] == 5 && ccnumber[1] == 3) || (ccnumber[0] == 5 && ccnumber[1] == 4) || (ccnumber[0] == 5 && ccnumber[1] == 5)))
{
printf("MASTERCARD\n");
}
else if ((counter == 13 || counter == 16) && (ccnumber[0] == 4))
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
else
{
printf("INVALID\n");
return 0;
}
}

Why am I still getting the "expected identifier" error?

I'm new to programming (currently learning C and working alongside the cs50x course). I'm doing the Problem Set 1, Card. I'm supposed to make a program where you type a credit card number and it gives you the type of credit card (AMEX, VISA, etc). I need help with this error: "Error: expected identifier or '('"
Here is the code:
#include <stdio.h>
#include <cs50.h>
void print_credit_card_brand(long long ccn);
bool check_validity(long long credit_card_number);
int find_lenght(long long n);
bool checksum(long long ccn);
int main(void)
{
long long credit_card_number;
do
{
credit_card_number = get_long_long("Number: \n");
}
while (credit_card_number < 0);
if (check_validity(credit_card_number) == true)
print_credit_card_brand(credit_card_number);
else
printf ("INVALID\n");
}
bool check_validity(long long credit_card_number);
{
int len = find_lenght(credit_card_number);
return (len = 13 || len = 15 || len = 16) && checksum(credit_card_number);
}
int find_lenght(long long n);
{
int len;
for (int len = 0; n ! = 0; n/=10, len++)
return len;
}
bool checksum(long long ccn);
{
int sum = 0;
for (int i = 0; ccn!= 0; i++; ccn/= 10)
{
if(i % 2 == 0)
sum += ccn % 10;
else
{
int digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
return (sum % 10) == 0;
}
}
void print_credit_card_brand(long long ccn);
{
if ((ccn >= 34e13 && ccn < 32e13) || (ccn >= 37e13 && ccn < 38e13))
printf ("AMEX\n");
else if (ccn >= 51e14 && ccn < 56e14)
printf("MASTERCARD\n");
else if ((ccn >= 4e12 && ccn < 5e12) || (ccn >= 4e15 && ccn < 5e15))
printf("VISA\n");
else printf("INVALID\n");
}
Remove semicolon here. :D
bool check_validity(long long credit_card_number); <--------
{
int len = find_lenght(credit_card_number);
return (len = 13 || len = 15 || len = 16) && checksum(credit_card_number);
}
int find_lenght(long long n); <---------
.
.
.
You have some typos in your code:
Every function definition has an extra ; at the end, remove them all.
bool checksum(long long cc);
{ ^
//...
}
This:
return (len = 13 || len = 15 || len = 16) && checksum(credit_card_number);`
^ ^ ^
You probably want ==.
This:
for (int i = 0; ccn!= 0; i++; ccn/= 10)
^
You probably want:
for (int i = 0; ccn!= 0; i++, ccn/= 10)
This:
for (int len = 0; n ! = 0; n/=10, len++)
^
You'll want to remove that space and make it !=.

CS50 Problem set 1 Credit - can't find the logic error

When I enter a credit card number that should work it outputs "INVALID" when it should output the credit card brand. I believe something is going wrong in the validity function but i can't seem to figure out what. I've spent a couple hours trying to fix the problem but nothing has worked. It would be great if I could get some help, thanks so much!
This is my code:
#include <stdio.h>
#include <cs50.h>
bool validity(long long creditNum);
int find_length(long long n);
bool checksum(long long ccn);
void credit_card_num(long long ccn);
int main(void)
{
long long creditNum;
do
{
creditNum = get_long_long("Enter Card Number: ");
}
while(creditNum < 0);
if (validity(creditNum) == true)
credit_card_num(creditNum);
else
printf("INVALID\n");
}
bool validity(long long creditNum)
{
int length = find_length(creditNum);
if ((length == 13 || length == 15 || length == 16) && checksum(creditNum))
return true;
else
return false;
}
int find_length(long long n)
{
int length;
for (length = 0; n != 0; n/= 10)
length++;
return length;
}
bool checksum(long long ccn)
{
int sum = 0;
int digit;
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
if (i % 2 == 0)
sum += ccn % 10;
else
digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
if ((sum % 10) == 0)
return true;
else
return false;
}
void credit_card_num(long long ccn)
{
if ((ccn >= 34e13 && ccn < 35e13) || (ccn >= 37e13 && ccn < 38e13))
printf("AMEX\n");
else if (ccn >= 51e14 && ccn < 56e14)
printf("MASTERCARD\n");
else if ((ccn >= 4e12 && ccn < 5e12) || (ccn >= 4e15 && ccn < 5e15))
printf("VISA\n");
else
printf("INVALID\n");
}
It looks like your error is in your checksum function; specifically, the for loop.
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
if (i % 2 == 0)
sum += ccn % 10;
else
digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
should be
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
if (i % 2 == 0){
sum += ccn % 10;
} else {
digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
}
There was incorrect nesting around your if-else statement. I tested with a couple numbers and they printed the correct output.
First of all, it would be great if you included the "get_long_long" function, so we could see how the input is taken.
Secondly, the digit variable inside the checksum function wasn't initialized, which caused some problems.
Lastly, from a brief look here, you kinda implemented the algorithm in a wrong way, I fixed it, please check that the result is working for you:
bool checksum(long long ccn)
{
int sum = 0;
int digit;
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
digit = ccn % 10;
if (i % 2 != 0) {
digit *= 2;
if (digit > 9)
digit -= 9;
}
sum += digit;
}
if ((sum % 10) == 0)
return true;
else
return false;
}

My program gives the correct output in windows(gcc) but in Linux(gcc) it leads to segmentation fault

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

C programming / what is the difference between these two codes [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
What is the difference between these two codes? I think it's same code.
It can't operate both of codeup and Visual Studio.
codeup.kr 1505 problem
The problem for array
when you put number it
it makes num*num array
For example, given num = 3, it creates:
1 2 3
8 9 4
7 6 5
Code 1:
#include<stdio.h>
#include<string.h>
int main()
{
int tile[52][52];
int x, y;
int num;
int start = 1;
int check = 1, complete = 1;
int i;
scanf("%d", &num);
memset(tile, 0, 4 * 52 * 52);
tile[0][1] = 10;
tile[1][num + 1] = 10;
tile[num + 1][num + 1] = 10;
tile[num + 1][0] = 10;
x = 1; y = 1;
for (i = 0; i <= 3000; i++)
{
switch (check)
{
case 1:
{
if (tile[x][y + 1] != 0)
{
check += 1;
break;
}
tile[x][y++] = start;
start++;
complete++;
break;
}
case 2:
{
if (tile[x + 1][y] != 0)
{
check += 1;
break;
}
tile[x++][y] = start;
start++;
complete++;
break;
}
case 3:
{
if (tile[x][y - 1] != 0)
{
check += 1;
break;
}
tile[x][y--] = start;
start++;
complete++;
break;
}
case 4:
{
if (tile[x - 1][y] != 0)
{
check = 1;
break;
}
tile[x--][y] = start;
start++;
complete++;
break;
}
}
if (complete == num*num)
{
break;
}
}
if (num % 2 == 0)
{
tile[x][y] = start;
}
else
{
tile[x][y++] = start;
}
for (x = 1;x <= num; x++)
{
for (y = 1; y <= num; y++)
{
printf("%d ", tile[x][y]);
}
printf("\n");
}
}
This code operates in Visual Studio.
#include<stdio.h>
int main()
{
int tile[52][52];
int x, y;
int num;
int start = 1;
int check = 1, complete = 1;
int i;
scanf("%d", &num);
for (x = 0;x <= num; x++)
{
for (y = 0; y <= num; y++)
{
tile[x][y] = 0;
}
}
tile[0][1] = 10;
tile[1][num+1] = 10;
tile[num + 1][num + 1] = 10;
tile[num + 1][0] = 10;
x = 1; y = 1;
for (i = 0; i <= 3000; i++)
{
switch (check)
{
case 1:
{
if (tile[x][y + 1] != 0)
{
check += 1;
break;
}
tile[x][y++] = start;
start++;
complete++;
break;
}
case 2:
{
if (tile[x + 1][y] != 0)
{
check += 1;
break;
}
tile[x++][y] = start;
start++;
complete++;
break;
}
case 3:
{
if (tile[x][y - 1] != 0)
{
check += 1;
break;
}
tile[x][y--] = start;
start++;
complete++;
break;
}
case 4:
{
if (tile[x - 1][y] != 0)
{
check = 1;
break;
}
tile[x--][y] = start;
start++;
complete++;
break;
}
}
if (complete == num*num)
{
break;
}
}
if (num % 2 == 0)
{
tile[x][y] = start;
}
else
{
tile[x][y++] = start;
}
for (x = 1;x <= num; x++)
{
for (y = 1; y <= num; y++)
{
printf("%d ", tile[x][y]);
}
printf("\n");
}
}
The difference:
$ diff -w one.c two.c2,3d1
< #include<string.h>
<
14,15c12,16
< memset(tile, 0, 4 * 52 * 52);
<
---
> for (x = 0; x <= num; x++) {
> for (y = 0; y <= num; y++) {
> tile[x][y] = 0;
> }
> }
95a97
>
so, the first one uses memset to set all entries of tile to 0 (zero) and the second one uses a loop to set only the entries of tile to zero that are used, the content of the rest of the cells is undefined, could be everything. You can look for some places where x and/or y are outside of 0 <= x <= num < 52 in your code, or step through with a debugger, or use printf()s to find the exact places.
If you do not want to use memset() or are not able too: just change the loop to zero every cell out:
for (x = 0; x < 52; x++) {
for (y = 0; y < 52; y++) {
tile[x][y] = 0;
}
}

Resources