An error with the logic in creating a basic calendar program - c

I made a program just for testing purposes, when you hold the key 'p' on the keyboard it spills out every day starting from the 1st of January 2012, it should continue on to 2013 and it does although it goes to 32 January 2013, and this is an error which I have no idea how to fix, I've been trying to fix this problem for a few hours now and nothing seems to make it work as it should.. (should go to 1st February 2013 after 31st of January)
here is my code:
#include <stdio.h>
#include <stdlib.h>
int month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int day = 0;
int year = 2012;
char *months[]=
{
" ",
" January ",
" February ",
" March ",
" April ",
" May ",
" June ",
" July ",
" August ",
" September ",
" October ",
" November ",
" December "
};
int x = 1; //skip the blank element 0, get to January (element 1)
int main()
{
while(1)
{
char ch;
ch = getch(); //in_char();
if(ch == 'p')
{
day++;
if(day == month[x]+1)
{
day = 1; //day is equal to the first day of the new month
month[x]++; //month data increments
months[x]++; //month display increments
x++; //element of month array increments to get the data of the next month
if(year % 4 == 0) //leapyear
{
month[2] = 29;
}
else
{
month[2] = 28;
}
if(x == 13) //if 12 months have passed
{
year++; //year increments
day = 1; //initialize day to be day 1 of the next year
x = 1; //go back to the 'January' element in the array
if(day == month[x]) //if day is equal to the first month (January) 31 days
{
day = 1;
month[x]++; //month data increments
months[x]++; //month display increments
}
}
}
if(year == 9999)
{
year = 1;
}
printf("%i%s%04i\n",day,months[x],year);
}
}
return 0;
}
output:
.
.
.
28 December 2012
29 December 2012
30 December 2012
31 December 2012
1January 2013
2January 2013
3January 2013
4January 2013
5January 2013
6January 2013
7January 2013
8January 2013
9January 2013
10January 2013
11January 2013
12January 2013
13January 2013
14January 2013
15January 2013
16January 2013
17January 2013
18January 2013
19January 2013
20January 2013
21January 2013
22January 2013
23January 2013
24January 2013
25January 2013
26January 2013
27January 2013
28January 2013
29January 2013
30January 2013
31January 2013
**32January 2013**
1February 2013
2February 2013
.
.
.

The problem is here:
if(day == month[x]+1)
{
day = 1; // reset date...OKAY
month[x]++; // NOT OKAY
by doing month[x]++ you are incrementing the number of days allowed in the month. Instead you need to keep a variable to track the month,just as you've done with day and year..

Related

How can I use the for loop instead of printf statement to execute for a enumerated list as below code?

Using enumerated lists.
Output on execution of using the printf statement - 6 7 8 2 3 4 6 7 8 1 2 3
However I wish to use the for loop to execute the enumerated lists instead of the printf statement.
#include<stdio.h>
enum Month
{
January=6, February, March, April=2, May, June, July=6, August, September, October=1, November, December
};
int main()
{
enum Month m;
int i;
// printf("%d %d %d %d %d %d %d %d %d %d %d %d", January, February, March, April, May, June, July, August, September, October, November, December);
for(m=January; m<=December; m++)
{
printf("%d \n ", ?); //what should be the statement ?
}
return 0;
}
How can I write the for loop such that it executes from jan to december, instead of having to use the
printf("%d %d %d %d %d %d %d %d %d %d %d %d", January, February, March, April, May, June, July, August, September, October, November, December) statement to print the values?
Here's the corrected answer.
#include<stdio.h>
enum Month
{
January=6, February, March, April=2, May, June, July=6, August, September, October=1, November, December
};
int main()
{
int i;
enum Month *month_order[] = { January, February, March, April, May, June, July, August, September, October, November, December };
for (i = 0; i < 12; i++)
{
printf("%d\n", month_order[i]);
}
return 0;
}
Thanks to the above users for giving me insights.
Usage of pointer to an array, would make it more easy for function calling and storage.
This also gives perfect output as required.
The initialization of the month names under enum Month can be changed as per need.
Basically, you can't. You can only iterate over the numeric values with ++. Had your enum values been from say January = 3 to December = 14 in monotonic order without gaps, then - and only then - your approach would have worked.
The only way to do that with arbitrary values order and a loop is that you store the values in that order into an array:
enum Month month_order = { January, February, March, April, May, June, July,
August, September, October, November, December };
for (size_t i = 0; i < 12; i++) {
printf("%d\n", (int)month_order[i]);
}
To avoid repetition you could use the X-macro technique here but it actually wouldn't save keystrokes.

How i make restrictions into a variable

I'm new in C language and I have a question.
I have to create a program where I put the number of days I worked in every single month.
I already done that but I need to restrict the days by the number of days of each month .
Example : January more than 1 day less than 31 , February more than 1 but less than 28 etc...
int numero_dias, mes;
for (mes = 0; mes != 12; mes++){
do {
printf("Digite o
numero de dias trabalhados no mes %s: ", meses[mes]);
scanf("%d", &numero_dias);
if (meses[mes] == 0 meses[mes] == 2 meses[mes] == 4 meses[mes] == 6 meses[mes] == 7 meses[mes] == 9 meses[mes] == 11 ){
if (numero_dias < -1 || numero_dias > 31){
continue;
}else{
break;
}
}
If I understand your question correctly, you want to:
Enter the number of days you worked in a month;
Check that the number of days you entered does not exceed the number of days for that month.
So, if you're entering the number of days you worked for the month of January, that number has to be between 0 and 31 (I'm assuming it's possible you can work zero days in a month). For the month of February it has to be between 0 and 28 (29 in a leap year), for April it has to be between 0 and 30, etc.
An easy way to do this is to set up an array to keep track of the number of days per month, indexed by the month number (0 for January, 1 for February, etc.):
/**
* We're declaring this const so that we can't accidentally change any
* of the entries in the array.
*/
const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
We'll have to add some special-case processing for February to deal with leap years, but for this first pass we won't worry about it.
It may also be useful to have another array1 for the month names, since you try to display that in your loop:
const char *names[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
So now your loop becomes:
for (mes = 0; mes < 12; mes++ )
{
do
{
printf( "Digite o numero de dias trabalhados no mes %s: ", names[mes] );
scanf ( "%d", &numero_dias );
} while ( numero_dias < 0 || numero_dias > days[mes] );
// do something with numero_dias
}
The inner do loop will repeat while numero_dias is outside the range of 0 and days[mes]. So when mes is 0, days[mes] is 31, when mes is 3, days[mes] is 30, etc.
February (1) is a special case - it can be either 28 or 29 days. So we need to modify the condition of the do loop slightly:
do
{
...
} while ( numero_dias < 0 || numero_dias > ( mes != 1 ? days[mes] : feb_days() ) );
The expression mes != 1 ? days[mes] : feb_days() checks to see if mes corresponds to February (1) - if it doesn't, then we use the value in days[mes] (January, March, April, May, etc.). If it does, then we call another function feb_days() that returns the number of days in February for the current year.
So the condition in the do-while loop now checks to see if numero_dias is less than zero or greater than the number of days for the current month, with a special case for February.
To get the number of days in February for the current year, you can do the following:
int feb_days( void )
{
time_t now = time( NULL ); // Get number of seconds since 1970-01-01
struct tm *utc = gmtime( &now ); // Break time into year, month, day, etc.
int days = 28; // default number of days in Feb
return days + (utc->tm_year % 4 == 0 && (utc->tm_year % 100 != 0 || utc->tm_year % 400 == 0 ));
}
The expression (utc->tm_year % 4 == 0 && (utc->tm_year % 100 != 0 || utc->tm_year % 400 == 0 )) will evaluate to 1 if the current year is divisible by 4 and it's not divisible by 100 or it is divisible by 400. If any of those conditions are not true, then it evaluates to 0. So if this is not a leap year, we return 28 + 0 == 28 days. If it is a leap year, we return 28 + 1 == 29 days.
There's a lot more bulletproofing that needs to be done - you need to check the return value of scanf to make sure your input was actually read correctly (and take action to clear the input stream if it wasn't), you probably want to give your user a way to cancel the input operation, etc., but this should get you started.
Actually, we'd use a single array of a struct type instead of separate arrays, but I'm trying to keep things basic.

return the day of the week with day, month, year and first of January provided?

I have the C99 as follow:
int dayOfWeek(int day, int month, int year, int firstJan);
The first parameter, day, provides the day of interest − range from 1 to 31 (inclusive). The second parameter, month, provides the month of interest − range from 1 to 12 (inclusive). The third parameter, year, provides the year of interest − any integer value of 1970 or greater. The fourth parameter, firstJan, indicates the day of the week on which the first of January falls in the provided year.
The function will return the day of the week on which the indicated date falls. For example, the call:
dayOfWeek(13, 11, 2017, 0);
will return the integer 1 (representing Monday).
How can I approach the solution? Its permitted values are 0 (representing Sunday), 1 (representing Monday), and so on, up to 6 (representing Saturday). Code has been edit:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int dayOfweek(int day, int month, int year, int firstJan)
5 {
6 int mth[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
7 int mth_leap[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
8
9 if(year <1970 || month < 1 || month > 12 || day < 1 || day > 31 || firstJan < 0 || firstJan > 6 ){
10 printf("invalid input");
11 //return -1;
12 }
13
14 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)){
15 day = mth_leap[month - 1] + day ;
16 }else{
17 day = mth[month - 1] + day;
18 }
19
20 int dow = (day - firstJan + 7)%7;
21 printf("Day of week is %i.\n", dow);
22 //return 1;
23
24 }
Day of the week is found simply with mktime().
The mktime function
On successful completion, the values of the tm_wday and tm_yday components of the structure are set appropriately, and the other components are set to represent the specified calendar time,
#include <time.h>
int dayOfWeek(int day, int month, int year, int /*firstJan*/) {
// struct tm members domain are: years from 1900, and months since January
// Important to set tm_isdst = -1 to let the function determine dst setting.
struct tm ymd = { .tm_year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_isdst = -1);
time_t t = mktime(&ymd); // this will fill in .tm_wday
if (t == -1) return -1; // Failed to find a valid calender time (and day-of-the-week)
return ymd.tm_wday;
}
How can I approach the solution?
Yet OP has a function that provides the day-of-the-week for Jan 1st.
Some pseudo code for that approach:
int dayOfWeek(int day, int month, int year, int firstJan) {
days_since_jan1 = table[month] + day;
if (month > Feb and isleap(year)) days_since_jan1++;
dow = (days_since_jan1 - firstJan + 7)%7
}

Tabbing a Calendar console application using C

I am implementing a simple yearly calendar in traditional format in a console application using ANSI C. The calendar must be tabbed to show in the format of 3 x 4 months. Till now I managed to display all the months beneath each other as shown in the code below. Any help how can I tackled the tabbing part? I tried to split the month[] into 3 according to the column for example Jan, April, July and October will be the 1st column and then work column by column, but I don't know if it is the best thing to do...any help please?
#include<stdio.h>
int main()
{
int d,y,no_lp,n,i=1,j,month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
printf("Enter year:");
scanf("%d", &y);
if (y%4==0)
{month[2]=29;}
no_lp= (27 + (42/5) + (y-1) + ((y-1)/4) - ((y-1)/100) + ((y-1)/400) + 1);
d= no_lp%7;
n=d;
for(j=1;j<=12;j++)
{
printf("\n\n %s",monthname[j]);
//printf ("\n\n%d",j);
printf("\n Su Mo Tu We Th Fr Sa\n");
while(d--!=0)
printf(" "); //spaces for empty days
while(i<=month[j])
{
if(i<10)
{printf(" %d ",i++);} //formating for dates with 2 digits
else{printf("%d ",i++);}//formatting for dates with 1 digit
n++;
if(n==7) //if 7 is reached start new line
{
n=0;
printf("\n");
}
}
d=n;
i=1; //n will be the 1st day of next month
}
return(0);
}
You can replace
if(i<10)
{printf(" %d ",i++);} //formating for dates with 2 digits
else{printf("%d ",i++);}//formatting for dates with 1 digit
with
printf("%2d ",i++);
In order to print 3 * 4, don't print on the fly
Store those values
char out[12][6][24];
| | |
n months <- | -> string containing week in calendar (e.g 10 11 12 13 14 15 17)
V
Max weeks in a month
and print
week 1 month 1 , week 1 month 2 , week 1 month 3
week 2 month 1 , week 2 month 2 , week 2 month 3
week 3 month 1 , week 3 month 2 , week 3 month 3
...
week 1 month 4 , week 1 month 5 , week 1 month 6
week 2 month 4 , week 2 month 5 , week 2 month 6
week 3 month 4 , week 3 month 5 , week 3 month 6
...
...

Is there something wrong with my date code?

Description: given a date after START_GREGORIAN_CALENDAR, this function returns the number of days until the next Thursday. For example, for 16 March 2011 (2011,3,16), the function will return 1, and for 17 March 2011 (2011,3,17), the function will return 7.
int daysToNextThursday (int year, int month, int day) {
int Thursday;
Thursday = 7;
return (Thursday - day);
}
The code compiles correctly, but when I input a date, e.g. 16 3 2011, I do not get the right answer. Note this is apart of a larger amount of code that I have written, which works perfectly.
Any ideas?
Yes, I have an idea. My idea is that you go back and rethink the algorithm you've selected for determining that a day is Thursday. It's dead wrong :-)
Now, like a broken clock that's right twice a day, you may find input parameters that give you the correct answer but they'll be the exception rather than the rule.
If you want to figure out when next Thursday is from a given date, C provides date and time functions for exactly that purpose:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
static char *textday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
int main (int argc, char *argv[]) {
int year, month, day, today, thursday;
struct tm *mytm;
time_t mytime;
// Get all arguments (minimal error checks).
if (argc != 3) {
printf ("Usage: next_thursday <year> <month>\n");
return -1;
}
year = atoi (argv[1]);
month = atoi (argv[2]);
// Do first fourteen days of the month.
for (day = 1; day <= 14; day++) {
Up until there, it's just getting parameters and starting the loop. The meat of the calculation is below, setting up a useful struct tm and then forcing our year, month and day into it. Then mktime will fill in the tm_wday (day of week) field for us and we can use that to figure out the number of days till Thursday.
// Make the tm structure based on date (and midday).
mytime = time (0);
mytm = localtime (&mytime);
mytm->tm_year = year - 1900;
mytm->tm_mon = month - 1;
mytm->tm_mday = day;
mytm->tm_hour = 12;
mytime = mktime (mytm);
// Output filled in fields and days till next Thursday.
today = mytm->tm_wday;
thursday = (11 - today) % 7;
if (thursday == 0)
thursday = 7;
printf ("%04d-%02d-%02d, weekday = %d (%s), days till Thu = %d\n",
mytm->tm_year + 1900, mytm->tm_mon + 1, mytm->tm_mday,
today, textday[today], thursday);
}
return 0;
}
Note that the thursday calculation is a bit of modulus trickery - it's simply used to give us the number of days based on the following table:
today thursday
------- --------
0 (sun) 4
1 (mon) 3
2 (tue) 2
3 (wed) 1
4 (thu) 7
5 (fri) 6
6 (sat) 5
If you want a more readable solution, you can use:
if (today < 4) thursday = 4 - today;
else thursday = 11 - today;
This program outputs the following for 2011-03:
2011-03-01, weekday = 2 (Tue), days till Thu = 2
2011-03-02, weekday = 3 (Wed), days till Thu = 1
2011-03-03, weekday = 4 (Thu), days till Thu = 7
2011-03-04, weekday = 5 (Fri), days till Thu = 6
2011-03-05, weekday = 6 (Sat), days till Thu = 5
2011-03-06, weekday = 0 (Sun), days till Thu = 4
2011-03-07, weekday = 1 (Mon), days till Thu = 3
2011-03-08, weekday = 2 (Tue), days till Thu = 2
2011-03-09, weekday = 3 (Wed), days till Thu = 1
2011-03-10, weekday = 4 (Thu), days till Thu = 7
2011-03-11, weekday = 5 (Fri), days till Thu = 6
2011-03-12, weekday = 6 (Sat), days till Thu = 5
2011-03-13, weekday = 0 (Sun), days till Thu = 4
2011-03-14, weekday = 1 (Mon), days till Thu = 3

Resources