How do I parse this string for the year, month, and day?

Ok, I have today's date in a character array.  

How do I parse it so that I can store the year, month, and day into variables "year", "month", and "day".

My code is attached.  Yes, I am learning.  Yes, I am only on Chapter 4 in my teach-yourself, self-help book.  And yes, I am not a computer programmer.  Thank you in advance for your help!
int main()
{
// Get TODAY's date in string form   
	
    time_t rawtime;
    struct tm * timeinfo;
    char str[60];

    time ( &rawtime );
    timeinfo = localtime ( &rawtime );

   strftime(str, sizeof(str) , "%d%b%Y", timeinfo);   
//   printf(str);                                                //lets me see if date is right
   

// Get YESTERDAY's date 	
   unsigned short year;
   unsigned short month;
   unsigned short day;

   year = 2010;
   month = 3;
   day = 31;

   one_Day_Earlier(year, month, day);

    return 0;
}

Open in new window

LVL 1
shaolinfunkAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

shaolinfunkAuthor Commented:
I want to get today's date, April 2nd, 2010 into those unsigned short variables.

So that year = 2010, month = 4, and day = 2.  How do I do this?
0
phoffricCommented:
>> I have today's date in a character array.
In your OP you have three representations of today's date:
12: char array
9: seconds since epoch
10: timeinfo, a pointer to struct tm whose values are filled in with your local time.
0
shaolinfunkAuthor Commented:
well I don't really understand or want to understand 9 or 10 yet (pointers?).  

12, a char array, is something i've covered in my book.  how do i extract from that char array the values needed for the unsigned shorts i've declared?
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

phoffricCommented:
The easiest way to store into variable year, month, day is to use the timeinfo pointer.
Here is what a struct tm looks like:
    http://www.cplusplus.com/reference/clibrary/ctime/tm/
Note in particular the unusual ranges for month and year!
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;  // you need this for the day of the month
int tm_mon;   // you need this for the month
int tm_year;  // you need this for the year
int tm_wday;
int tm_yday;
int tm_isdst;

Open in new window

0
phoffricCommented:
OK, scratch the struct tm details and the reference to pointers. You want the Month to be digits, right? So, modify the strftime as shown below to get a month number rather than, say, Apr. If you prefer, you can keep the Apr in the string, and then you can convert the month name into a number.

The whitespace between the fields will be used to separate the three strings when converting to a number.

Which way do you want to go: "Apr" or "04". The leading 0 is part of the strftime result; but that will not be a problem if you want the integer number 4.


strftime(str, sizeof(str), "%Y %m %d", timeinfo);

Open in new window

0
phoffricCommented:
Your layout of str is "YYYY MM DD"

To convert an ASCII representation of a number to an integer, you can use atoi.
    http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

But that requires a just a little bit of pointers. To get the year, it is as simple as saying
  year = atoi(str).
since str, an array name, is actually a constant pointer to the starting address of the array.

(BTW, I am not at a computer, so be sure to check code on your system.)

If you want to avoid atoi because it has a pointer in it, then you have to parse each field in str yourself and compute the integer.

For example, 2010: 0+1*10+0*100+2*1000
0
phoffricCommented:
Or, I can come up with C++ approach, but that would not be covered in Chapters 1-4 I don't think. What do you know about streams?
0
phoffricCommented:
To convert a single char that has an ASCII digit in it, you can use something like this:

char digit = '5'; // this is just setup code
int intDigit = digit - '0'; // this is how to convert a single char digit into an integer digit

Now, if you care about robustness, you might want to test to make sure that there really is an ASCII digit present. For that you can use isdigit.
       http://www.cplusplus.com/reference/clibrary/cctype/isdigit/




0
shaolinfunkAuthor Commented:
Hi Phoffric,

I want to continue this thread but got stuck because my program no longer compiles after I implemented the code from your previous thread...

http://www.experts-exchange.com/Programming/Languages/CPP/Q_25651416.html

Once I get past whatever error is being generated, I can compile and move forward with this thread...
0
phoffricCommented:
I can now get onto a machine with a compiler. Be back soon.
0
phoffricCommented:
OK, I have a computer now. The
     using namespace std;
statement should have fixed your compilation errors, right?
0
shaolinfunkAuthor Commented:
ah yes, that was it.  however, i do get some warnings regarding that 'sprintf' stuff you suggested.  what does it mean to be "declared deprecated"?
1>------ Build started: Project: junk, Configuration: Debug Win32 ------
1>Compiling...
1>Junk.cpp
1>c:\documents and settings\administrator\desktop\junk\junk\junk.cpp(41) : warning C4996: 'sprintf' was declared deprecated
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\stdio.h(345) : see declaration of 'sprintf'
1>        Message: 'This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
1>c:\documents and settings\administrator\desktop\junk\junk\junk.cpp(56) : warning C4996: 'localtime' was declared deprecated
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\time.inl(114) : see declaration of 'localtime'
1>        Message: 'This function or variable may be unsafe. Consider using localtime_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
1>Linking...
1>Embedding manifest...
1>Build log was saved at "file://c:\Documents and Settings\Administrator\Desktop\junk\junk\Debug\BuildLog.htm"
1>junk - 0 error(s), 2 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Open in new window

0
shaolinfunkAuthor Commented:
fyi, this is how my code looks when it generated those errors:
#include <time.h>
#include <stdio.h>
#include <string>

using namespace std;

string one_Day_Earlier(unsigned short year, unsigned short month, unsigned short day)
{

//months with 31 days: 1, 3, 5, 7, 8, 10, 12
//months with 30 days: 4, 6, 9, 11
//months with 28/29 days: 2
	day = day - 1; //decrement the day

    if (day == 0) //if day = 0, today must be 1st of the month
	{    
			if (month == 2 || month == 4 || month == 6 || month == 8 || month == 9 || month == 11 || month == 1)
			{
				day = 31;
			}

			if (month == 5 || month == 7 || month == 10 || month == 12)
			{
				day = 30;
			}
			if (month == 3)  //if not a leap year, who cares, just search, find nothing, skip, and decrement to 28
			{
				day = 29;
			}


			month = month - 1;
			if (month == 0)  //if this month is Jan, prior month will be Dec.
			{
				month = 12;  //if we are in Dec., we must be in prior year...so...
				year = year - 1; //we will never count back before year 2000, so it's always positive
			}
    }

   char buffer[40];
   sprintf( buffer, "%d\\\\%d\\\\%d", year, month, day);

   return string(buffer);
}


int main()
{
// Get TODAY's date in string form   
	
    time_t rawtime;  //rawtime is variable of data type time_t, related to time.h
    struct tm * timeinfo; //timeinfo points to a struct of type tm, related to time.h
    char str[60];

    rawtime = time (NULL); //retrieves number of seconds from 1/1/70, in GMT, stores in address of rawtime
    timeinfo = localtime ( &rawtime ); //localtime takes rawtime, and creates a "tm" struct

   strftime(str, sizeof(str) , "%Y %m %d", timeinfo);   
   printf(str);                                                //lets me see if date is right
   

// Get YESTERDAY's date 	
   unsigned short year;
   unsigned short month;
   unsigned short day;

   year = 2010;
   month = 3;
   day = 31;

//   newdate = one_Day_Earlier(year, month, day);

    return 0;
}

Open in new window

0
phoffricCommented:
Deprecated means that someday this function won't be supported; so they recommend that you stop using it. Sometimes the "unsafe" conditions pertains to multi-threading, which you currently are not involved with. The time.h header is pretty bad w.r.t. multi-threading. I had to use time.h and had to use semaphores to protect against threads clobbering each other w.r.t. time.

Search your other threads for how to put _CRT_SECURE_NO_DEPRECATE in your project to remove these warnings. I recall including directions in one of them.
0
shaolinfunkAuthor Commented:
i like using atoi...it's simple...and i get it. but using atoi(str) only gives us the year...how do i get the month and day as well?
0
shaolinfunkAuthor Commented:
yes, you did in fact tell me how to get rid of them...i am just leaving them in for now so that i can get a sense of what kind of warnings will be generated with the code.
0
phoffricCommented:
str:
0123456789
yyyy mm dd

so,

str[0] starts with yyyy
str[5] starts with mm
str[8] starts with dd

But atoi needs a pointer (i.e., an address). So you need the address of str[5], etc. Now to get the address of an entity, you need the "address of" operator, which is &

So you would have atoi( & str[5] ).

fyi - atoi( str ) returns the same result as atoi( &str[0] ) for reasons described elsewhere.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
shaolinfunkAuthor Commented:
ohhhh, now i get it!  thanks!  this process is really helping me.  EE is awesome.  what a great learning tool.
0
shaolinfunkAuthor Commented:
Ok here's my final code.  My gut tells me I should call a function from main that is called GetTodaysDate.  It would just look prettier and be easier to read.  

However, I don't know how I should be passing-by-value correctly.  

I get some warnings when compiling this.  What am I doing wrong?
#include <time.h>
#include <stdio.h>
#include <string>

using namespace std;

unsigned short GetTodaysDate(unsigned short year, unsigned short month, unsigned short day)
{
	time_t rawtime;  //rawtime is variable of data type time_t, related to time.h
    struct tm * timeinfo; //timeinfo points to a struct of type tm, related to time.h
    char str[60];

    rawtime = time (NULL); //retrieves number of seconds from 1/1/70, in GMT, stores in address of rawtime
    timeinfo = localtime ( &rawtime ); //localtime takes rawtime, and creates a "tm" struct

   strftime(str, sizeof(str) , "%Y %m %d", timeinfo);   
//   printf(str);                                                //lets me see if date is right
   
   year = atoi(&str[0]);
   month = atoi(&str[5]);
   day = atoi(&str[8]);

   return (year, month, day);
}


string one_Day_Earlier(unsigned short year, unsigned short month, unsigned short day)
{

//months with 31 days: 1, 3, 5, 7, 8, 10, 12
//months with 30 days: 4, 6, 9, 11
//months with 28/29 days: 2
	day = day - 1; //decrement the day

    if (day == 0) //if day = 0, today must be 1st of the month
	{    
			if (month == 2 || month == 4 || month == 6 || month == 8 || month == 9 || month == 11 || month == 1)
			{
				day = 31;
			}

			if (month == 5 || month == 7 || month == 10 || month == 12)
			{
				day = 30;
			}
			if (month == 3)  //if not a leap year, who cares, just search, find nothing, skip, and decrement to 28
			{
				day = 29;
			}


			month = month - 1;
			if (month == 0)  //if this month is Jan, prior month will be Dec.
			{
				month = 12;  //if we are in Dec., we must be in prior year...so...
				year = year - 1; //we will never count back before year 2000, so it's always positive
			}
    }

   char buffer[40];
   sprintf( buffer, "%d\\\\%d\\\\%d", year, month, day);

   return string(buffer);
}


int main()
{
// Get TODAY's date in string form   
   unsigned short year;
   unsigned short month;
   unsigned short day;

	GetTodaysDate (year, month, day);

   

// Get YESTERDAY's date 	
//   newdate = one_Day_Earlier(year, month, day);

    return 0;
}




1>Junk.cpp
1>c:\documents and settings\administrator\desktop\junk\junk\junk.cpp(74) : warning C4700: uninitialized local variable 'day' used
1>c:\documents and settings\administrator\desktop\junk\junk\junk.cpp(74) : warning C4700: uninitialized local variable 'month' used
1>c:\documents and settings\administrator\desktop\junk\junk\junk.cpp(74) : warning C4700: uninitialized local variable 'year' used
1>Linking...
1>Embedding manifest...
1>Build log was saved at "file://c:\Documents and Settings\Administrator\Desktop\junk\junk\Debug\BuildLog.htm"
1>junk - 0 error(s), 3 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Open in new window

0
phoffricCommented:
So, now you're a pointer Expert. Start helping others in the C or C++ zone. You help; and you will learn better.

I'll be back tonight. But if you want to start the integration phase, go right ahead. You may get fresh ideas that are simpler than what we have already done. At this point, be flexible in changing the profile of the function(s) you have. The main problem you face w/o using struct or pointer or reference is how to return multiple items from one function. I think you need to re-read chapter 4.

The shortcut easiest way, I think may be for you to use references. But now the the & has a different meaning. Since I'm leaving now, I suggest that you ask a related question from this question, and learn how to return multiple items.

I see that you just posted a new function. Good, go with your gut. One thing that may help the Expert is for you to add a function comment that explains what the input and output is. Good luck!
0
shaolinfunkAuthor Commented:
Ok, catch up with you later tonight hopefully.  I can't stop until I finish this thing!  It's becoming all-consuming.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.