Here are the files that I was given, I was told not to change either of the two. The specifications of the functions are in the header and the main.c is a shell to test the code:
date.h:
#ifndef _DateH_
#define _DateH_
typedef struct {
int month;
int day;
int year;
} date;
int is_leap_year(int the_year);
int days_in_month(int month,int leap_year);
// Recommendation: use switch statement
void input_date(date *dp); // User input of form mm/dd/yyyy
// where mm, dd and yyy are integers
// NO PROMPT JUST INPUT
void print_date(date d); // Output format same as input_date's input format
int day_of_year(date d); // Number of days since beginning of year
// January 1 is day 1 (not 0)
int compare_dates(date d1, date d2);
// Returns -1 if d1 earlier than d2, 0 if same date, +1 if d1 after d2
void check_age_and_birthday(date birthdate, date today);
// Output: "You are __ years old and this is your birthday\n"
// or "You are __ years old and this is not your birthday\n"
void submit_status(date start, date end, date submit);
// Prints ""Submission not accepted - too early\n" if submit < start;
// "Submission not accepted too - late\n" if end < submit;
// "Submission accepted\n" otherwise.
#endif
// Note: A year is a leap year if and only if it is divisible by 4
// and, if it is divisible by 100, it is also divisible by 400.
main.c:
#include "date.h"
#include <stdio.h>
int main()
{
date d,bdate,today,start,end,submit;
printf("Enter a date: ");
input_date(&d);
printf("\n");
print_date(d);
printf(" is day %d of year %d, which is ",day_of_year(d),d.year);
if (!is_leap_year(d.year))
printf("not ");
printf("a leap year\n\n");
printf("Enter your birthdate: ");
input_date(&bdate);
printf("Enter today's date: ");
input_date(&today);
printf("\n");
check_age_and_birthday(bdate,today);
printf("\nEnter the start date: ");
input_date(&start);
printf("Enter the end date: ");
input_date(&end);
printf("Enter the date submitted: ");
input_date(&submit);
printf("\n\n");
submit_status(start,end,submit);
return 0;
}
date.c:
#include "date.h"
int is_leap_year(int the_year)
{
if (the_year % 4 == 0) {
if (the_year % 100 == 0) {
if (the_year % 400 == 0) {
return (1);
}
else return (0);
}
else return (1);
}
else return (0);
}
int days_in_month(int month, int leap_year)
{
switch (month) {
case 1: {
return (31);
break;
}
case 2: {
if (leap_year) return (29);
else return (28);
break;
}
case 3: {
return (31);
break;
}
case 4: {
return (30);
break;
}
case 5: {
return (31);
break;
}
case 6: {
return (30);
break;
}
case 7: {
return (31);
break;
}
case 8: {
return (31);
break;
}
case 9: {
return (30);
break;
}
case 10: {
return (31);
break;
}
case 11: {
return (30);
break;
}
case 12: {
return (31);
break;
}
}
}
void input_date(date *dp)
{
do
{
scanf("%d/%d/%d", dp->month, dp->day, dp->year);
}
while
(dp->day > days_in_month(dp->month, is_leap_year(dp->year)) || dp->day < 1);
}
void print_date(date d)
{
printf("%d/%d/%d", d.month, d.day, d.year);
}
int day_of_year(date d)
{
int day_sum = 0;
int i;
if (is_leap_year(d.year))
{
for (i = 1; i < d.month; i++)
{
day_sum = day_sum + days_in_month(i, 1);
}
}
else
{
for (i = 1; i < d.month; i++)
{
day_sum += days_in_month(i, 0);
}
}
day_sum += d.day;
return (day_sum);
}
void check_age_and_birthday(date birthdate, date today)
{
int age;
if (today.month > birthdate.month)
{
age = today.year - birthdate.year;
}
if (today.month < birthdate.month)
{
age = (today.year - birthdate.year) - 1;
}
if (today.month == birthdate.month)
{
if ((today.day > birthdate.day) || (today.day == birthdate.day)) {
age = today.year - birthdate.year;
}
if (today.day < birthdate.day) {
age = (today.year - birthdate.year) - 1;
}
}
if (!compare_dates(birthdate, today))
{
printf ("You are %d years old and this is your birthday\n", age);
}
else
{
printf ("You are %d years old and this is not your birthday\n", age);
}
}
int compare_dates(date d1, date d2)
{
if (d1.year > d2.year)
{
return (1);
}
if (d1.year < d2.year)
{
return (-1);
}
if (d1.year == d2.year)
{
if (d1.month > d2.month)
{
return (1);
}
if (d1.month < d2.month)
{
return (-1);
}
if (d1.month == d2.month)
{
if (d1.day > d2.day)
{
return (1);
}
if (d1.day < d2.day)
{
return (-1);
}
if (d1.day == d2.day)
{
return (0);
}
}
}
}
void submit_status(date start, date end, date submit)
{
if (compare_dates(submit, start) == -1)
{
printf("Submission not accepted - too early\n");
}
if (compare_dates(submit, end) == 1)
{
printf("Submission not accepted - too late\n");
}
if ((compare_dates(submit, start) == 1) && (compare_dates(submit, end) == -1))
{
printf("Submission accepted\n");
}
}
When I put them into a ‘console application’ project and build it, I get the error:
[Linker error] undefined reference to `submit_status'
ld returned 1 exit status
[Build Error] [DateStruct.exe] Error 1
If I run them in separate tabs, with no project created I get:
mangled line number section.
[Linker error] undefined reference to `WinMain@16'
ld returned 1 exit status
I’m using Dev-C++ for this.
Your program is crashing when you enter a date because you are passing the value of
dp->month,dp->day, anddp->yeartoscanf().scanf()needs a pointer to store the result in; in C, and integer looks like a pointer, so it happily tries to interpret the unitialized value indp->monthas a pointer, and crashes because it can’t write there.You want to use
&dp->month, etc., instead.I would recommending compiling with all warnings enabled (I don’t know Dev-C++, but the GCC flags are
-Wall -Wextra); I also recommend treating warnings on errors, so you can’t accidentally ignore them, with-Werror. If I compile with warnings enabled, GCC tells me about the problem:This example error was also from a very quick test file that I wrote up. It really helps when debugging a problem, and asking questions if you’re stuck, if you try to create a short, self-contained example of the problem. The code you posted had a lot of extraneous bits; several header files, functions that you never actually get to, and so on. Stripping your code down into a minimal example of the problem can either help you find the problem yourself, or failing that, give an example that is much easier for other people to glance at and see the problem, without wading through a bunch of extra stuff.
Here’s a minimal example that demonstrates the problem:
And how to fix it: