Thread: Problem with ctime

  1. #1
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827

    Problem with ctime

    Hello all.
    I am having a problem with the ctime() function defined in the header included by #include <ctime>.

    The function is supposed to return a string in the format:

    Www Mmm dd hh:mm:ss yyyy

    Where Www is the weekday, Mmm the month in letters, dd the day of the month, hh:mm:ss the time, and yyyy the year.

    There should only be one space between each thing. I just encountered a situation where the returned string had two spaces after the month, which breaks my properlyFormatDateAndTime() function's algorithm which depends on the above format. The string returned by the ctime function just a couple of minutes ago, looks like this:

    Code:
    Wed Mar  2 10:59:10 2011
    As you can see, there are two spaces after the month, instead of just one. I don't know why that is, but just thought I'd go ahead and post about it before the behavior went away (seeing as it doesn't do that all the time, as I just ran my program which has the properlyFormatDateAndTime() function the other day, and it worked fine, and as expected, then).

    EDIT: Ok, this is even weirder. The above is what I thought was happening, but actually this is what the ctime function is returning:

    Code:
    ' Wed Mar  2 11:12:33 2011
    I was reporting the output of a C++ string before that had the content of the C-style string returned by ctime assigned to it (because I assumed the content would be the same), but then I decided to check the content of the actual C-style string, and the above is what it is returning now, and what the C++ string which gets the content of the C-style string returned by ctime contains is this:

    Code:
    Wed Mar  2 11:12:33 2011
    As you can see, the C++ string is missing the beginning hyphen and space that the original string contained for some reason.
    Last edited by Programmer_P; 03-02-2011 at 12:17 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    It's not two spaces after the month, it's the single digit day printed with a leading space.

    What code are you using?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Salem View Post
    It's not two spaces after the month, it's the single digit day printed with a leading space.

    What code are you using?
    Ahh..ok. But why does it put a leading space before the day?

    Here's my code (please ignore the debugging statements, most of which are commented out):

    Code:
    const char* properlyFormatDateAndTime(char* c_time) {
    
        const char* properly_formatted_c_time;
        string c_time_str = c_time;
        cout<< "c_time is: ' " << c_time <<endl;
        cin.get();
        cout<< "c_time_str is: " << c_time_str <<endl;
        cin.get();
        string day_of_the_week = c_time_str.substr(0, c_time_str.find(' ', 0));
        //cout<< "day_of_the_week is: " << day_of_the_week <<endl;
        //cin.get();
        c_time_str = c_time_str.substr(c_time_str.find(' ', 0) + 1);
        //cout<< "c_time_str is: " << c_time_str <<endl;
        //cin.get();
        string month = c_time_str.substr(0, c_time_str.find(' ', 0));
        //cout<< "month is: " << month <<endl;
        //cin.get();
        c_time_str = c_time_str.substr(c_time_str.find(' ', 0) + 1);
        //cout<< "c_time_str is: " << c_time_str <<endl;
        //cin.get();
        string date = c_time_str.substr(0, c_time_str.find(' ', 0));
        //cout<< "date is: " << date <<endl;
        //cin.get();
        c_time_str = c_time_str.substr(c_time_str.find(' ', 0) + 1);
        //cout<< "c_time_str is: " << c_time_str <<endl;
        //cin.get();
        string current_time = c_time_str.substr(0, c_time_str.find(' ', 0) + 1);
        //cout<< "current_time is: " << current_time <<endl;
        //cin.get();
        string hour = current_time.substr(0, current_time.find(':', 0));
        if (hour.at(0) == '0') {
           hour.erase(0, 1);
        }
        stringstream hour_ss;
        hour_ss<< hour;
        int hour_int;
        hour_ss>> hour_int;
        //cout<< "hour_int is: " << hour_int <<endl;
        //cin.get();
        string ampm = "AM";
        if (hour_int > 12) {
           ampm = "PM";
           if (hour_int == 13)
              hour_int = 1;
    
           else if (hour_int == 14)
              hour_int = 2;
    
           else if (hour_int == 15)
              hour_int = 3;
    
           else if (hour_int == 16)
              hour_int = 4;
    
           else if (hour_int == 17)
              hour_int = 5;
    
           else if (hour_int == 18)
              hour_int = 6;
    
           else if (hour_int == 19)
              hour_int = 7;
    
           else if (hour_int == 20)
              hour_int = 8;
    
           else if (hour_int == 21)
              hour_int = 9;
    
           else if (hour_int == 22)
              hour_int = 10;
    
           else if (hour_int == 23)
              hour_int = 11;
    
           else if (hour_int == 24) {
              hour_int = 12;
              ampm = "AM";
           }
    
        }
        //cout<< "hour_int is: " << hour_int <<endl;
        //cin.get();
        hour_ss.str("");
        hour_ss.clear();
        hour_ss<< hour_int;
        hour = hour_ss.str();
        //cout<< "hour is: " << hour <<endl;
        //cin.get();
        current_time = current_time.substr(current_time.find(':', 0) + 1);
        string minutes = current_time.substr(0, current_time.find(':', 0));
        //cout<< "minutes is: " << minutes <<endl;
        //cin.get();
        current_time = current_time.substr(current_time.find(':', 0) + 1);
        string seconds = current_time.substr(0, current_time.find(' ', 0));
        //cout<< "seconds is: " << seconds <<endl;
        //cin.get();
        string complete_time = hour + ":" + minutes + ":" + seconds + " " + ampm;
        //cout<< "complete_time is: " << complete_time <<endl;
        //cin.get();
        c_time_str = c_time_str.substr(c_time_str.find(' ', 0) + 1);
        //cout<< "c_time_str is: " << c_time_str <<endl;
        //cin.get();
        string year = c_time_str.substr(0, c_time_str.find('\n', 0));
        /*
        if (year.at(year.size() - 1) == '\n') {
           cout<< "year is followed by a new line." <<endl;
           cin.get();
        }
        */
        //cout<< "year is: " << year <<endl;
        //cin.get();
        string properly_formatted_c_time_str = complete_time + " - " + day_of_the_week + " " + month + " " + date + ", " + year;
        //cout<< "properly_formatted_c_time_str is: " << properly_formatted_c_time_str <<endl;
        //cin.get();
        properly_formatted_c_time = properly_formatted_c_time_str.c_str();
        //cout<< "properly_formatted_c_time is: " << properly_formatted_c_time <<endl;
        //cin.get();
    
        return properly_formatted_c_time;
    
    }
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Why not use strftime, and get the format you exactly want?
    man page strftime section 3
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I think it's very consistent with what happens when you print a single digit in a field two characters wide. sprintf wouldn't pad zeros on a number unless you told it to a la "%02d". I can't say ctime() or asctime() are implemented in such a way, I never looked. Anyway, using strftime() instead should solve your format issues. See strftime - C++ Reference.

  6. #6
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Salem View Post
    Why not use strftime, and get the format you exactly want?
    man page strftime section 3
    Quote Originally Posted by whiteflags View Post
    I think it's very consistent with what happens when you print a single digit in a field two characters wide. sprintf wouldn't pad zeros on a number unless you told it to a la "%02d". I can't say ctime() or asctime() are implemented in such a way, I never looked. Anyway, using strftime() instead should solve your format issues. See strftime - C++ Reference.
    Thanks guys.
    My properlyFormatDateAndTime() function definition now looks like this:

    Code:
    const char* properlyFormatDateAndTime(const struct tm* timeptr) {
    
        char properly_formatted_date_and_time[80];
        strftime(properly_formatted_date_and_time, 80, "%I:%M:%S - %A %B %d, %Y", timeptr);
        cout<< "Properly formatted date and time is: " << properly_formatted_date_and_time <<endl;
        cin.get();
        return properly_formatted_date_and_time;
    
    }
    Which formats it in roughly the way I want it to be, only I can't figure out how to get rid of the 0 in front of the hour if its < 10 and the 0 in front of day of the month if its < 10, when using strftime. Any advice on that?

    Thanks.

    EDIT: Nevermind...just realized what I need to do.

    EDIT again: Hmm...maybe not. I was able to remove the one for the hour, but I can't figure out how to remove the one for the date (or I mean I probably could, but I don't feel like working on this issue any longer right now ).

    Here is my new code:

    Code:
    const char* properlyFormatDateAndTime(const struct tm* timeptr) {
    
        char properly_formatted_date_and_time_non_const[80];
        strftime(properly_formatted_date_and_time_non_const, 80, "%I:%M:%S - %A %B %d, %Y", timeptr);
        string date_and_time_str = properly_formatted_date_and_time_non_const;
        string hour = date_and_time_str.substr(0, date_and_time_str.find(':', 0));
        //cout<< "hour is: " << hour <<endl;
        //cin.get();
        stringstream hour_ss;
        hour_ss<< hour;
        int hour_int;
        hour_ss>> hour_int;
        //cout<< "hour_int is: " << hour_int <<endl;
        //cin.get();
        if (hour_int < 10) {
           string new_hour = hour_ss.str();
           new_hour.erase(0, 1);
           //cout<< "new_hour.size() is: " << new_hour.size() <<endl;
           //cout<< "new_hour is: " << new_hour <<endl;
           date_and_time_str.replace(date_and_time_str.find(hour, 0), hour.size(), new_hour);
        }
        //cout<< "Date and time is: " << date_and_time_str <<endl;
        //cin.get();
        const char* properly_formatted_date_and_time = date_and_time_str.c_str();
        return properly_formatted_date_and_time;
    
    }
    Last edited by Programmer_P; 03-02-2011 at 06:54 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    How about using Boost's Date/Time library?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    const char* properlyFormatDateAndTime(const struct tm* timeptr) {
    
        char properly_formatted_date_and_time_non_const[80];
        strftime(properly_formatted_date_and_time_non_const, 80, "%I:%M:%S - %A %B %d, %Y", timeptr);
        string date_and_time_str = properly_formatted_date_and_time_non_const;
        string hour = date_and_time_str.substr(0, date_and_time_str.find(':', 0));
        //cout<< "hour is: " << hour <<endl;
        //cin.get();
        stringstream hour_ss;
        hour_ss<< hour;
        int hour_int;
        hour_ss>> hour_int;
        //cout<< "hour_int is: " << hour_int <<endl;
        //cin.get();
        if (hour_int < 10) {
           string new_hour = hour_ss.str();
           new_hour.erase(0, 1);
           //cout<< "new_hour.size() is: " << new_hour.size() <<endl;
           //cout<< "new_hour is: " << new_hour <<endl;
           date_and_time_str.replace(date_and_time_str.find(hour, 0), hour.size(), new_hour);
        }
        //cout<< "Date and time is: " << date_and_time_str <<endl;
        //cin.get();
        const char* properly_formatted_date_and_time = date_and_time_str.c_str();
        return properly_formatted_date_and_time;
    
    }
    You are returning a pointer to an internal area of memory managed by a local string object which is destructed after the function exits.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  9. #9
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    How about using Boost's Date/Time library?
    I'm trying to stay away from 3rd party libraries as much as possible, for right now.
    I want to get the standard C++ library down first.
    Quote Originally Posted by hk_mp5kpdw View Post
    Code:
    const char* properlyFormatDateAndTime(const struct tm* timeptr) {
    
        char properly_formatted_date_and_time_non_const[80];
        strftime(properly_formatted_date_and_time_non_const, 80, "%I:%M:%S - %A %B %d, %Y", timeptr);
        string date_and_time_str = properly_formatted_date_and_time_non_const;
        string hour = date_and_time_str.substr(0, date_and_time_str.find(':', 0));
        //cout<< "hour is: " << hour <<endl;
        //cin.get();
        stringstream hour_ss;
        hour_ss<< hour;
        int hour_int;
        hour_ss>> hour_int;
        //cout<< "hour_int is: " << hour_int <<endl;
        //cin.get();
        if (hour_int < 10) {
           string new_hour = hour_ss.str();
           new_hour.erase(0, 1);
           //cout<< "new_hour.size() is: " << new_hour.size() <<endl;
           //cout<< "new_hour is: " << new_hour <<endl;
           date_and_time_str.replace(date_and_time_str.find(hour, 0), hour.size(), new_hour);
        }
        //cout<< "Date and time is: " << date_and_time_str <<endl;
        //cin.get();
        const char* properly_formatted_date_and_time = date_and_time_str.c_str();
        return properly_formatted_date_and_time;
    
    }
    You are returning a pointer to an internal area of memory managed by a local string object which is destructed after the function exits.
    Maybe so, but it still works.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Programmer_P View Post
    I'm trying to stay away from 3rd party libraries as much as possible, for right now.
    I want to get the standard C++ library down first.
    Is learning the C standard library on your list too, especially when there is a C++ portable alternative available?

    Maybe so, but it still works.
    Geez. Do you not realize that you are running on undefined behavior?
    Just because it works, doesn't that it's right.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    Is learning the C standard library on your list too, especially when there is a C++ portable alternative available?
    Not really, as I'm not really interested in C, because I understand C++ is a step up from C which basically includes all of C's features anyway (though I'm sure someone will correct me on the "all" part I said).
    Geez. Do you not realize that you are running on undefined behavior?
    Haha, I knew that would get some responses.
    How so? I mean, if it works, how is it "undefined behavior"?
    Computers can only do what you tell it to do, so if my computer is outputting the time correctly from my program when I use the above function, then its behavior must obviously be defined somewhere.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Allow me to demonstrate why it's undefined behavior...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    Allow me to demonstrate why it's undefined behavior...
    Please do.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    #include <string>
    #include <iostream>
    
    const char* foo() 
    {
    	std::string s = "Hello World!\n";
    	std::cout << "foo: " << s;
    	return s.c_str();
    }
    
    int main()
    {
    	const char* s = foo();
    	std::cout << "main: " << s;
    }
    Output:
    foo: Hello World!
    main: Press any key to continue . . .

    Not what you expected?

    Quote Originally Posted by Programmer_P View Post
    Not really, as I'm not really interested in C, because I understand C++ is a step up from C which basically includes all of C's features anyway (though I'm sure someone will correct me on the "all" part I said).
    Right. So why bother with C functions where there is a better C++ alternative available?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    If you're only really interested in C++, then return a std::string rather than messing with char* pointers of various persuations.

    Only use char arrays for the very minimum of using legacy functions. As soon as you have your char array result, copy it to a std::string and use that in the rest of the code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM