Link to home
Start Free TrialLog in
Avatar of shaolinfunk
shaolinfunkFlag for United States of America

asked on

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

Avatar of shaolinfunk
shaolinfunk
Flag of United States of America image

ASKER

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?
Avatar of phoffric
phoffric

>> 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.
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?
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

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

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
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?
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/




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...

https://www.experts-exchange.com/questions/25651416/How-do-I-count-backwards-in-days-on-the-calendar.html

Once I get past whatever error is being generated, I can compile and move forward with this thread...
I can now get onto a machine with a compiler. Be back soon.
OK, I have a computer now. The
     using namespace std;
statement should have fixed your compilation errors, right?
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

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

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.
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?
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.
ASKER CERTIFIED SOLUTION
Avatar of phoffric
phoffric

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ohhhh, now i get it!  thanks!  this process is really helping me.  EE is awesome.  what a great learning tool.
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

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!
Ok, catch up with you later tonight hopefully.  I can't stop until I finish this thing!  It's becoming all-consuming.