C++ time() gives me almost random result - c++

I wrote a following simple code:
time_t makeUnixTimeStamp( int year, int month, int day, int hour, int min, int sec ) {
tm uts_time;
uts_time.tm_year = year - 1900;
uts_time.tm_mon = month - 1;
uts_time.tm_mday = day;
uts_time.tm_sec = sec;
uts_time.tm_min = min;
uts_time.tm_hour = hour;
return mktime( &uts_time );
}
std::string getReadableDateTime( unsigned int unixTimeStamp ) {
char dateTime[ 40 ];
time_t someTime = unixTimeStamp;
struct tm *mTime;
mTime = localtime( &someTime );
strftime( dateTime, sizeof( dateTime ), "%Y-%m-%d %H:%M:%S", mTime );
return std::string( dateTime );
}
unsigned int startLogTime = makeUnixTimeStamp( 2016, 05, 04, 00, 00, 00 );
time_t nowTime;
time( &nowTime );
std::cout << "readable Time = " << getReadableDateTime( startLogTime ) << '\n';
I get strange output after a few runs. I do php -r 'echo time();' for show current second.
Why have I different "readable time" if I don't change anything in my code?
Output:
15:20:58 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-04 00:00:00
1462450865
15:21:05 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-04 00:00:00
1462450866
15:21:06 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-04 00:00:00
1462450867
15:21:07 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-03 23:00:00
1462450868
15:21:08 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-03 23:00:00
1462450869
15:21:09 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-04 00:00:00
1462450871
15:21:11 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-03 23:00:00
1462450872
15:21:12 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-04 00:00:00
1462450877
15:21:17 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-04 00:00:00
1462450882
15:21:22 ~ $ rm a.out && g++ analyze.cpp && ./a.out && php -r 'echo time();'
readable Time = 2016-05-03 23:00:00
1462450883
Seems that if I remove time() function - it works better but I need it after that code.

You should set the DST flag. It is probably being randomly initialized
The Daylight Saving Time flag (tm_isdst) is greater than zero if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and less than zero if the information is not available.
http://www.cplusplus.com/reference/ctime/tm/
A useful recipe is to fist initialize the tm structure with the current local time, so that this gets set the same way as everything else on your machine.
time_t now = time(0);
uts_time = * localtime( &now );
// initialise with the time you really want

You have some uninitialised parts of your tm structure: the behaviour on reading back any uninitialised portion is undefined.
Use code like tm foo{}; instead which causes all structure elements to be initialised with zero values (and pointers to null pointer values).

Related

boost::program_options positional options

I have a positional option (a file name), and I want it to be the very last option. The user can pass in a bunch of stuff on the command line, and also use -F for the file name. However, I want the user also to have the ability to place the file name at the end.
For example:
./program --var 3 /path/to/file
The code I currently have implemented allows the caller to place the file name wherever in the command line. Is there any way to force the positional arguments to always come after the "regular" ones?
Here's how I set-up the positional argument:
pos_opts_desc.add("filename", -1);
And to parse the command line:
store(
command_line_parser(argc, argv).options(opts_desc).positional(pos_opts_desc).run(),
opts_var_map);
Thanks in advance for the help.
Edited to add:
I'm perfectly OK with -F being specified anywhere in the command line. However, if the setting was done via the positional option, I want to ensure that the positional option is at the very end.
The run() member function gives you back an instance of type parsed_options. The simple usage is to never actually look at this object and pass it directly into store(), as in your example:
po::store(
po::command_line_parser(argc, argv).options(opts_desc).positional(pos_opts_desc).run(),
opts_var_map);
But we can hold onto it and examine its contents:
auto parsed = po::command_line_parser(argc, argv)
.options(opts_desc)
.positional(pos_opts_desc)
.run();
po::store(parsed, opts_var_map);
The parsed_options class has a member options which has an ordered list of all the options (unlike the variable map, which is ordered by option name - since it's a std::map). So you can look up the "filename" argument and check its position_key member. We want either: position_key == -1 (which means it provided with -F) or position_key == 0 and it being the last element in the options list (it was a positional argument that was the last argument):
auto it = std::find_if(parsed.options.begin(),
parsed.options.end(),
[](po::option const& o) {
return o.string_key == "filename";
});
if (it == parsed.options.end()) {
// fail: missing filename);
}
if (it->position_key != -1 && it != std::prev(parsed.options.end())) {
// fail: filename was positional but wasn't last
}
variables_map is as the name suggests a std::map, which allows us to use regular STL functions on it.
if ( vm.count("filename") ) {
if ( vm.find("filename") != std::prev(vm.rbegin()).base() ) {
std::cout << "filename must go at the end.";
}
}
Test cases:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp -lboost_system -lboost_program_options \
&& echo -n "Case 1 " && ./a.out asdf --foo=12 && echo \
&& echo -n "Case 2 " && ./a.out --foo=12 asdf && echo \
&& echo -n "Case 3 " && ./a.out asdf && echo \
&& echo -n "Case 4 " && ./a.out --foo=12 && echo \
&& echo -n "Case 5 " && ./a.out && echo \
&& echo -n "Case 6 " && ./a.out --foo=12 asdf asdf
Result:
Case 1 filename must go at the end.
Case 2
Case 3
Case 4
Case 5
Case 6 option '--filename' cannot be specified more than once

Using a text file as input for a binary

I'm trying to test my homework (knapsack problem) and it's getting repetitive entering all these inputs every time I recompile.
Here's what I've got:
will#will-mint ~/code/byun-sp15 $ g++ knapsack.cpp
will#will-mint ~/code/byun-sp15 $ ./a.out
Please enter number of items: 3
Please enter Knapsack Capacity: 10
Enter weights and values of 3 items:
Item 1: 3 40
Item 2: 2 10
Item 3: 5 50
0 * 0 * 0 * 0 * 0 * 0 * 0 * 0 * 0 * 0 *
0 * 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10 *
0 * 50 * 50 * 99 * 50 * 50 * 60 * 60 * 60 * 60 *
Clearly my table is not correct, please do not help me there. NO SPOILERS!
I put 3 10 3 40 2 10 5 50 in test.txt and tried the following:
will#will-mint ~/code/byun-sp15 $ vim test.txt
will#will-mint ~/code/byun-sp15 $ test.txt > ./a.out
test.txt: command not found
will#will-mint ~/code/byun-sp15 $ cat test.txt | ./a.out
will#will-mint ~/code/byun-sp15 $ cat test.txt | ./a.out >> output.log
will#will-mint ~/code/byun-sp15 $ vim output.log
will#will-mint ~/code/byun-sp15 $ cat test.txt | ./a.out 2> output.log
will#will-mint ~/code/byun-sp15 $ vim output.log
will#will-mint ~/code/byun-sp15 $ ./a.out < test.txt
will#will-mint ~/code/byun-sp15 $ cat test.txt | ./a.out > output.log
will#will-mint ~/code/byun-sp15 $ vim output.log
will#will-mint ~/code/byun-sp15 $ ./a.out << test.txt
None of which worked. I need help with my bash-fu, how can I use a string of space-separated numbers in a text file as input for my a.out?

Escaping special characters with sed

I have a script to generate char arrays from strings:
#!/bin/bash
while [ -n "$1" ]
do
echo -n "{" && echo -n "$1" | sed -r "s/((\\\\x[0-9a-fA-F]+)|(\\\\[0-7]{1,3})|(\\\\?.))/'\1',/g" && echo "0}"
shift
done
It works great as is:
$ wchar 'test\n' 'test\\n' 'test\123' 'test\1234' 'test\x12345'
{'t','e','s','t','\n',0}
{'t','e','s','t','\\','n',0}
{'t','e','s','t','\123',0}
{'t','e','s','t','\123','4',0}
{'t','e','s','t','\x12345',0}
But because sed considers each new line to be a brand new thing it doesn't handle actual newlines:
$ wchar 'test
> test'
{'t','e','s','t',
't','e','s','t',0}
How can I replace special characters (Tabs, newlines etc) with their escaped versions so that the output would be like so:
$ wchar 'test
> test'
{'t','e','s','t','\n','t','e','s','t',0}
Edit: Some ideas that almost work:
echo -n "{" && echo -n "$1" | sed -r ":a;N;;s/\\n/\\\\n/;$!ba;s/((\\\\x[0-9a-fA-F]+)|(\\\\[0-7]{1,3})|(\\\\?.))/'\1',/g" && echo "0}"
Produces:
$ wchar 'test\n\\n\1234\x1234abg
test
test'
{test\n\\n\1234\x1234abg\ntest\ntest0}
While removing the !:
echo -n "{" && echo -n "$1" | sed -r ":a;N;;s/\\n/\\\\n/;$ba;s/((\\\\x[0-9a-fA-F]+)|(\\\\[0-7]{1,3})|(\\\\?.))/'\1',/g" && echo "0}"
Produces:
$ wchar 'test\n\\n\1234\x1234abg
test
test'
{'t','e','s','t','\n','\\','n','\123','4','\x1234ab','g','\n','t','e','s','t',
test0}
This is close...
The first isn't performing the final replacement, and the second isn't correctly adding the last line
You can pre-filter before passing to sed. Perl will do:
$ set -- 'test1
> test2'
$ echo -n "$1" | perl -0777 -pe 's/\n/\\n/g'
test1\ntest2
This is a very convoluted solution, but might work for your needs. GNU awk 4.1
#!/usr/bin/awk -f
#include "join"
#include "ord"
BEGIN {
RS = "\\\\(n|x..)"
FS = ""
}
{
for (z=1; z<=NF; z++)
y[++x] = ord($z)<0x20 ? sprintf("\\x%02x",ord($z)) : $z
y[++x] = RT
}
END {
y[++x] = "\\0"
for (w in y)
y[w] = "'" y[w] "'"
printf "{%s}", join(y, 1, x, ",")
}
Result
$ cat file
a
b\nc\x0a
$ ./foo.awk file
{'a','\x0a','b','\n','c','\x0a','\0'}

Find foldername of highest version [duplicate]

This question already has answers here:
Unix sort of version numbers
(7 answers)
Closed 9 years ago.
I've got a few folders
src/1.0.0.1/
src/1.0.0.2/
src/1.0.0.12/
src/1.0.0.13/
src/1.0.1.1/
I'm looking for a bash command-chain that always returns only the latest version.
In the upper case that would be 1.0.1.1. If 1.0.1.1 wasn't present the latest version would be 1.0.0.13
I'm on OS X so sort has no -V option.
Can anyone help me out here?
You can also use an awk script:
#!/usr/bin/awk -f
$0 ~ /[0-9]+(.[0-9]+)*\/?$/ {
t = $0
sub(/\/$/, "", t)
sub(/.*\//, "", t)
current_count = split(t, current_array, /\./)
is_later = 0
for (i = 1; i <= current_count || i <= latest_count; ++i) {
if (current_array[i] > latest_array[i]) {
is_later = 1
break
} else if (latest_array[i] > current_array[i]) {
break
}
}
if (is_later) {
latest_string = $0
latest_count = split(t, latest_array, /\./)
}
}
END {
if (latest_count) {
print latest_string
}
}
Run:
find src/ -maxdepth 1 -type d | awk -f script.awk ## Or
ls -1 src/ | awk -f script.awk
You can also use a minimized version:
... | awk -- '$0~/[0-9]+(.[0-9]+)*\/?$/{t=$0;sub(/\/$/,"",t);sub(/.*\//,"",t);c=split(t,a,/\./);l=0;for(i=1;i<=c||i<=z;++i){if(a[i]>x[i]){l=1;break}else if(x[i]>a[i])break}if(l){s=$0;z=split(t,x,/\./)}}END{if(z)print s}'
Use sort (the -V option performs version sort):
$ ls -1 src/
1.0.0.1
1.0.0.12
1.0.0.13
1.0.0.2
$ find src/1* -type d | sort -rV
src/1.0.0.13
src/1.0.0.12
src/1.0.0.2
src/1.0.0.1
$ mkdir src/1.0.1.1
$ find src/1* -type d | sort -rV
src/1.0.1.1
src/1.0.0.13
src/1.0.0.12
src/1.0.0.2
src/1.0.0.1
Pipe the output to head and you can get only the highest version:
$ find src/1* -type d | sort -rV | head -1
src/1.0.1.1

Why am I not getting the sha256 right?

I am using crypto++ library for some exercise. I am expecting the same output as from the sha256sum tool invoked from the shell.
// typedef unsigned char byte;
byte out[CryptoPP::SHA256::DIGESTSIZE];
byte in=65; // 'A'
CryptoPP::SHA256().CalculateDigest(out, &in, 1);
for(int i=0; i < CryptoPP::SHA256::DIGESTSIZE; i++)
std::cout << std::hex << (int)out[i];
std::cout << std::endl;
559aead08264d5795d399718cdd5abd49572e84fe55590eef31a88a08fdffd
$ echo A | sha256sum
06f961b802bc46ee168555f066d28f4f0e9afdf3f88174c1ee6f9de004fc30a0
Why are the two not equal?
echo appends a newline, so you're comparing the hashes of different strings. Use printf instead:
$ printf 'A' | sha256sum
559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd -
$ printf 'A\n' | sha256sum
06f961b802bc46ee168555f066d28f4f0e9afdf3f88174c1ee6f9de004fc30a0 -
In your command line, you're checksumming A + a line feed.
If your unix version supports it, use echo -n to echo without adding the line feed;
$ echo -n A | sha256sum
559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd -