When I enter the date 08/01/2015 the program prints 00/00/00 instead of 08/01/2015. What seems to be the problem?
#include <stdio.h>
int main ()
{
int month = 0;
int day = 0;
int year = 0;
printf("Enter today's date (mm/dd/yyyy): ");
scanf("%i/%i/%i", &month, &day, &year);
printf("%.2i/%.2i/%.2i", month, day, year);
return 0;
}
I amended your original program to deal with several issues. But the main one was to use the correct format specifier %d in scanf(). Using %i will interpret an input as octal if it has a leading 0 - very likely when typing a date, especially as you encourage that with the output format. Months 01 to 07 did not fail because the octal input works correctly - but 08 and 09 do not, as 8 and 9 do not exist in octal number representation.
I also checked the return value from scanf() to ensure the integer date fields were correctly entered. If you had done that, you would have seen there was something wrong there.
Other things I changed are:
Checked the date you entered to be valid to avoid the GIGO syndrome.
Avoided writing to the array of days per month as commented earlier.
Restricted the year to the Gregorian calendar, as some days were missing.
Separated form from functionality. For example, your leapYear() function checked for a leap year and also tested (inadequately) - and reported errors in the date entered.
Moved the global date variables to be local vars, which are passed as function arguments.
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
int daysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int leapyear(int year) {
return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}
int validdate(struct date now) {
int daysmon;
if (now.year <= 1582) // pre-Gregorian
return 0;
if (now.month < 1 || now.month > 12)
return 0;
daysmon = daysPerMonth[now.month-1];
if (leapyear(now.year) && now.month == 2)
daysmon++;
if (now.day < 1 || now.day > daysmon)
return 0;
return 1;
}
struct date bumpdate(struct date now) {
int daysmon = daysPerMonth[now.month-1];
if (leapyear(now.year) && now.month == 2)
daysmon++;
if (++now.day > daysmon) {
now.day = 1;
if (++now.month > 12) {
now.month = 1;
now.year++;
}
}
return now;
}
int main (void) {
struct date today, tomorrow;
printf("Enter today's date (mm/dd/yyyy): ");
if (3 != scanf("%d %*[/-] %d %*[/-] %d", &today.month, &today.day, &today.year)) {
printf ("Need the proper date format\n");
return 1;
}
if (!validdate(today)) {
printf ("Invalid date\n");
return 1;
}
tomorrow = bumpdate(today);
printf("Tomorrow's date is %02d/%02d/%04d", tomorrow.month, tomorrow.day, tomorrow.year);
return 0;
}
Related
Write a program that for a date read from SI (in the format DD MM YYYY) will print on standard output a message YES if the date is correct and possible, or NO if the date is not correct.
When deciding whether the date is correct or not correct, you have to consider the following factors:
is the month between January and December (1-12)
does the number for days correspond with the number of days in the specified month
if the month is February, is the year leap?
Leap years are those years who are divisible with 400, or they are divisible with 4, but not with 100
#include<stdio.h>
int main()
{
int day,month,year;
scanf("%d %d %d", &day, &month, &year);
for(month=1;month<=12;month++){
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0) ) {
printf("YES");
} else
printf("NO");
}
return 0;
}
You need an array of the days in a month and then check if the month is between 1 and 12. If the month is exactly 2, you should first check for leap years.
Something like this:
int daysInMonth = {31, 28, ...}; //replace ... with actual information
if(month < 1 || month > 13) {
//month isn't valid
printf("NO");
return 0;
}
month -= 1; //to convert to 0-indexed
if(month == 1 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) {
//month is february and is leap year
daysInMonth[1] += 1; //february now has 29
}
if(day < 1 || day > daysInMonth[month]) {
//day isn't valid
printf("NO");
return 0;
}
//When getting to this point it means we have a valid date
printf("YES");
return 0;
Please note that this does not handle some very special edge cases, explained here. These include the days that don't exist because of the switch from Julian to Gregorian calendar. But I'm almost certain that these are not what the exercise was asking for anyways. You may also want to check against negative years, depending on the exact definition of a valid year.
As others have mentioned, you don't need to loop [on the month].
You should get the number of days in a month by indexing into an array (vs. switch).
Adding some extra boolean flags can help simplify things.
Anyway, here's a refactored version with some descriptive comments:
// is the month between January and December (1-12)
// does the number for days correspond with the number of days in the specified
// month
// if the month is February, is the year leap?
// Leap years are those years who are divisible with 400, or they are
// divisible with 4, but not with 100
#include <stdio.h>
#include <stdlib.h>
int days_in_month[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 31, 31, 30, 31
};
int
main(int argc,char **argv)
{
int day, month, year;
int month_valid;
int leap_year;
int max_days;
int day_valid;
int date_valid;
--argc;
++argv;
if (argc == 3) {
month = atoi(argv[0]);
day = atoi(argv[1]);
year = atoi(argv[2]);
}
else {
if (0)
scanf("%d %d %d", &day, &month, &year);
else
scanf("%d %d %d", &month, &day, &year);
}
// is month in range?
month_valid = (month >= 1) && (month <= 12);
// is it a leap year?
leap_year = (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
// get number of days in month [if month is valid]
if (month_valid)
max_days = days_in_month[month - 1];
else
max_days = -1;
// february in a leap year has an extra day
if (month == 2)
max_days += leap_year;
// is day of the month valid?
day_valid = (day >= 1) && (day <= max_days);
// is entire date valid?
date_valid = month_valid && day_valid;
if (date_valid)
printf("YES\n");
else
printf("NO\n");
return 0;
}
I am working on a program that a user enters a date and then the program adds 7 days and prints out the date entered and then prints out the date with seven days added. I am getting the month and date correctly formatted and it appears that it is adding the seven days. However, the year is printing as four zeros and I am not quite sure what I am missing. Below is a screen show of the results and the code follows. Can someone let me know what is needed to print out the year please?
Result:
Please enter a date formatted as mm/dd/yyyy: 02/02/2000
The date you entered is: 02/16/0000
The date in seven days will be: 02/23/0000
Process returned 0 (0x0) execution time : 7.071 s
Press any key to continue.
#include <stdio.h>
#include <stdbool.h>
//This is a global definition of struct for date so it can be utilized for any function within the program.
struct date
{
int month;
int day;
int year;
};
//This will add the seven days to the date entered by the user
struct date newDate (struct date today)
{
struct date week;
int daysOfMonth (struct date d);
if(today.day != daysOfMonth(today))
{
week.day = today.day+7;
week.month = today.month;
week.year = today.year;
}
else if(today.month == 12)//end of month
{
week.day = 1;
week.month = today.month = 1;
week.year = today.year +1;
}
else //end of year
{
week.day = 1;
week.month = today.month+1;
week.year = today.year;
}
return week;
}
//Function to find the number of days in a month
int daysOfMonth (struct date d)
{
//Declare variables to be used within function
int days;
bool flagLeapYear (struct date d);
const int daysOfMonth [12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (flagLeapYear (d) == true && d.month == 2)
days = 29;
else
days = daysOfMonth[d.month - 1];
return days;
}
//Function to determine if it is a leap year
bool flagLeapYear (struct date d)
{
bool flagLeapYear;
if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0)
flagLeapYear = true; //It is a leap year
else
flagLeapYear = false; // Not a leap year
return flagLeapYear;
}
int main(void)
{
struct date newDate (struct date today);
struct date entered, seven;
printf("Please enter a date formatted as mm/dd/yyyy: ");
scanf(" %i%i%i", &entered.month, &entered.day, &entered.year);
seven = newDate (entered);
printf("\nThe date you entered is: %.2i/%.2i/%.4i", entered.month, entered.day, entered.year);
printf("\nThe date in seven days will be: %.2i/%.2i/%.4i", seven.month, seven.day, seven.year);
return 0;
}
Thanks,
Annette
You are using wrong format specifier, e.g. %.2i -> %02d:
// ...
printf("Please enter a date formatted as mm/dd/yyyy: ");
scanf("%d/%d/%d", &entered.month, &entered.day, &entered.year);
seven = newDate (entered);
printf("\nThe date you entered is: %02d/%02d/%04d", entered.month, entered.day, entered.year);
printf("\nThe date in seven days will be: %02d/%02d/%04d", seven.month, seven.day, seven.year);
// ...
How to add the value 09 in an array as it can't be inserted as it shows the value is octal value and can't be inseted then how can we insert it into the array is there any method..
#include<stdio.h>
#include<stdlib.h>
void prin(int day, int year) {
int data[3];
data[0] = day;
data[1] = 09;
data[2] = year;
printf("%d.%d.%d",data[0],data[1], data[2]);
}
void check(int year) {
int day;
if (1700 <= year && year <= 1917) {
if (year % 4 == 0) {
//printf("The year is leap year");
day = 12;
prin(day, year);
}
else {
day = 13;
prin(day, year);
}
}
else {
//printf("REached");
if(year % 400 == 0 || (year % 4 == 0 && year % 100 == 0)) {
//printf("Year is not leap");
day = 13;
prin(day, year);
}
else {
day = 12;
prin(day, year);
}
}
}
int main(void) {
int year;
//printf("Enter the value of the year");
scanf("%d",&year);
check(year);
return 0;
}
The error is as follows :
Day_of_programmer.c: In function 'prin':
Day_of_programmer.c:7:15: error: invalid digit "9" in octal constant
7 | data[1] = 09;
| ^~
Here's the problem:
data[1] = 09;
The leading 0 tells the compiler that it should expect an octal constant, which only contains the digits 0 through 7. Just get rid of the leading 0:
data[1] = 9;
Then the compiler will treat it as an ordinary decimal value.
This is what your prin function should be:
void prin(int day, int year) {
printf("%02d.%02d.%04d",day, 9, year);
}
But actually you probably want rather this at the end of the day, because it's pretty pointless to print a date with a fixed month:
void prin(int day, int month, int year) {
printf("%02d.%02d.%04d", day, month, year);
}
If you use %d, the number is printed without any non significant
zeros.
If you use %02d, the number will be printed with two digits,
non significant digits will be replaced with 0.
If you use %2d, the number will be printed with two digits,
non significant digits will be replaced by whitespac .
Read up the documentation of printf, especially the part dealing with the different variants of the %d format specifier.
Concerning the error message error: invalid digit "9" in octal constant, the other answer answers this.
Can anyone spot what's wrong with my code?
It should simply compare Dates and the earliest one should get recorded, however only my first input is. Walked through it slowly can't see where my logic error is.
#include <stdio.h>
int main(void)
{
int month=1, day=1, year=1;
int fmonth=0, fday=0, fyear=0;
while((month != 0) && (day != 0) && (year != 0))
{
printf("Enter the date: (0/0/0 to cancel) ");
scanf("%d/%d/%d", &month, &day, &year);
if(fyear < year)
{
fyear = year;
fmonth = month;
fday = day;
}
else if ((fyear == year) && (fmonth < month) && (fday <= day))
{
fyear=year;
fmonth=month;
fday=day;
}
}
printf("Earliest Date is: %d/%d/%d\n", fmonth,fday,fyear);
return 0;
}
Hah, this was kinda fun. Your primary problem was you had your comparisons turned around backwards. (and you needed to add a (month == fmonth) test) Your secondary problem was a total failure to validate user input -- it will bite you every time.
First, you want to check if (date < fdate) before assigning, not if (fdate < date) or you will overwrite your earlier date with a later one (as yuchaun correctly noted originally).
Always, always, validate user input. For all you know a cat may be stepping on the keyboard. At minimum, at least check the return of scanf to validate that the number of conversions to int you expected, did in fact take place (validating the values fall into valid month, day, year ranges is left to you).
Putting those pieces together, and replacing the "0/0/0" cancellation with a simple counter to determine when you have two dates entered, you could do something similar to:
#include <stdio.h>
int main (void) {
int month = 1, day = 1, year = 1,
fmonth = 0, fday = 0, fyear = 0,
n = 0; /* simple counter - no need for 0/0/0 */
while (1) { /* just loop until you have 2 dates */
printf ("Enter the date: ");
/* validate ALL User Input */
if (scanf ("%d/%d/%d", &month, &day, &year) != 3) {
fprintf (stderr, "error: invalid date, exiting.\n");
return 1;
}
/* if no fdate or if (date < fdate) then fdate = date */
if (!n || (year < fyear) ||
((year == fyear) && ((month < fmonth) ||
((month == fmonth) && (day < fday))))) {
fyear = year;
fmonth = month;
fday = day;
}
if (++n == 2) /* increment counter and test */
break;
}
printf ("Earliest Date : %d/%d/%d\n", fmonth, fday, fyear);
return 0;
}
Example Use/Output
$ ./bin/earlierdate
Enter the date: 12/21/1991
Enter the date: 12/22/1991
Earliest Date : 12/21/1991
$ ./bin/earlierdate
Enter the date: 12/22/1991
Enter the date: 12/21/1991
Earliest Date : 12/21/1991
When you run into a problem like this, always see How to debug small programs and don't be shy about talking to the duck... it works!
Look things over, and consider all answers, and let me know if you have any further questions.
Some errors in your code include:
if (fyear < year): Say previously I got fyear = 2015, now I scan year = 2012. Is 2015 < 2012 ? So, the conditions will be reversed, right?
Now the problem with reversing is, fmonth=0, fday=0, fyear=0. Suppose, I scan year = 2012. So, check (fyear > year) ⇒ (0 > 2012)? It won't be updated. So, change the initialization.
Lastly, if you scan 0/0/0, and say our present fyear = 2012 and year = 0. So, fyear > year ⇒ 2012 > 0, this updates the whole thing to 0/0/0. We need to take care the when to scan because while loop executes the whole thing before checking the previous scan.
(fyear == year) && (fmonth < month) && (fday <= day) What if only present month is less than the previous? The conditions should be ||
So, I think you can draw a solution like this,
#include <stdio.h>
#include <limits.h>
int main(void)
{
int fmonth=INT_MAX, fday=INT_MAX, fyear=INT_MAX, month=INT_MAX, year = INT_MAX, day = INT_MAX;
while(month != 0 && year != 0 && day != 0)
{
if(year<fyear || (year==fyear && month<fmonth) || (year==fyear && month==fmonth && day<fday))
{
fyear = year;
fmonth = month;
fday = day;
}
printf("Enter the date: (0/0/0 to cancel) ");
scanf("%d/%d/%d", &month, &day, &year);
}
printf("Earliest Date is: %d/%d/%d\n", fmonth,fday,fyear);
return 0;
}
Since the decision tree is hard to debug and write, you should first ensure that all months and days are within a proper range.
Then it's just a matter of assigning a proper weight to each digit in this possibly mixed radix number system:
int days_total = w_y * years + w_m * months + w_d * days;
And same for the other date. The comparison reduces to comparing this linearized date with any w_d >= 1, w_m >= 31, w_y >= 366.
Suggested values are 1,32 and 512 for best performance.
You're actually overwriting the value of fyear,fmonth,fdays when the date entered is LATER than the stored fyear/month/day, which I don't think is your intention
I get the following output:
$ ./a.out
Enter the date: (0/0/0 to cancel) 1/2/3
Enter the date: (0/0/0 to cancel) 3/4/5
Enter the date: (0/0/0 to cancel) 0/0/0
Earliest Date is: 3/4/5
$ ./a.out
Enter the date: (0/0/0 to cancel) 3/4/5
Enter the date: (0/0/0 to cancel) 1/2/3
Enter the date: (0/0/0 to cancel) 0/0/0
Earliest Date is: 3/4/5
$ ./a.out
Enter the date: (0/0/0 to cancel) 1/2/3
Enter the date: (0/0/0 to cancel) 0/0/0
Earliest Date is: 1/2/3
so it's not just the first input that's being captured, but the date recorded is the latest, not the earliest.
You made a little mistake when comparing in
if(fyear < year)
Since you save the user input in variable year, you only record the date which is the latest, not the earliest.
But simply changing the operator won't work here, you need to implement this program anew. Try imaging how the comparison works best.
Tips:
Maybe try using ranges for days and month (1 <= day <= 28, 30, 31 and 1 <= month <= 12)
Your idea to compare first the year in your second if-statement was okay, now try the same for month and day like this:
if(year <= fyear) {
if(month <= fmonth) {
if(day <= day) {
fday = day;
fmonth = month;
fyear = year;
}else{
/* nothing happens, since date
* is later than the current */
}
}else{
// your logic here
}
}else{
// your logic here
}
Maybe assign the values to the fyear, fmonth and fday variables immediately when they are all 0. Because when comparing to input dates, an if-statement which checks wether the input date is earlier than the initial (0/0/0) date will always fail.
Here, I edited your code and included some statements to make the program user friendly. I think this will ensure your requirement. And also you have to consider, Feb 29(leap year) month,year date > 0.
#include<stdio.h>
int main(void)
{
int month=1, day=1, year=1;
int fmonth, fday, fyear;
printf("Enter the date: (0/0/0 to cancel)\n ");
scanf("%d/%d/%d", &fday, &fmonth, &fyear);
while(1)
{
printf("1.Do you want to continue.\n2.print the result.\n");
int ch;
scanf("%d",&ch);
if(ch==2){break;}
printf("Enter the date: (0/0/0 to cancel)\n ");
scanf("%d/%d/%d", &day, &month, &year);
if(fyear > year)
{
fyear = year;
fmonth = month;
fday = day;
}
else if ((fyear == year) && (fmonth > month))
{
fyear=year;
fmonth=month;
fday=day;
}
else
{if ((fyear == year) && (fmonth == month) && (fday > day))
{
fyear=year;
fmonth=month;
fday=day;
}
}
}
printf("Earliest Date is: %d/%d/%d\n",fday,fmonth,fyear);
return 0;
}
I want to add x number of days to a date.
Can someone help me with my logic especially in adding x number of days to a specific date.
It seems to work for small number of days added but if I add a large number of days, it starts to give really funny answers.
Also no functions please, just logic.
int
main(int argc, char *argv[]) {
int dd, mm, yyyy, daysthismonth, days, option;
printf("Please enter a date in the following format: dd/mm/yyyy:\n");
if(scanf("%d/%d/%d",&dd,&mm,&yyyy)!= 3){
printf("Please enter a valid date\n");
exit(EXIT_FAILURE);
/* Calculating days in a month */
}
if((mm == 4)|| (mm == 6) || (mm == 9) || (mm == 11)){
daysthismonth = 30;
}
else if((mm == 2)){
if((yyyy%4 == 0) && ( (yyyy%100 == 0) || (yyyy%400 == 0))){
daysthismonth = 29;
}
else{
daysthismonth = 28;
}
}
else {
daysthismonth = 31;
}
/* Calculating the validity of User Input */
if( (dd<0) || (dd>daysthismonth) || (mm<0) || (mm>12) || (yyyy < 0) || (yyyy>9999) ){
printf("Plase enter a valid date between from a day from 0 AD to 9999 AD\n.");
}
printf("Todays date: %02d/%02d/%04d\n"
"How many days would you like to go in the future? \n",dd,mm,yyyy);
if(scanf("%d",&days) != 1){
printf("Please enter a valid input\n");
}
printf("The date %d days in the future is:\n",days);
while(days > (daysthismonth - dd)){
mm = mm + 1;
days = days - (daysthismonth - dd);
if( days < daysthismonth){
dd = days;
}
if( mm>12){
mm = 1;
yyyy = yyyy + 1;
}
}
dd = dd + days;
}
printf(" %02d/%02d/%04d\n",dd,mm,yyyy);
exit(EXIT_SUCCESS);
}
I guess my logic was if you added a large number of days, it would subtract the next month's days until you get to a point where the days to be added is less than the days in the month. At that point the date can just be the days you have to add.
That's why I implemented a while? loop so it could reiterate
edited: scanf() != 1
Just store your day/month/year into a struct tm, call mktime() on it to convert to epoch seconds, add days*24*60*60 to advance it, then call localtime_r() (or localtime()) on the result to get day/month/year again.
Be mindful of daylight saving time: you should probably set the hours component to noon to avoid any possibility of gaining or losing a day when DST changes.
So you want to add days on a date.
The easy logic is to convert the date to days, add the x days, then convert days to date.
The complex logic is to just make the add like in maths
yyyy/mm/dd
+ dd
-----------
result
like in the maths the numbers can only be from 0-9 here the date / month / year have to be valid based on the rest.
converting the days you want to add to date before the add and then add before making valid can help.
Example in javascript (so that you can easy run it on the browser's console):
function daysInMonth(month,year){
// Does not matter how you make this function
return new Date(year, month, 0).getDate();
}
var year = 2014;
var month = 8;
var day = 8;
var daysToAdd = 123434;
day += daysToAdd;
var maxDay = daysInMonth( month, year);
while( day>maxDay ){
day -= maxDay;
month += 1;
if(month==13){
month = 1;
year += 1;
}
maxDay = daysInMonth( month, year);
}
console.log(day+'/'+month+'/'+year);
It works like a charm :)
C code (After a request) :
#include <stdio.h>
main(){
// Init the variables we use
int year = 0;
int month = 0;
int day = 0;
int maxDay = 0;
int daysToAdd = 0;
// Ask user for a date
printf("Please enter a date in the following format: dd/mm/yyyy:\n");
// Validate data
while( scanf( "%d/%d/%d", &day, &month, &year)!= 3 || day<=0 || month<=0 || year<0 || daysInMonth(month,year)<day ){
printf("Please enter a valid date.\n");
}
// Ask user for days to add
printf("Please enter days to add: \n");
// Validate data
while( scanf( "%d", &daysToAdd)!= 1 || daysToAdd<=0 ){
printf("Please enter a positive number.\n");
}
// Calculate date
day += daysToAdd;
maxDay = daysInMonth( month, year);
while( day>maxDay ){
day -= maxDay;
month += 1;
if(month==13){
month = 1;
year += 1;
}
maxDay = daysInMonth( month, year);
}
printf("Result date : %d/%d/%d", day, month, year);
return(0);
}
// Get days in the month
int daysInMonth( int month, int year){
if( month==4 || month==6 || month==9 || month==11 ){
return 30;
}else if( month== 2 ){
if( year%4==0 && ( year%100==0 || year%400==0) )
return 29;
else
return 28;
}else{
return 31;
}
}
Online test link : http://ideone.com/CGXgtP
Happy coding.