JohnnyJedial
JohnnyJedial

Reputation: 55

Date comparison program

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;
}

Upvotes: 0

Views: 158

Answers (6)

Aki Suihkonen
Aki Suihkonen

Reputation: 20027

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.

Upvotes: 1

lu5er
lu5er

Reputation: 3564

Some errors in your code include:

  1. if (fyear < year): Say previously I got fyear = 2015, now I scan year = 2012. Is 2015 < 2012 ? So, the conditions will be reversed, right?
  2. 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.
  3. Lastly, if you scan 0/0/0, and say our present fyear = 2012 and year = 0. So, fyear > year2012 > 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.
  4. (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;
}

Upvotes: 1

Win Key
Win Key

Reputation: 49

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;
}

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84561

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.

Upvotes: 2

CRoemheld
CRoemheld

Reputation: 949

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.

Upvotes: 0

yuchuan
yuchuan

Reputation: 26

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.

Upvotes: 0

Related Questions