Solved

# Using time.h

Posted on 2006-07-15
254 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
Question by:Benjamin_Barrett
• 2
3 Comments

LVL 53

Accepted Solution

Infinity08 earned 500 total points
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

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

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

## Join & Write a Comment Already a member? Login.

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

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

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

#### Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!