I am trying to make this program which takes YYYY and MM from the user. I have defined macros outside the main function, which is kinda range for years to be taken as input. For months, i have declared JAN and DEC as 1 and 12 respectively. What I am trying to is,show an error when something(month and year) is out of range, and the loop should repeat untill the right input has been entered. I tried my best to do that, but i didnt get anything. here is my code.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MIN_YEAR 2012
#define MAX_YEAR 2022
int main(void)
{
const int JAN = 1;
const int DEC = 12;
int year = 0;
int month = 0;
do
{
printf("Set the year and month(YYYY MM): ");
scanf(" %d %d", &year, &month);
if ((MIN_YEAR > year && year > MAX_YEAR))
{
printf("ERROR: The year must be between 2012 and 2022 inclusive");
}
if ((JAN >= month >= DEC))
{
printf("ERROR: Jan.(1) - Dec.(12)");
}
else
{
printf("*** Log date set! ***");
}
} while (MIN_YEAR <= year <= MAX_YEAR , JAN <= month <= DEC);
return 0;
}
This condition
if ((MIN_YEAR > year && year > MAX_YEAR))
is logically incorrect. It seems you mean
if ( year < MIN_YEAR || year > MAX_YEAR )
The condition in this if statement
if ((JAN >= month >= DEC))
will always evaluate to false.
It is equivalent to
if ( (JAN >= month ) >= DEC )
So the sub-expression (JAN >= month ) evaluates either to 0 or 1 that in any case is less than DEC.
It seems you mean
if ( month < JAN || month > DEC )
In this condition
while (MIN_YEAR <= year <= MAX_YEAR , JAN <= month <= DEC)
there is used the comma operator. Its value is the values of the second operand JAN <= month <= DEC. That is as the first operand has no side effect then in fact the first operand MIN_YEAR <= year <= MAX_YEAR is ignored and does not influence on the result.
It seems you mean
while ( year < MIN_YEAR || year > MAX_YEAR || month < JAN || month > DEC)
Also there is another logical error
if ( ... )
{
printf("ERROR: The year must be between 2012 and 2022 inclusive");
}
if ( ... )
{
printf("ERROR: Jan.(1) - Dec.(12)");
}
else
{
printf("*** Log date set! ***");
}
The else statements belongs to the second if statement. So even if the year was entered incorrectly but the month was specified correctly then the else statement gets the control.
You should write for example
if ( ... )
{
printf("ERROR: The year must be between 2012 and 2022 inclusive");
}
else if ( ... )
{
printf("ERROR: Jan.(1) - Dec.(12)");
}
else
{
printf("*** Log date set! ***");
}
Related
So I created a program where you have to enter a date dd/mm/yyyy and then you get date.day + 1 , but I wan't to verify that the date entered is valid, that is date.day between 1 and 31, month between 1 and 12 and year between 1 and 9999, and that day entered is less than the number of days of that month, if one of these fails return exit failure
`// Program to determine tomorrow's date
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
struct date
{
int day;
int month;
int year;
};
int main(void)
{
struct date today, nextDay;
bool isValidDate(struct date VarName);
struct date dateUpdate(struct date today);
printf("Enter today's date (dd mm yyyy): ");
scanf("%i %i %i", &today.day, &today.month, &today.year);
if (isValidDate(today) == false)
{
printf("Invalid date format. \n");
exit(EXIT_FAILURE);
}
nextDay = dateUpdate(today);
printf("Tomorrow's date is: %i/%i/%i \n", nextDay.day,
nextDay.month,
nextDay.year % 100);
return 0;
}
// Function to update today's date to tomorrow's date
struct date dateUpdate(struct date today)
{
struct date tomorrow;
int numberOfDays(struct date VarName);
if (today.day != numberOfDays(today)) // End of day
{
tomorrow.day = today.day + 1;
tomorrow.month = today.month;
tomorrow.year = today.year;
}
else if (today.month == 12) // End of year
{
tomorrow.day = 1;
tomorrow.month = 1;
tomorrow.year = today.year + 1;
}
else // End of month
{
tomorrow.day = 1;
tomorrow.month = today.month + 1;
tomorrow.year = today.year;
}
return tomorrow;
}
// Function to find the numbers of days in a month
int numberOfDays(struct date VarName)
{
const int daysPerMonth[13] = {0, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
int days;
bool isLeapYear(struct date VarName);
bool isValidDate(struct date VarName);
if (isLeapYear(VarName) == true && VarName.month == 2)
{
days = 29;
}
else
{
days = daysPerMonth[VarName.month];
}
return days;
}
// Function to determine if a year is a leap year
bool isLeapYear(struct date VarName)
{
bool leapYearFlag;
if ((VarName.year % 4 == 0 && VarName.year % 100 != 0) ||
VarName.year % 400 == 0)
{
leapYearFlag = true; // It's a leap year
}
else
{
leapYearFlag = false; // Not a leap year
}
return leapYearFlag;
}
bool isValidDate(struct date VarName)
{
if ( (VarName.day < 1 && VarName.day > 31) || (VarName.day >
numberOfDays(VarName)) ) // Day format verifier
{
return false;
}
else if (VarName.month < 1 && VarName.month > 12)
// Month format verifier
{
return false;
}
else if (VarName.year < 1 && VarName.year > 9999)
// Year format verifier
{
return false;
}
else
{
return true;
}
}`
TEST A
Enter today's date (dd mm yyyy): 31 13 2018
RESULT
prog_8.4.c:78:16: runtime error: index 13 out of bounds for type 'const int [13]'
Invalid date format.
TEST B
Enter today's date (dd mm yyyy): 31 2 2018
RESULT
Invalid date format.
TEST C
Enter today's date (dd mm yyyy): 31 12 2018
RESULT
Tomorrow's date is: 1/1/19
if you notice, if there's a month that's greater than 13 I get a runtime error, which I don't want to get, I wan't to get the same message as test B where the day entered is greater than the days of that month, if I have my format verifier before the DateUpdate function why does the compiler runs the DateUpdate function, because I think that A error is related to this function, but if my error verifier worked correctly the program wouldn't run this function because it would terminate before it gets there, at least that's what I think, can you help me out here please?
I guess the problem lies in here:
if ( (VarName.day < 1 && VarName.day > 31) || (VarName.day >
numberOfDays(VarName)) ) // Day format verifier
As you see in the below, there is no index for 13 in const in daysPerMonth[13]. You only have index from 0 to 12, and in function bool isValidDate(), you put the Varname without checking whether the index is between 1 to 12.
Checking the index before putting Varname inside numberOfDays() will fix your problem.
I've got an issue which I can't find a solution. Or at least a "good" one.
I want to find the last day of the month given a month and a year in C.
For example :
last_day(10, 2017) > 31
last_day(02, 2017) > 28
last_day(02, 2016) > 29
last_day(01, 2017) > 31
last_day(12, 2010) > 31
last_day(X, Y) > X is the month, Y the year
Here is my idea: Get the day on the month X + 1, of year Y. Remove 1 day from this date.
I would like to know if there is a better solution than that, since that will a make "lot" of operation for a "simple" thing.
Thanks.
Edit : https://ideone.com/sIISO1
#include <stdio.h>
#include <time.h>
#include <string.h>
int main(void) {
struct tm tm;
char out[256];
memset(&tm, 0, sizeof(struct tm));
tm.tm_mon = 1;
tm.tm_mday = 0;
strftime(out, 256, "%d-%m-%Y", &tm);
printf("%s", out);
return 0;
}
I've tested by using struct tm, and day = 0, in order to get the previous day but did not work
Ask point out in the commentary, I've complexify the problem way to much.
I have been inspired by what #Agnishom Chattopadhyay said in comment, which is get the date from a lookup table.
But I did make a function which did that
#include <stdio.h>
int days_in_month(int month, int year) {
if ( year < 1582 ) return 0; /* Before this year the Gregorian Calendar was not define */
if ( month > 12 || month < 1 ) return 0;
if (month == 4 || month == 6 || month == 9 || month == 11) return 30;
else if (month == 2) return (((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 29 : 28);
return 31;
}
int main() {
printf("%d\n", days_in_month(10, 2017));
printf("%d\n", days_in_month(2, 2000));
printf("%d\n", days_in_month(2, 1300)); // Does not work !
printf("%d\n", days_in_month(2, 2018));
printf("%d\n", days_in_month(2, 2016));
}
https://ideone.com/5OZ3pZ
I have a little problem with my code. I need to check if user's given date is valid or not. I want to check it using 2 rules:
1. Date is valid date and found in a calendar (for example 29.2.2015 is invalid because there's only 28 days in February 2015) 2. Day and month can only be max 2 numbers (for example day 10 and 02 are valid but 010 and 002 are not). All help is appreciated!
This is my code this far:
void dateValidator(const char *date1) {
struct tm date = {0};
int day1;
int month1;
int year1;
int vday;
int vmonth;
int vyear;
sscanf(date1, "%3d.%3d.%d",&day1,&month1,&year1);
/**How do I check that if sscanf reads more than 2 characters on month and day, date is
invalid?**/
date.tm_year = year1 - 1900;
date.tm_mon = month1 - 1;
date.tm_mday = day1;
date.tm_isdst = -1;
vday = date.tm_mday;
vmonth = date.tm_mon;
vyear = date.tm_year;
mktime(&pvm);
if ((vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
/**This doesnt seem to work**/
printf("Invalid date");
}
}
I have deleted my previous answer and posting another one. Actually your code is fine, You just have to send the correct parameter to mktime and to check its return value. I.e. change:
mktime(&pvm);
if ((vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
/**This doesnt seem to work**/
printf("Invalid date");
}
to something like:
r = mktime(&date);
if (r == -1 || (vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
printf("Invalid date");
}
and declare the variable r as time_t r;.
int IsValidDate(int year, int month, int day)
{
unsigned int leap;
unsigned char mon_day[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
/* check the rang of the year */
if ((year < 1) || (year >= 3200))
{
return 0;
}
if ((month < 1) || (month > 12))
{
return 0;
}
/* if it's leep year */
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
{
leap = 1;
}
else
{
leap = 0;
}
mon_day[1] += leap;
if ((day > mon_day[month - 1]) || (day < 1))
{
return 0;
}
return 1;
}
For ruler 1, I have wrote this code for check the date before.
And I hope this code can help you.
The ruler 2 can easily checked, you can check it by format the valid date and compare it with the input string.
How do I check that if sscanf reads more than 2 characters on month and day, date is invalid?
Day and month can only be max 2 numbers digits (for example day 10 and 02 are valid but 010 and 002 are not).
An easy check: Record the offset at the end of the scan and tests 1) that it is not the original 0 (scanning got that far) and 2) this is the end of the string so as to detect extra junk in data1[]. Change 3d to 2d.
int n = 0;
sscanf(date1, "%2d.%2d.%d %n",&day1,&month1,&year1, &n);
if (n > 0 && data1[n] == '\0') Success();
else Fail();
Pedantic code would check with "%[]" to disallow leading spaces and '+'.
int n = 0;
sscanf(date1, "%*2[0-9].%*2[0-9].%*4[0-9] %n", &n);
if (n == 0 || data1[n]) Fail();
else {
sscanf(date1, "%2d.%2d.%d",&day1,&month1,&year1);
...
How to check if date is valid using mktime?
#Marian posted a good solution which adds a test of the return value of mktime().
if (-1 == mktime(&data)) Fail();
if (vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year) Fail();
I am writing a program that involves checking the validity of a date. I have set the conditions for the months which have 31 days in them, and I have set the conditions for the months which have 30 days in them. I left out February because there are issues with leap year.
When I run the program, it is able to print "SUCCESS" on the screen for all valid dates. However, when I try to enter an invalid date, the program fails to write "FAILURE" on the screen, as I have it set to do [at least I believe].
What is wrong with the code here?
#include <stdio.h>
int main ()
{
int month = 1;
int day = 32;
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8
|| month == 10 || month == 12)
{
if (0 < day && day < 32)
{
return printf("%s","SUCCESS");
}
}
else if (month == 4 || month == 6 || month == 9 || month == 11)
{
if (0 < day && day < 31 )
{
return printf("%s","SUCCESS");
}
}
else
{
return printf("%s","FAILURE");
}
return 1;
}
Your code have a wrong flow and #JoshStir is right about it.
I may know when you enter in a conditional statement, the other conditionals in the same level are ignored.
You test guide your code to enter in your first condicional.
int month = 1;
int day = 32;
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8
|| month == 10 || month == 12)
{
//--> Flow pass through here ( cause month == 1 )
if (0 < day && day < 32)
{
//Flow DON'T pass through here ( cause day == 32)
return printf("%s","SUCCESS");
}
}
else if (month == 4 || month == 6 || month == 9 || month == 11)
{
//--> Flow DON'T pass through here ( cause flow ENTERER FIRST IF STATEMENT BEFORE)
if (0 < day && day < 31 )
{
return printf("%s","SUCCESS");
}
}
else
{
//--> Flow DON'T pass through here ( cause flow ENTERED FIRST IF STATEMENT BEFORE)
return printf("%s","FAILURE");
}
I advice you to review your code.
Try rethink and considerate what did #JoshStir advice you too.
Maybe using months and days in same comparation operation a good idea.
We were all new once, so I'll try to answer your question as clearly as I can. Given your test data:
int month = 1;
int day = 32;
your code will enter the first if statement (as month == 1)
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8
|| month == 10 || month == 12)
It will then check against the inner if statement (is day > 0 and < 32?)
if (0 < day && day < 32)
day == 32, so it will not enter the if and print "SUCCESS", it will exit the if and then exit the application. If you want the data above to enter the failure condition, you would want something somewhat like the following:
if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8|| month == 10 || month == 12) && (day > 0 && day < 32))
I'm trying to get this validation for a date entered, from Jan 01 1901 to Dec 31 2299, if the date is out of range, give a error message, this is my code, some how it doesn't validate correctly, am I doing something wrong
int main (void)
{
// insert code here...
int day,month,year;
printf("Enter Year, Month and Day as YYYY,MM,DD\n");
scanf("4%d 2%d 2%d", &year, &month, &day);
if (year>1900 && year <2300) {
if (month>=1 && month <=12)
if (day >=1 && day <=31)
printf("correct/n");
else
printf("invalid/n");
}
return 0;
}
The problem is that you're using nested if statements, but you don't have enough else statements. If you simply consolidate the statements it should work.
if (year > 1900 && year < 2300 &&
month > 0 && month < 13 &&
day > 0 && day < 32)
{
printf("correct\n");
}
else
{
printf("invalid\n");
}
If I were doing this, I think I'd start with a small function like:
int in_range(int val, int lower, int upper) {
return val >= lower && val <= upper;
}
Then I'd write something like:
if (in_range(year, 1901, 2299) && in_range(month, 1, 12) && in_range(day, 1, 31))
printf("Corrent\n");
else
printf("invalid\n";
You don't say anything for a number of conditions. Fix:
if (year>1900 && year <2300) {
if (month>=1 && month <=12) {
if (day >=1 && day <=31)
printf("correct/n");
else
printf("invalid/n");
} else {
printf("invalid/n");
} else {
printf("invalid/n");
}
Of course, you could collapse that code to avoid redundancies.
if ( year > 1900 && year < 2300
&& month >= 1 && month <= 12
&& day >= 1 && day <= 31
) {
printf("correct/n");
} else {
printf("invalid/n");
}
I'd move that logic into a function.
int is_valid_date(int year, int month, int day) {
return ( year > 1900 && year < 2300
&& month >= 1 && month <= 12
&& day >= 1 && day <= 31
);
}
if (is_valid_date(year, month, day)){
printf("correct/n");
} else {
printf("invalid/n");
}