Sscanf() Function - c++

What is the difference between using '&' with year and day as an arguments and doesn't use it with month and weekday in sscanf() function ?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int day, year;
char weekday[20], month[20], dtm[100];
strcpy( dtm, "Saturday March 25 1989" );
sscanf( dtm, "%s %s %d %d", weekday, month, &day, &year );
printf("%s %d, %d = %s\n", month, day, year, weekday );
return(0);
}

The & operator gets the address of a variable. So you're actually passing a pointer to day and year into sscanf.
Since they are arrays, weekday and month are already pointers to their first elements.
So rather than passing in different things to sscanf you're actually passing in the same things.
2 char*s and 2 int*s.

Related

Get System Date Format String Win32

I need to get the system current date format string like ("dd-mm-yyyy" , "mm/dd/yyyy" ect.
GetDateFormat() API returns the formatted string like "12-09-2015" but need string like "dd-mm-yyyy"
C# solution
string sysFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
But I need in Win32.
You can get a list of format strings currently applicable, by enumerating them. This is done through EnumDateFormats. Note, that there can be (and usually is) more than one, so you will have to decide, which one to pick1).
The following code returns the system's default short dateformat pattern:
static std::list<std::wstring> g_DateFormats;
BOOL CALLBACK EnumDateFormatsProc( _In_ LPWSTR lpDateFormatString ) {
// Store each format in the global list of dateformats.
g_DateFormats.push_back( lpDateFormatString );
return TRUE;
}
std::wstring GetShortDatePattern() {
if ( g_DateFormats.size() == 0 &&
// Enumerate all system default short dateformats; EnumDateFormatsProc is
// called for each dateformat.
!::EnumDateFormatsW( EnumDateFormatsProc,
LOCALE_SYSTEM_DEFAULT,
DATE_SHORTDATE ) ) {
throw std::runtime_error( "EnumDateFormatsW" );
}
// There can be more than one short date format. Arbitrarily pick the first one:
return g_DateFormats.front();
}
int main() {
const std::wstring strShortFormat = GetShortDatePattern();
return 0;
}
1) The .NET implementation does the same thing. From its list of candidates, it arbitrarily picks the first one.
You can use time function together with localtime function.
Example code:
//#include <time.h>
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
//The years are since 1900 according the documentation, so add 1900 to the actual year result.
char cDate[255] = {};
sprintf(cDate, "Today is: %d-%d-%d", timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year + 1900);

Attempting to convert a time_t data type to have (dd/mm/yyyy) format C++

My question is pretty much in the title. I have a function call with a parameter of type time_t, and I need to initialize a variable to today's date, month, and year, and send it via the argument. For example,
void WebCall(time_t TodaysDate)
Where TodaysDate is the populated variable with the format DD/MM/YYYY with the slashes included. Is this possible? I can't change the data type from time_t to SYSTEMTIME or anything else. This is coded in C++. Any Ideas?
If you mean time_t, you can format it using gmtime and strftime:
time_t TodaysDate= ...;
struct tm * ptm= gmtime(&time);
char buffer[80];
strftime(buffer, 80, "%d/%m/%Y", ptm);
time_t is "unix time" and is the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC. As MSN answered you can convert that to a date using gmtime, for most common purposes, UTC is synonymous with GMT. You didn't specify in the question but if you need the local date use localtime instead of gmtime. Here's a function that'll do that for you and return a std::string:
#include <time.h>
#include <string>
std::string time_to_local_date( time_t utc )
{
struct tm *now = localtime(&utc);
char buffer[80];
strftime(buffer, 80, "%d/%m/%Y", now);
return std::string(buffer);
}

Build string as in printf function

printf("%d.%d.%d", year, month, day);
Can I do the same but without printing, smth like
char* date = "%d.%d.%d", year, month, day;
Or maybe some other simple ways to do that?
In plain c there is asprintf() which will allocate memory to hold the resulting string:
#include <stdio.h>
char *date;
asprintf(&date, "%d.%d.%d", year, month, day);
(error handling omitted)
Since you have tagged C++ you probably want to use the C++ solutions.
In C++:
#include <string>
std::string date = std::to_string(year) + '.' +
std::to_string(month) + '.' + std::to_string(day);
If you need the underlying char const *, say date.c_str().
The function std::to_string uses snprintf internally; you should probably look up that function, too, as it is fairly fundamental to formatted output, and you can use it directly if you really think you need to.
There are various implementations of a format function that looks something like:
std::string format(const std::string& fmt, ...);
so your example would be:
std::string date = format("%d.%d.%d", year, month, day);
One possible implementation is shown below.
Boost has a format library that works a little differently. It assumes you like cin, cout, and their ilk:
cout << boost::format("%1%.%2%.%3%") % year % month % day;
Or, if you just wanted a string:
boost::format fmt("%1%.%2%.%3%");
fmt % year % month % day;
std::string date = fmt.str();
Note that % flags are not the ones you're used to.
Finally, if you want a C string (char*) instead of a C++ string, you could use the asprintf function:
char* date;
if(asprintf(&date, "%d.%d.%d", year, month, day) == -1)
{ /* couldn't make the string; format was bad or out of memory. */ }
You could even use vasprintf to make your own format function returning a C++ string:
std::string format(const char* fmt, ...)
{
char* result = 0;
va_list ap;
va_start(ap, fmt);
if(vasprintf(*result, fmt, ap) == -1)
throw std::bad_alloc();
va_end(ap);
std::string str_result(result);
free(result);
return str_result;
}
This isn't terribly efficient, but it works. There also might be a way to call vsnprintf twice, the first with no buffer to get the formatted string length, then allocate the string object with the right capacity, then call the second time to get the string. This avoids allocating the memory twice, but has to make two passes through the formatted string.
In C++ I wrote a function to create strings using the printf format.
Headerfile stringf.h:
#ifndef STRINGF_H
#define STRINGF_H
#include <string>
template< typename... argv >
std::string stringf( const char* format, argv... args ) {
const size_t SIZE = std::snprintf( NULL, 0, format, args... );
std::string output;
output.resize(SIZE+1);
std::snprintf( &(output[0]), SIZE+1, format, args... );
return std::move(output);
}
#endif
Usage:
#include "stringf.h"
int main(){
int year = 2020;
int month = 12;
int day = 20
std::string date = stringf("%d.%d.%d", year, month, day);
// date == "2020.12.20"
}
In C language use sprintf function from stdio.h header file.
char buffer[100];
sprintf(buffer,"%d.%d.%d", year, month, day);
See here for more info.

simple c++ time program error

I am messing around with the time header and have encountered an error:
invalid conversion from 'tm*' to 'time_t'
You can see the where the error is in the code below all the way at the bottom when I try to use the difftime function. I know im just doing something stupid and illegal but I cant see how I can get around this. If anyone has a solution let me know. Thanks!
The program is supposed to get the current time, take time input from a user, and then find the time difference.
Code:
#include <stdio.h>
#include <time.h>
int main ()
{
time_t rawtime;
struct tm * timeinfo;
struct tm * cur_timeinfo_hold;
int year, month ,day,hour,minute,second;
double dif;
/* prompt user for time to be compared*/
printf ("Enter year: "); scanf ("%d",&year);
printf ("Enter month: "); scanf ("%d",&month);
printf ("Enter day: "); scanf ("%d",&day);
printf ("Enter hour: "); scanf ("%d",&hour);
printf ("Enter minute: "); scanf ("%d",&minute);
printf ("Enter second: "); scanf ("%d",&second);
/* get current timeinfo*/
time ( &rawtime );
timeinfo = localtime ( &rawtime );
/* print it */
printf("The present time is: "); printf(asctime (timeinfo));
/* set current time into a new variable to use for difftime, since timeinfo, will be changed */
cur_timeinfo_hold = timeinfo;
/* modify current timeinfo to the user's choice */
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
timeinfo->tm_hour = hour;
timeinfo->tm_min = minute;
timeinfo->tm_sec = second;
mktime ( timeinfo );
/* and print it */
printf ("time to compare: "); printf(asctime (timeinfo));
/* find time difference */
//dif = difftime (cur_timeinfo_hold,timeinfo); //error: invalid conversion from 'tm*' to 'time_t'
return 0;
}
mktime is a function. It accepts one parameter, a tm pointer, and returns a value, a time_t. It does not transform its argument from one type into another. Therefore, after you call mktime(timeinfo), your timeinfo variable is still a tm pointer.
The difftime function expects to receive two time_t values, so it won't accept cur_timeinfo_hold or timeinfo; they're the wrong type. The first variable's value came from converting rawtime to a tm pointer with localtime, so use that for the first parameter. When you later called mktime(timeinfo), it returned a time_t value, but you ignored the return value. Assign the return value to a variable so you can use it for the second difftime parameter.
time_t info = mktime(timeinfo);
// ...
dif = difftime(rawtime, info);
It's because difftime requires the raw time_t values, not the struct tm structures.
The prototype is:
double difftime(time_t time1, time_t time0);
What you'll need to do is leave the system time as it is (no localtime performed on it) and then properly convert your user-entered information into the equivalent time_t with mktime (or timegm if working with UTC times).
Then you can use difftime to get the difference. Effectively, something like:
time_t base, other;
struct tm tms;
double delta;
time (&base); // basetime is now.
tms.blah = blah; // for all blahs.
other = mktime (&tms); // get time_t for other time.
delta = difftime (other, base); // get difference.

Splitting a `char[]` in C++

I have a char[] in YYYYMMDDHHMMSS format.
e.g. 2011052504572
I want to retrieve the year, month, date, hour, minute and second from this char. How do I do that?
NOTE:I cant use any third party dll.
Thanks,
Syd
If you're using the STL then just put the string into a std::string and use the substr method:
std::string dateTime=......;
std::string year=dateTime.substr(0,4);
std::string month=dateTime.substr(4,2);
// etc
// etc
Use string::substr() for this purpose. Example,
string date = "20110524112233";
string year = date.substr(0, 4);
string month = date.substr(4, 2);
string day = date.substr(6, 2);
string hour = date.substr(8, 2);
string minute = date.substr(10, 2);
string second = date.substr(12, 2);
It depends on whether you want to extract the values as text, or convert them to numbers. For getting lots of strings, you can use std::string and substr() as thoroughly illustrated in other answers.
If you want to get numbers that you can then calculate with, then one approach is:
int year, month, day, hour, minute, second;
if (sscanf(input, "%.4d%.2d%.2d%.2d%.2d%.2d",
&year, &month, &day, &hour, &minute, &second) == 6)
{
// all 6 conversions worked... can use the values...
int second_in_day = hour * 3600 + minute * 60 + second;
...
}
Another approach is to use strptime() - if your system has it. It parses a string into a broken-down-time structure:
struct tm tm;
strptime(input, "%Y%m%d%H%M%S", &tm);
// parsed values are in tm.tm_year, tm.tm_mon, tm.tm_mday,
// tm.tm_hour, tm.tm_min, tm.tm_sec
// further, tm_wday has day of week, tm_yday has day in year
// i.e. it actually understands the date, not just chopping up numbers/text
Note: sscanf() and strncpy() are C functions callable from C++, and they're not as safe to use as C++-specific functionality (std::string, std::istringstream) in that small misunderstandings and mistakes in handling the data can lead to not just erroneous results, but program crashes. So, read the manual pages for these things carefully if you use them.
Use strncpy... okay, so if it is not homework, then this is the best way. The others using std::string are wasting resources:
static const char *yyyymmddhhmmss = "20110526101559";
char year[5] = { '\0' };
char month[3] = { '\0' };
char day[3] = { '\0' };
char hour[3] = { '\0' };
char minute[3] = { '\0' };
char second[3] = { '\0' };
strncpy(year, yyyymmddhhmmss, 4);
strncpy(month, &yyyymmddhhmmss[4], 2);
strncpy(day, &yyyymmddhhmmss[6], 2);
strncpy(hour, &yyyymmddhhmmss[8], 2);
strncpy(minute, &yyyymmddhhmmss[10], 2);
strncpy(second, &yyyymmddhhmmss[12], 2);
Since you have the input in the form of a char[] (or char*—for
this use, it comes out to the same thing), the simplest solution is
probably using the two iterator constructors for std::string to creat
a string for each field, e.g.:
std::string year ( date , date + 4 );
std::string month( date + 4, date + 6 );
std::string day ( date + 6, date + 8 );
// ...
If you need the numerical values, boost::lexical_cast can be used,
e.g.:
int extractField( char const* string, int begin, int end )
{
return boost::lexical_cast<int>(
std::string( date + begin, date + end ) );
}
int year = extractField( date, 0, 4 );
int year = extractField( date, 4, 6 );
// ...