Counting work days between two dates in C - c

I am writing a code in C with two functions.
The first (WorkDay) takes a date and says if it is a working day (return 1) or not (return 0). I think the first function is OK, although it could be better, but it is working. It includes weekends and public holidays in my country.
The problem comes with the second function (CountWorkDays). It should take two dates and say if they are correct (return 1) and in that case also say how many working days is among them, including the entered dates (cnt=). If the dates aren't correct (first is bigger than second etc.), there is return 0. I've tried to make a helping function next_day(), but I am pretty sure it is wrong. Can you help me with the second function please?
I cannot use <time.h> and I put there some asserts, which I am testing the function with.
#include <stdio.h>
#include <math.h>
#include <assert.h>
int WorkDay ( int y, int m, int d )
{
int h, day;
h= (d + floor(((m+1)*26)/10) + y + floor(y/4) + 6*floor(y/100) + floor(y/400));
day=h%7;
if ((y%4!=0) && m==2 && d==29)
return 0;
else if (((y%4==0 || y%400==0) && (y%100!=0 || y%4000!=0)) && m==2 && d==29)
{
if (day==2 || day==3 || day==4 || day==1 || day==0)
return 1;
else
return 0;
}
else if ((d==1 && m==1) || (d==1 && m==5) || (d==8 && m==5) || (d==5 && m==7) || (d==6 && m==7) || (d==28 && m==9) || (d==28 && m==10) || (d==17 && m==11) || (d==24 && m==12) || (d==25 && m==12) || (d==26 && m==12) || day==0 || day==1 || (m==1 && (d>31 || d<1)) || (m==2 && (d>29 || d<1)) || (m==3 && (d>31 || d<1)) || (m==4 && (d>30 || d<1)) || (m==5 && (d>31 || d<1)) || (m==6 && (d>30 || d<1)) || (m==7 && (d>31 || d<1)) || (m==8 && (d>31 || d<1)) || (m==9 && (d>30 || d<1)) || (m==10 && (d>31 || d<1)) || (m==11 && (d>30 || d<1)) || (m==12 && (d>31 || d<1)) || y<2000 || m>12 || m<1)
return 0;
else if (day==2 || day==3 || day==4 || day==5 || day==6)
return 1;
else
return 0;
}
int next_day()
{
int y1, m1, d1;
static int days_in_month[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned short day_counter;
d1 += 1; day_counter++;
if (d1 > days_in_month[m1])
{
d1 = 1;
m1 += 1;
if (m1 > 12)
{
m1 = 1;
y1 += 1;
if (((y1%4==0 || y1%400==0) && (y1%100!=0 || y1%4000!=0)))
{
days_in_month[2] = 29;
}
else
{
days_in_month[2] = 28;
}
}
}
return 0;
}
int CountWorkDays ( int y1, int m1, int d1,
int y2, int m2, int d2,
int * cnt )
{
int i,x;
if ( (m1==1 && (d1>31 || d1<1)) || (m1==2 && (d1>29 || d1<1)) || (m1==3 && (d1>31 || d1<1)) || (m1==4 && (d1>30 || d1<1)) || (m1==5 && (d1>31 || d1<1)) || (m1==6 && (d1>30 || d1<1)) || (m1==7 && (d1>31 || d1<1)) || (m1==8 && (d1>31 || d1<1)) || (m1==9 && (d1>30 || d1<1)) || (m1==10 && (d1>31 || d1<1)) || (m1==11 && (d1>30 || d1<1)) || (m1==12 && (d1>31 || d1<1)) || y1<2000 || m1>12 || m1<1 ||(m2==1 && (d2>31 || d2<1)) || (m2==2 && (d2>29 || d2<1)) || (m2==3 && (d2>31 || d2<1)) || (m2==4 && (d2>30 || d2<1)) || (m2==5 && (d2>31 || d2<1)) || (m2==6 && (d2>30 || d2<1)) || (m2==7 && (d2>31 || d2<1)) || (m2==8 && (d2>31 || d2<1)) || (m2==9 && (d2>30 || d2<1)) || (m2==10 && (d2>31 || d2<1)) || (m2==11 && (d2>30 || d2<1)) || (m2==12 && (d2>31 || d2<1)) || y2<2000 || m2>12 || m2<1 || y2>y1 || (y1==y2 && m2>m1) || (y1==y2 && m1==m2 && d2>d1) )
return 0;
else
{
while (y1!=y2 && m1!=m2 && d1!=d2)
{
while (next_day())
{
if (WorkDay( y1, m1, d1 ) == 1)
i=0;
x=i++;
}
}
*cnt=x;
return 1;
}
}
int main ( int argc, char * argv [] )
{
int cnt;
assert ( WorkDay ( 2016, 11, 11 ) );
assert ( ! WorkDay ( 2016, 11, 12 ) );
assert ( CountWorkDays ( 2016, 11, 1,
2016, 11, 30, &cnt ) == 1
&& cnt == 21 );
assert ( CountWorkDays ( 2001, 1, 1,
2015, 2, 29, &cnt ) == 0 );
return 0;
}

The problem is in next_day() and CountWorkDays().
next_day() is using local variables d1, m1 and y1. It is calculating next day of some random day.
In CountWorkDays(), you are not incrementing d1, m1, y1.
Solution:
Modify next_day() to receive a day as input and return next day as output.
int next_day(int *d, int *m, int *y)
{
/* Use current day to start. */
int y1 = *y;
int m1 = *m;
int d1 = *d;
/* Your code to find next day. Remove day_counter here as it is unnecessary.*/
/* Return next day. */
*y = y1;
*m = m1;
*d = d1;
return 0;
}
In CountWorkDays() call next_day with d1, m1, y1 as below.
else
{
while (1)
{
if (y1!=y2 && m1!=m2 && d1!=d2) //Check if end day is reached.
{
if (WorkDay( y1, m1, d1 ) == 1)
x++; //At the beginning initialize x to 0.
}
else
{
break;
}
next_day(&d1, &m1, &y1); //Get the next day.
}
}

int CountWorkDays(int y1, int m1, int d1, int y2, int m2, int d2, int * cnt)
{
int i, x;
if( (m1 == 1 && (d1>31 || d1<1)) || (m1 == 2 && (d1>29 || d1<1)) || (m1 == 3 && (d1>31 || d1<1)) || (m1 == 4 && (d1>30 || d1<1)) || (m1 == 5 && (d1>31 || d1<1)) || (m1 == 6 && (d1>30 || d1<1)) || (m1 == 7 && (d1>31 || d1<1)) || (m1 == 8 && (d1>31 || d1<1)) || (m1 == 9 && (d1>30 || d1<1)) || (m1 == 10 && (d1>31 || d1<1)) || (m1 == 11 && (d1>30 || d1<1)) || (m1 == 12 && (d1>31 || d1<1)) || y1<2000 || m1>12 || m1<1 ||
(m2 == 1 && (d2>31 || d2<1)) || (m2 == 2 && (d2>29 || d2<1)) || (m2 == 3 && (d2>31 || d2<1)) || (m2 == 4 && (d2>30 || d2<1)) || (m2 == 5 && (d2>31 || d2<1)) || (m2 == 6 && (d2>30 || d2<1)) || (m2 == 7 && (d2>31 || d2<1)) || (m2 == 8 && (d2>31 || d2<1)) || (m2 == 9 && (d2>30 || d2<1)) || (m2 == 10 && (d2>31 || d2<1)) || (m2 == 11 && (d2>30 || d2<1)) || (m2 == 12 && (d2>31 || d2<1)) || y2<2000 || m2>12 || m2<1 ||
y2>y1 || (y1 == y2 && m2>m1) || (y1 == y2 && m1 == m2 && d2>d1))
...
x++;
Your logic is wrong and redundant. You need to check only once if day is less than 1. You are checking at least 20 times. Then you check it again another 20 times in another function. You repeat that for d2. This makes your code unreadable and prone to errors.
Also you are not initializing variables. The starting value of x is undefined. Put int x = 0; and i = 0;
Later you have:
i=0;
x=i++;
You could rewrite this as x = 1. But you probably mean to write x++
Here it seems you are checking for holidays:
else if((
d == 1 && m == 1) ||
(d == 1 && m == 5) ||
(d == 8 && m == 5) ||
(d == 5 && m == 7) ||
(d == 6 && m == 7) ||
(d == 28 && m == 9) ||
(d == 28 && m == 10) ||
(d == 17 && m == 11) ||
(d == 24 && m == 12) ||
(d == 25 && m == 12) ||
(d == 26 && m == 12) ||
This type of coding is not wrong, but it's not practical either. I would put the holidays in a structure:
struct holidays_t
{
int day, month;
};
struct holidays_t holidays[] = {
{ 1 , 1 },
{ 1 , 5 },
...
};
Then loop through holidays array to see if the dates match. If you have not learned structures yet, then put the days and months in two different arrays. Example:
int holiday_days[]={1,1,...};
int holiday_months[]={1,5,...};
Your formula for weekday is wrong. You need to fix that.
#include <stdio.h>
#include <math.h>
int is_leap_year(int y)
{
return (y % 4) == 0 && y % 100 != 0 || (y % 400 == 0 && y != 4000);
}
int get_days_in_month(int year, int month)
{
const int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if(month >= 1 && month <= 12)
{
int days = days_in_month[month - 1];
if(month == 2 && is_leap_year(year))
days++;
return days;
}
return 0;
}
int is_date_valid(int year, int month, int day)
{
if(get_days_in_month(year, month) == 0) return 0;
return day >= 1 && day <= get_days_in_month(year, month);
}
//this is wrong: ***************************************************
int get_weekday(int y, int m, int d)
{
int h = (d + floor(((m + 1) * 26) / 10) + y + floor(y / 4) + 6 * floor(y / 100) + floor(y / 400));
int weekday = h % 7;
return weekday;
}
struct holidays_t
{
int day, month;
};
int is_holiday(int m, int d)
{
const struct holidays_t holidays[] = {
{ 1 , 1 },
{ 1 , 5 },
{ 8 , 5 },
{ 5 , 7 },
{ 6 , 7 },
{ 28, 9 },
{ 28, 10 },
{ 17, 11 },
{ 24, 12 },
{ 25, 12 },
{ 26, 12 },
};
int count = sizeof(holidays) / sizeof(holidays[0]);
int i;
for(i = 0; i < count; i++)
if(holidays[i].month == m && holidays[i].day == d)
return 1;
return 0;
}
int CountWorkDays(int y1, int m1, int d1, int y2, int m2, int d2, int *ptr)
{
int count = 0;
*ptr = 0;
if(!is_date_valid(y1, m1, d1)) return 0;
if(!is_date_valid(y2, m2, d2)) return 0;
int y, m, d;
for(y = y1; y <= y2; y++)
{
int month_start = 1;
int month_end = 12;
if(y == y1) month_start = m1;
if(y == y2) month_end = m2;
for(m = month_start; m <= month_end; m++)
{
int day_start = 1;
int day_end = get_days_in_month(y, m);
if(y == y1 && m == m1) day_start = d1;
if(y == y2 && m == m2) day_end = d2;
for(d = day_start; d <= day_end; d++)
{
int test = 0;
if(is_holiday(m, d))
{
test = 1;
printf("holiday %d %d %d\n", y, m, d);
}
int weekday = get_weekday(y, m, d);
if(weekday == 0 || weekday == 6)
{
test = 1;
printf("weekend %d %d %d %s\n", y, m, d, (weekday == 0) ? "sunday" : "staurday");
}
if(!test)
{
count++;
}
}
}
}
*ptr = count;
//return success
return 1;
}
int main()
{
int count = 0;
CountWorkDays(2016, 1, 1, 2016, 12, 31, &count);
printf("count %d\n", count);
return 0;
}

Related

Error expected identifier before '(' token in c

About
It's a program to calculate the actual age of a person with years, months and days.
I keep getting an error, and I'm not sure how to fix it.
Code:
#include <stdio.h>
int main(){
int dia,mes,anio;
int dia_n,mes_n, anio_n;
int edad_a,edad_m, edad_d;
printf("********Ingrese la fecha actual********\nDia:");
scanf("%d",&dia);
printf("Mes:");
scanf("%d", &mes);
printf("Anio:");
scanf("%d", &anio);
printf("********Ingrese la fecha de nacimiento********\nDia:");
scanf("%d",&dia_n);
printf("Mes:");
scanf("%d", &mes_n);
printf("Anio:");
scanf("%d", &anio_n);
if (dia_n>dia) && (mes_n>mes) || (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n){
edad_d=(dia - dia_n) +30;
}
else
if (dia>dia_n) || (dia_n==dia) && (mes>mes_n) || (mes_n>mes) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n){
edad_d=dia-dia_n;
}
if (dia>dia_n) || (dia==dia_n) && (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n) {
edad_m=mes-mes_n;
}
else
if (dia_n>dia)&&(mes_n>mes) || (mes==mes_n) && (anio>anio_n){
edad_m=(mes-mes_n) +11;
}
else
if (dia==dia_n) || (dia>dia_n) && (mes_n>mes) && (anio>anio_n){
edad_m=(mes-mes_n)+12;
}
else
if (dia_n>dia) && (mes>mes_n) && (anio>anio_n) || (anio==anio_n) {
edad_m=(mes-mes_n) -1;
}
if (dia>dia_n) || (dia==dia_n) && (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n) {
edad_a=anio-anio_n;}
else
if (dia_n>dia) && (mes_n>mes) || (mes>mes_n) || (mes==mes_n) && (anio>anio_n){
edad_a=(anio-anio_n)-1;
}
printf("********Su edad actual es********\n%d anios %d meses y %d dias", edad_a, edad_m, edad_d);
return 0;
}
Error:
22 19 C:\Users\Briansucho\Desktop\Sin Nombre2.c
[Error] expected identifier before '(' token
The problem in your code is your first if statement. Your code states:
if (dia_n>dia) && (mes_n>mes) || (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n){
This wrong because all those conditions need to be covered in a final (). What I mean is this:
if ((dia_n>dia) && (mes_n>mes) || (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n)){
You just required more (). That is why you are getting that error. Also, your code isn't clean and has a lot of error. I know I should do this, but here is your code all cleaned up error free.
#include <stdio.h>
int main(){
int dia,mes,anio;
int dia_n,mes_n, anio_n;
int edad_a,edad_m, edad_d;
printf("********Ingrese la fecha actual********\nDia:");
scanf("%d",&dia);
printf("Mes:");
scanf("%d", &mes);
printf("Anio:");
scanf("%d", &anio);
printf("********Ingrese la fecha de nacimiento********\nDia:");
scanf("%d",&dia_n);
printf("Mes:");
scanf("%d", &mes_n);
printf("Anio:");
scanf("%d", &anio_n);
if ((dia_n>dia) && (mes_n>mes) || (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio == anio_n)){
edad_d=(dia - dia_n) +30;
}
else if ((dia>dia_n) || (dia_n==dia) && (mes>mes_n) || (mes_n>mes) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n)){
edad_d=dia-dia_n;
}
if ((dia>dia_n) || (dia==dia_n) && (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n)) {
edad_m=mes-mes_n;
}
else if ((dia_n>dia)&&(mes_n>mes) || (mes==mes_n) && (anio>anio_n)){
edad_m=(mes-mes_n) +11;
}
else if ((dia==dia_n) || (dia>dia_n) && (mes_n>mes) && (anio>anio_n)){
edad_m=(mes-mes_n)+12;
}
else if ((dia_n>dia) && (mes>mes_n) && (anio>anio_n) || (anio==anio_n)) {
edad_m=(mes-mes_n) -1;
}
if ((dia>dia_n) || (dia==dia_n) && (mes>mes_n) || (mes==mes_n) && (anio>anio_n) || (anio==anio_n)) {
edad_a=anio-anio_n;}
else if ((dia_n>dia) && (mes_n>mes) || (mes>mes_n) || (mes==mes_n) && (anio>anio_n)){
edad_a=(anio-anio_n)-1;
}
printf("********Su edad actual es********\n%d anios %d meses y %d dias", edad_a, edad_m, edad_d);
return 0;
}

Finding mean of 3 numbers in c and avoid overflow. What's wrong with the code?

I want to find a mean of 3 numbers. The code works when all numbers are positive, but not when they're negative. What can I change?
int mean3(int a, int b, int c) {
if ((a < 0) || (b < 0) || (c < 0)) {
if ((a == b) && (b == c)) {
return a;
} else if (((a%3!=0) && (b%3!=0)) || ((a%3!=0) && (c%3!=0)) || ((b%3!=0) && (c%3!=0))) {
return (a/3)+(b/3)+(c/3);
} else {
return (a/3)+(b/3)+(c/3)-1;
}
} else {
if ((a == b) && (b == c)) {
return a;
} else if (((a%3!=0) && (b%3!=0)) || ((a%3!=0) && (c%3!=0)) || ((b%3!=0) && (c%3!=0))) {
return (a/3)+(b/3)+(c/3)+1;
} else {
return (a/3)+(b/3)+(c/3);
}
}
}
To prevent int overflow, use (a%3 +b%3+c%3)/3 to handle the division of the remainders. #EOF #Jean-François Fabre
int mean3pf(int a, int b, int c) {
return a/3 + b/3 + c/3 + (a%3 +b%3+c%3)/3;
}

Struggling with TicTacToe in C

I tried to program a simple TicTacToe in C. The program itselfs compiles and show no errors.
So the program draws the field, reads the names and let a player put his symbol in a specific field. All this happens in a while loop, the should be run until its a draw or someone wins.
But the program just run the loop one time so there is only one turn then the program stops.
So here is my code:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
#define NAMELENGTH 20
int main(void) {
char names[2][NAMELENGTH];
// field positions
char field[9];
int winner = -1;
getnames(names);
printf("\n\n");
initField(field);
// set field positions to 'empty'
char actualPlayer = (char)(get_random_number()*10.0) % 2;
while (1) {
drawField(field);
turn(actualPlayer, names, field);
winner = isWinner(actualPlayer, field);
drawField(field);
if (winner >= 1) {
printwinner(winner, names);
return 0;
}
else if (winner == 0) {
printDrawGame(names);
return 0;
}
actualPlayer = (actualPlayer + 1) % 2;
}
return 0;
}
game.h Headerfile:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define NAMELENGTH 20
#pragma warning(disable:4996)
extern void drawField(char *field);
extern void getnames(char nameField[][NAMELENGTH]);
extern void initField(char *field);
extern void turn(char actualPlayer, char names[][NAMELENGTH], char *field);
extern char isWinner(char actualPlayer, char *field);
extern void printwinner(char winnerNumber, char names[][NAMELENGTH]);
extern void printDrawGame(char names[][NAMELENGTH]);
extern double get_random_number();
and then my game.c where I defined my functions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "game.h"
#define NAMELENGTH 20
#pragma warning(disable:4996)
void drawField(char *field) {
printf("________________________\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[0], field[1], field[2]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[3], field[4], field[5]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[6], field[7], field[8]);
printf("|_______|_______|______|\n");
}
void getnames(char nameField[][NAMELENGTH]) {
printf("Name of the first player: ");
scanf("%s", nameField[0]);
printf("Name of the second player: ");
scanf("%s", nameField[1]);
}
void initField(char *field) {
for (int i = 0; i <= 8; i++)
{
field[i] = i + '1';
}
}
void turn(char actualPlayer, char names[][NAMELENGTH], char *field) {
char symbol = ' ';
int p1fieldnumber;
int p2fieldnumber;
if (actualPlayer == 0)
{
do {
printf("\nIts Player %s's turn.", names[0]);
char symbol = 'X';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%d", &p1fieldnumber);
if (field[p1fieldnumber] == 'X' || field[p1fieldnumber] == 'O')
{
printf("\nField is already occupied!");
p1fieldnumber = 10;
}
} while (p1fieldnumber < 1 || p1fieldnumber > 9);
field[p1fieldnumber-1] = 'X';
}
else {
do {
printf("\nIts Player %s's turn.", names[1]);
char symbol = 'O';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%d", &p2fieldnumber);
if (field[p2fieldnumber] == 'X' || field[p2fieldnumber] == 'O')
{
printf("\nField is already occupied!");
p2fieldnumber = 10;
}
} while (p2fieldnumber < 1 || p2fieldnumber > 9);
field[p2fieldnumber-1] = 'O';
}
}
char isWinner(char actualPlayer, char *field) {
char pwinner = '3';
if (((field[0] == 'O') && (field[1] == 'O') && (field[2] == 'O')) ||
(field[3] == 'O') && (field[4] == 'O') && (field[5] == 'O') ||
(field[6] == 'O') && (field[7] == 'O') && (field[8] == 'O') ||
(field[0] == 'O') && (field[4] == 'O') && (field[8] == 'O') ||
(field[2] == 'O') && (field[4] == 'O') && (field[6] == 'O') ||
(field[0] == 'O') && (field[3] == 'O') && (field[6] == 'O') ||
(field[1] == 'O') && (field[4] == 'O') && (field[7] == 'O') ||
(field[2] == 'O') && (field[5] == 'O') && (field[8] == 'O'))
{
pwinner = '2';
}
else if (((field[0] == 'X') && (field[1] == 'X') && (field[2] == 'X')) ||
(field[3] == 'X') && (field[4] == 'X') && (field[5] == 'X') ||
(field[6] == 'X') && (field[7] == 'X') && (field[8] == 'X') ||
(field[0] == 'X') && (field[4] == 'X') && (field[8] == 'X') ||
(field[2] == 'X') && (field[4] == 'X') && (field[6] == 'X') ||
(field[0] == 'X') && (field[3] == 'X') && (field[6] == 'X') ||
(field[1] == 'X') && (field[4] == 'X') && (field[7] == 'X') ||
(field[2] == 'X') && (field[5] == 'X') && (field[8] == 'X'))
{
pwinner = '1';
}
else if (((field[0] == 'X') || (field[0] == 'O')) && ((field[1] == 'X') || (field[1] == 'O')) && ((field[2] == 'X') || (field[2] == 'O')) ||
((field[3] == 'X') || (field[3] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[5] == 'X') || (field[5] == 'O')) ||
((field[6] == 'X') || (field[6] == 'O')) && ((field[7] == 'X') || (field[7] == 'O')) && ((field[8] == 'X') || (field[8] == 'O')) ||
((field[0] == 'X') || (field[0] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[8] == 'X') || (field[8] == 'O')) ||
((field[2] == 'X') || (field[2] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[6] == 'X') || (field[6] == 'O')) ||
((field[0] == 'X') || (field[0] == 'O')) && ((field[3] == 'X') || (field[3] == 'O')) && ((field[6] == 'X') || (field[6] == 'O')) ||
((field[1] == 'X') || (field[1] == 'O')) && ((field[4] == 'X') || (field[4] == 'O')) && ((field[7] == 'X') || (field[7] == 'O')) ||
((field[2] == 'X') || (field[2] == 'O')) && ((field[5] == 'X') || (field[5] == 'O')) && ((field[8] == 'X') || (field[8] == 'O')))
{
pwinner = '0';
}
return pwinner;
}
void printwinner(char winnerNumber, char names[][NAMELENGTH]) {
if (winnerNumber == '1') {
printf("Player %s won!", names[0]);
}
else if (winnerNumber == '2') {
printf("Player %s won!", names[1]);
}
}
void printDrawGame(char names[][NAMELENGTH]) {
printf("Draw!");
}
static int _initialized;
double get_random_number() {
if (!_initialized) {
srand(time(NULL));
_initialized = 1;
}
return (double)rand() / ((double)(RAND_MAX)+1);
}
There are multiple issues
isWinner returns characters '0', '1', '2' and '3'. Replace them with numbers 0, 1, 2, 3, because your are comparing with numbers in main.
In main instead of checking if (winner >= 1) {, which is true even if 3 is returned by isWinner, check for if (winner == 1 || winner == 2) {.
Suggest to use parentheses in isWinner around each condition separated by ||.
Parentheses as shown below for the first condition
if (((field[0] == 'O') && (field[1] == 'O') && (field[2] == 'O')) ||
((field[3] == 'O') && (field[4] == 'O') && (field[5] == 'O')) ||
((field[6] == 'O') && (field[7] == 'O') && (field[8] == 'O')) ||
((field[0] == 'O') && (field[4] == 'O') && (field[8] == 'O')) ||
((field[2] == 'O') && (field[4] == 'O') && (field[6] == 'O')) ||
((field[0] == 'O') && (field[3] == 'O') && (field[6] == 'O')) ||
((field[1] == 'O') && (field[4] == 'O') && (field[7] == 'O')) ||
((field[2] == 'O') && (field[5] == 'O') && (field[8] == 'O')))

Struggling programming TicTacToe in C

I'm new to C and programming and I tried to code a simple TicTacToe game. I new that I defintaly did many dumb things.
So I have a main .c file and two header files, which I will post here:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
#include "random.h"
#define NAMELENGTH 20
int main(void) {
char names[2][NAMELENGTH];
// field positions
char field[9];
int winner = -2;
getnames(names);
printf("\n\n");
initField(field);
// set field positions to 'empty'
char actualPlayer = (char)(get_random_number()*10.0) % 2;
while (1) {
drawField(field);
turn(actualPlayer, names, field);
winner = isWinner(actualPlayer, field);
drawField(field);
if (winner >= 0) {
printwinner(winner, names);
return 0;
}
else if (winner == -1) {
printDrawGame(names);
return 0;
}
actualPlayer = (actualPlayer + 1) % 2;
system("cls");
}
return 0;
}
game.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMELENGTH 20
#pragma warning(disable:4996)
void drawField(char *field) {
printf("________________________\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[1], field[2], field[3]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[4], field[5], field[6]);
printf("|_______|_______|______|\n");
printf("| | | |\n");
printf("| %c | %c | %c |\n", field[7], field[8], field[9]);
printf("|_______|_______|______|\n");
}
void getnames(char nameField[][NAMELENGTH]) {
printf("Name of the first player: ");
scanf("%s", &nameField[0]);
printf("Name of the second player: ");
scanf("%s", &nameField[1]);
}
void initField(char *field) {
for (int i = 1; i < 10; i++)
{
field[i] = i+48;
}
}
void turn(char actualPlayer, char names[][NAMELENGTH], char *field) {
char symbol = ' ';
int k;
int m;
if (actualPlayer == 1)
{
do {
printf("\nIts Player %s's turn.", names[0]);
char symbol = 'X';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%i", &k);
if (field[k] == 'X' || field[k] == 'O')
{
printf("\nField is already occupied!");
k = 10;
}
} while (k < 1 || k > 9);
field[k] = 'X';
}
else {
do {
printf("\nIts Player %s's turn.", names[1]);
char symbol = 'O';
printf("\nNumber of the field which you want to put your symbol in: ");
scanf("%i", &m);
if (field[m] == 'X' || field[m] == 'O')
{
printf("\nField is already occupied!");
m = 10;
}
} while (m < 1 || m > 9);
field[m] = 'X';
}
}
int isWinner(char actualPlayer, char *field) {
int w = 2;
if (((field[1] = 'O') && (field[2] = '0') && (field[3] = '0')) || (field[4] = '0') && (field[5] = '0') && (field[6] = '0') || (field[7] = '0') && (field[8] = '0') && (field[9] = '0') || (field[1] = '0') && (field[5] = '0') && (field[9] = '0') || (field[3] = '0') && (field[5] = '0') && (field[7] = '0') || (field[1] = '0') && (field[4] = '0') && (field[7] = '0') || (field[2] = '0') && (field[5] = '0') && (field[8] = '0') || (field[3] = '0') && (field[6] = '0') && (field[9] = '0'))
{
int w = 1;
}
if (((field[1] = 'X') && (field[2] = 'X') && (field[3] = 'X')) || (field[4] = 'X') && (field[5] = 'X') && (field[6] = 'X') || (field[7] = 'X') && (field[8] = 'X') && (field[9] = 'X') || (field[1] = 'X') && (field[5] = 'X') && (field[9] = 'X') || (field[3] = 'X') && (field[5] = 'X') && (field[7] = 'X') || (field[1] = 'X') && (field[4] = 'X') && (field[7] = 'X') || (field[2] = 'X') && (field[5] = 'X') && (field[8] = 'X') || (field[3] = 'X') && (field[6] = 'X') && (field[9] = 'X'))
{
int w = 0;
}
else
{
int w = -1;
}
return w;
}
void printwinner(char winnerNumber, char names[][NAMELENGTH]) {
if (winnerNumber == 0)
{
printf("Player %s won!", names[0]);
system("exit");
}
else if (winnerNumber == 1)
{
printf("Player %s won!", names[1]);
system("exit");
}
}
void printDrawGame(char names[][NAMELENGTH]) {
printf("Draw!");
system("exit");
}
and random.h:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int _initialized;
void init() {
srand(time(NULL));
_initialized = 1;
}
double get_random_number() {
init();
if (!_initialized)
printf("Warning: init() should be called first!\n");
double random;
random = (double)rand() / ((double)(RAND_MAX)+1);
return random;
}
So the Program itself runs till I type in which field I want to put in the symbol. I get a weird error ("Stack around the variable 'field' was corrupted.") and also the random function doesnt work like I want. Would be happy and thankful for you help guys :)
You declared field to be an array of 9 elements. The indices will be 0 to 8. In game.h you have a function initField in which you do:
for (int i = 1; i < 10; i++)
{
field[i] = i+48;
}
This will produce indices 1 to 9, which steps out of bounds for the array.
You reinitialize the random number generator each time it is called. You pseudo random values will not be very random I'm afraid.
Fix it this way:
static int _initialized;
double get_random_number() {
if (!_initialized) {
srand(time(NULL));
_initialized = 1;
}
return = (double)rand() / ((double)(RAND_MAX)+1);
}
You should not write code in header files. Declarations belong in header files, code belongs in source files with the extension .c.

Is my code correctly portraying the diagram?

What my function does, is it takes the values of the profit (function declared as fieldProfit) and the field score (function declared as fieldScore); and if both are above 10, then you earn a badge, hence, innerbadge = 1. BUT, there's also another condition that must be met, the field or (x, y) coordinates, have to fall in the area depicted as the shaded in box that has a hole in the middle. I've written the code for it, and I just wanted to make sure that my logic/syntax is correct! Any help is appreciated!
Here's my code:
int badgeInnerCircle(int x, int y) {
double fprofit, fscore;
int innerbadge;
if ((x >= 1 && x <= 20) && (y >= 1 && y <= 20)) {
if (((x == 7 || x == 8) && (y >= 7 && y <= 14)) || ((x == 13 || x == 14)
&& (y >= 7 && y <= 14)) || ((x >= 7 && x <= 14) && (y == 7 || y == 8))
|| ((x >= 7 && x <= 14) && (y == 13 || y == 14))) {
fprofit = fieldProfit(x, y);
fscore = fieldScore(x, y);
if (fprofit >= 10 && fscore >= 10) {
innerbadge = 1;
}
else {
innerbadge = 0;
}
}
}
else {
innerbadge = -1;
}
return innerbadge;
}
no, your code is not correct.
int innerbadge;
if (condition) {
if (condition) {
if (condition) {
innerbadge = 1;
}
else {
innerbadge = 0;
}
}
//else unidentified!
}
else {
innerbadge = -1;
}
you should change the initialisazion to "int innerbadge = 0;" or something approriate

Resources