Solved

Using time.h

Posted on 2006-07-15
3
258 Views
Last Modified: 2010-04-15
Hi there, I mentioned before that I'm doing a C course online & Im having  a problem with one of the exercises.

What the exercise is, is to take 2 dates and work out the difference.  The fuction follows:

void ageCalculator()
      {
      //Start with the date of birth
      char birth_Date[11];
      char test_Date[11];

      printf("Age Calculator\n");
      printf("Date of Birth = ");
      scanf("%s", birth_Date);

      printf("\nTest Date = ");
      scanf("%s", test_Date);


      struct tm *dob,*td;
      time_t now;//date_of_birth, test_date;

      //Initialize time structures
      now = time(NULL);
      dob = localtime(&now);
      td = localtime(&now);
      
      char p[3];
      int day = atoi(birth_Date);

      dob->tm_mday = day;

      char *sub_string;

      //Use strtok to look for the '/' delmiter
      printf("%s\n\n", strtok(birth_Date,"/"));
      
      //Loop through the remaining date string for month & year
      //and assign to the time structure.
      //If the token is greter than 2 digits long its the year
      while ((sub_string = strtok(NULL, "/")) != NULL)
            {
            if(strlen(sub_string) > 2)
                  {
                  int year = atoi(sub_string);
                  dob->tm_year = year;
                  }
            else
                  {
                  int month = atoi(sub_string);
                  dob->tm_mon = month;
                  }
            }

      //Populate the test date structure
      char q[3];
      int day2 = atoi(test_Date);

      td->tm_mday = day2;

      char *sub_string2;

      //Use strtok to look for the '/' delimiter
      printf("%s\n\n", strtok(test_Date,"/"));
      
      //Loop through the remaining date string for month & year
      //and assign to the time structure.
      //If the token is greater than 2 digits long its the year
      while ((sub_string2 = strtok(NULL, "/")) != NULL)
            {
            if(strlen(sub_string2) > 2)
                  {
                  int year = atoi(sub_string2);
                  td->tm_year = year;
                  }
            else
                  {
                  int month = atoi(sub_string2);
                  td->tm_mon = month;
                  }
            }


      time_t y = mktime(dob);
      if (y == -1)
                  {
                  printf("BUGGER");
                  }

      }



Now, I get all the bits of the date properly ie  day month, & assign them to the time struct dob....

But the output I get is still "Bugger" meaning the time y hasnt been initialized properly.

Any ideas?
Thanks
0
Comment
Question by:Benjamin_Barrett
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 53

Accepted Solution

by:
Infinity08 earned 500 total points
ID: 17115723
There are 2 problems with your code :

1) the tm_year part of a tm struct should be the number of years since 1900, and tm_mon starts counting from 0 (ie. january is 0)

2) you do two localtime's in a row this way :

       dob = localtime(&now);
       td = localtime(&now);

    The result is that dob and td point to the same memory block !! (the pointer returned is pointing to a statically allocated tm structure, and is overwritten on each call of gmtime, localtime and ctime). For more information, check this reference page :

http://www.cplusplus.com/ref/ctime/localtime.html


To fix 1), just adjust the values read in with scanf :

    dob->tm_year = year - 1900;
    dob->tm_mon = month - 1;

To fix 2) don't use a pointer returned by localtime(), but do it this way :

    struct tm dob, td;

and acces them like this :

    dob.tm_year

etc.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 17115764
A few more tips to clean up your code :

1) re-use your local (temporary) variables, or better, don't use an extra variable when you don't need one. A good example of this is that you use integers day and day2, while you could have just used one, day for example. A better solution would be that you drop the extra variable completely, ie. :

       int day = atoi(birth_Date);
       dob->tm_mday = day;

    becomes :

       dob->tm_mday = atoi(birth_Date);

    Check the rest of the code for similar optimisations yourself ...

2) I suppose that :

       char p[3];

    and :

       char q[3];

    are leftovers from previous code ? They're not used any more, so you can leave them out.

3) This :

       scanf("%s", birth_Date);

    is very dangerous for buffer overflows : if a user enters a string longer than 10 characters, the memory just after the character array birth_Date will be overwritten !! Limit the number of characters a user can input, by either using :

       scanf("%10s", birth_Date)

    or :

       fgets(birth_Date, 11, stdin);

4) your code now allows this date format :

       dd/yyyy/mm

    or even :

       dddddd/yyy/mm

    or :

       dd//

    The first is a design choice ... if you want the year to be in the second place too, then that's ok.
    The second is a bit more dangerous, as the day can be bigger than 31, and the year smaller than 1900. Both will result in an invalid tm structure.
    The fourth will set month and year to 0 ...

    An elegant way of extracting data from a string is this :

       int day, month, year;
       char dat[11] = "01/02/2003";
       sscanf(dat, "%02d/%02d/%04d", &day, &month, &year);
       fprintf(stdout, "%d %d %d\n", day, month, year);

    Don't forget to check the return value of sscanf() !!
0
 

Author Comment

by:Benjamin_Barrett
ID: 17115787
Cool, thanks heap Infinity. Especially for the coding tips. Im new to C & programming in general, so that stuff is gold to me

Benjamin
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question