Reputation: 1
I´m Working on a program for a class and this is what I have so far. My buddy helped me with the function but when a wrong date is entered it should iterate until a correct date is asked. Not sure what to do we have been working on it for a few hours right now and since we are both new to C, we need some outside help.
#include <stdio.h> //for input output
#include <stdlib.h>
#include <string.h> // for string functions
#include <time.h> //for time functions
#include <stdbool.h> //bool functions for true/false
//used typedef for convenience, no need to type struct all the time
typedef struct
{
int m, d, y;
} Data_t;
int checkDate (int m, int d, int y); //declare function to check input
void modDate (Data_t * data); //declare function to modify date
int
main ()
{
int x = 0; //kill switch for while loop
//declare a struct variable and initialize it for the date
Data_t uDate = { 0, 0, 0 };
/* program has infinite loop bug when using the while loop with x */
while (x == 0){
printf ("x before input: %d\n", x); //debug printer
// Ask user for date input
printf ("Enter a date in mm/dd/yyyy format: ");
//Pass the input to the uDate struct with scanf
scanf ("%d/%d/%d", &uDate.m, &uDate.d, &uDate.y);
// check data if valid and set x
x = checkDate (uDate.m, uDate.d, uDate.y);
printf ("x after check: %d\n", x); //debug printer
}
// end of while loop
// Display the entered date & modifier message
printf ("\nDate Entered: %d/%d/%d\n", uDate.m, uDate.d, uDate.y);
printf ("Adding 1 week to entered date...\n");
modDate (&uDate); //pass the address of uDate to the modDate function
/* since it was passed through a pointer (by reference),
the original uDate struct is now modified */
// Display the modified date
printf ("New Date is: %d/%d/%d\n", uDate.m, uDate.d, uDate.y);
return 0;
}
//Define the checkDate function
int
checkDate (int m, int d, int y)
{
// This is sloppy. Clean it up with multiple functions later
if (y <= 0)
{
printf ("Invalid Date, Please try again.\n");
return false;
}
if (m >= 1 && m <= 12)
{
//Then check the days against the months & leap years
if ((d >= 1 && d <= 31)
&& (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10
|| m == 12))
{
return true;
}
else if ((d >= 1 && d <= 30) && (m == 4 || m == 6 || m == 9 || m == 11))
{
return true;
}
else if ((d >= 1 && d <= 28) && (m == 2))
{
return true;
}
else if (d == 29 && m == 2
&& (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)))
{
return true;
}
else
{
printf ("Invalid Date, Please try again.\n");
return false;
}
}
else
{
printf ("Invalid Date, Please try again.\n");
return false;
}
}
//Define the modDate function to add 7 days
void
modDate (Data_t * data)
{
data->d = data->d + 7; // modify the day element in struct
// initialize the time_t structs from time.h and pass elements
struct tm t = {.tm_mon = data->m - 1,.tm_mday = data->d,
.tm_year = data->y - 1900
};
/* month+/-1 is because tm struct stores january as 0 and december as 11
year+/- 1900 is because year values are calculated starting from
the year 1900. So when calculating with mktime() you need to get
the integer value of the year by y-1900. And to properly display
the year value that is returned, you add 1900 as done below */
mktime (&t); // call mktime() to calculate the new date
// pass new values into struct and reformat month & year
data->m = t.tm_mon + 1;
data->d = t.tm_mday;
data->y = t.tm_year + 1900;
}
Upvotes: 0
Views: 76
Reputation: 1263
Your problem is that wrong input for scanf is not properly handled.
If you enter something like "A"
, scanf ("%d/%d/%d", &uDate.m, &uDate.d, &uDate.y);
won't be successful because it could not read any int
that was expected.
Because your "A"
is not properly processed it remains in your input buffer what will cause scanf
to fail again and again.
So first you should check if all 3 expected values are read:
if (scanf ("%d/%d/%d", &uDate.m, &uDate.d, &uDate.y) != 3)
// x remains 0
printf("Invalid input format!\n");
else
x = checkDate (uDate.m, uDate.d, uDate.y);
This alone would not be enough because the wrong input still remains in your input buffer. So you need to flush it before you are making the next try:
Edit
As @AndrewHenle pointed out you should avoid using fflush(stdin)
(at least if you are not on a windows platform and want to keep your code portable).
So another solution is to read every input including newline character after user input with e.g. while((getchar()) != '\n');
if (scanf ("%d/%d/%d", &uDate.m, &uDate.d, &uDate.y) != 3)
// x remains 0
printf("Invalid input format!\n");
else
x = checkDate (uDate.m, uDate.d, uDate.y);
// flush input buffer
while((getchar()) != '\n');
Upvotes: 1
Reputation: 9422
You have declared return type of int checkDate (int m, int d, int y);
as int
but return a bool
. When correcting this to bool checkDate (int m, int d, int y);
the code seems to work:
#include <stdio.h> //for input output
#include <stdlib.h>
#include <string.h> // for string functions
#include <time.h> //for time functions
#include <stdbool.h> //bool functions for true/false
//used typedef for convenience, no need to type struct all the time
typedef struct
{
int m, d, y;
} Data_t;
bool checkDate (int m, int d, int y); //declare function to check input
void modDate (Data_t * data); //declare function to modify date
int
main ()
{
bool x = false; //kill switch for while loop
//declare a struct variable and initialize it for the date
Data_t uDate = { 0, 0, 0 };
/* program has infinite loop bug when using the while loop with x */
while (x == false){
printf ("x before input: %d\n", x); //debug printer
// Ask user for date input
printf ("Enter a date in mm/dd/yyyy format: ");
//Pass the input to the uDate struct with scanf
scanf ("%d/%d/%d", &uDate.m, &uDate.d, &uDate.y);
// check data if valid and set x
x = checkDate (uDate.m, uDate.d, uDate.y);
printf ("x after check: %d\n", x); //debug printer
}
// end of while loop
// Display the entered date & modifier message
printf ("\nDate Entered: %d/%d/%d\n", uDate.m, uDate.d, uDate.y);
printf ("Adding 1 week to entered date...\n");
modDate (&uDate); //pass the address of uDate to the modDate function
/* since it was passed through a pointer (by reference),
the original uDate struct is now modified */
// Display the modified date
printf ("New Date is: %d/%d/%d\n", uDate.m, uDate.d, uDate.y);
return 0;
}
//Define the checkDate function
bool
checkDate (int m, int d, int y)
{
// This is sloppy. Clean it up with multiple functions later
if (y <= 0)
{
printf ("Invalid Date, Please try again.\n");
return false;
}
if (m >= 1 && m <= 12)
{
//Then check the days against the months & leap years
if ((d >= 1 && d <= 31)
&& (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10
|| m == 12))
{
return true;
}
else if ((d >= 1 && d <= 30) && (m == 4 || m == 6 || m == 9 || m == 11))
{
return true;
}
else if ((d >= 1 && d <= 28) && (m == 2))
{
return true;
}
else if (d == 29 && m == 2
&& (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)))
{
return true;
}
else
{
printf ("Invalid Date, Please try again.\n");
return false;
}
}
else
{
printf ("Invalid Date, Please try again.\n");
return false;
}
}
//Define the modDate function to add 7 days
void
modDate (Data_t * data)
{
data->d = data->d + 7; // modify the day element in struct
// initialize the time_t structs from time.h and pass elements
struct tm t = {.tm_mon = data->m - 1,.tm_mday = data->d,
.tm_year = data->y - 1900
};
/* month+/-1 is because tm struct stores january as 0 and december as 11
year+/- 1900 is because year values are calculated starting from
the year 1900. So when calculating with mktime() you need to get
the integer value of the year by y-1900. And to properly display
the year value that is returned, you add 1900 as done below */
mktime (&t); // call mktime() to calculate the new date
// pass new values into struct and reformat month & year
data->m = t.tm_mon + 1;
data->d = t.tm_mday;
data->y = t.tm_year + 1900;
}
Upvotes: 0