Printing the time in milliseconds in c++ - c++

HI I'm trying to log a sensor data to CSV file. I want the first row to be hh:mm:ss:ms.
The Code I have is
#include <chrono>
#include <ctime>
eyeDataLog << std::ctime(&today_time) << ","
<< gazeleft[0] << ","
<< gazeleft[1] << ","
|Timestamp2 |left gaze X |left gaze Y |left gaze Z |right gaze X
|Tue Mar 1 18:19:31 2022 |0 |0 |0 |0
how to add milliseconds to the logged time
regared thanks

You may try strftime or other library like fmt which is included in c++20.
Update: even you don't use C++20, fmt library itself is compatible with c++11 and above.
Since you have formatting requirement in logging, fmt might fit well.
Demo for fmt
#include <fmt/chrono.h>
int main() {
using namespace std::literals::chrono_literals;
fmt::print("Default format: {} {}\n", 42s, 100ms);
// %S prints milliseconds
fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s + 15ms);
}

Related

get_time parsing error for two digits year

std::get_time is behaving in the same way when the format includes '%y' or '%Y', in both cases it tries to read a four digit year. Am I doing something wrong or is it a bug ?
Example code:
#include <iostream>
#include <iomanip>
void testDate(const char *format,const char *date)
{
std::istringstream ds(date);
std::tm tm = {};
ds >> std::get_time(&tm,format);
std::cout<<date<<" parsed using "<<format<<" -> Year: "<<tm.tm_year+1900<<" Month: "<<tm.tm_mon<<" Day: "<<tm.tm_mday<<std::endl;
}
int main()
{
testDate("%y%m%d","101112");
testDate("%Y%m%d","101112");
testDate("%y%m%d","20101112");
testDate("%Y%m%d","20101112");
return 0;
}
Output:
101112 parsed using %y%m%d -> Year: 1011 Month: 11 Day: 0
101112 parsed using %Y%m%d -> Year: 1011 Month: 11 Day: 0
20101112 parsed using %y%m%d -> Year: 2010 Month: 10 Day: 12
20101112 parsed using %Y%m%d -> Year: 2010 Month: 10 Day: 12
Tested with:
g++ (SUSE Linux) 11.2.1 20210816 [revision 056e324ce46a7924b5cf10f61010cf9dd2ca10e9]
clang++ version 12.0.1
Found after testing
%y - Enter only two digits
%Y - Enter only four digits
If you use 4 digits when using %y, then 4 digits will be output directly, if it is 2 digits, it is consistent with the document
The Month
The Month, From the std::tm
tm_mon : months since January – [0, 11]
so it print out 11 represents December. You can use below code to print out the date.
std::cout << std::put_time(&tm, "%c") << std::endl;

Conversion to UTC timezone in C++ leaves the time intact (regardless of the original timezone)

I am working with a dataset that contains the following information: date and time in the form "yyyy-mm-dd", "hh:mm". It also contains the name of the US state where the time has been measured. My goal is to unify all the time measurements so that they are all in the UTC timezone. I have written a code that doesn't work and I don't intend to go through the details of that code. However, in order to check why my code doesn't work, I have written a simple test that also doesn't work. The test is as follows:
I have tried to convert "Friday January 1 2021 9:00 AM California" to its equivalent UTC time which is "Friday January 1 2021 5:00 PM". The code snippet for conversion comes in the following:
struct tm calTM;
calTM.tm_hour = 9;
calTM.tm_min = 0;
calTM.tm_year = 2021-1900;
calTM.tm_mon = 1-1;
calTM.tm_mday = 1;
calTM.tm_isdst = -1;
setenv("TZ", "America/California", 1);
time_t calTime = mktime(&calTM);
unsetenv("TZ");
struct tm* utcTime;
utcTime = gmtime(&calTime);
cout << "UTC hh: " << utcTime->tm_hour << ", UTC mm: " << utcTime->tm_min;
cout << ", UTC year: " << utcTime->tm_year << ", UTC month: " << utcTime->tm_mon << ", UTC day: " << utcTime->tm_mday << endl;
Instead of producing the expected result (Friday January 1 2021 5:00 PM), the code snippet above produces the following result:
UTC hh: 9, UTC mm: 0, UTC year: 121, UTC month: 0, UTC day: 1
which is "month 0, day 1, year 121, 9:00 AM". Year and month are fixed after passing utcTime to the mktime() function. After adding the lines
time_t utc_time_t = mktime(utcTime);
cout << ctime(&utc_time_t) << endl;
the output is
Fri Jan 1 09:00:00 2021
Still, the time (hh:mm:ss) is wrong (exactly the same as in the original timezone). Could you please help me figure out the problem with my code? Thank you very much!

boost::exists for symlinks do not dereference

In boost::filesystem, the path class always tries to dereference symlinks. A lot of the API is catered towards trying to make symlinks seem invisible. I'm guessing a lot of their syscalls underneath are stat related instead of lstat related. This is problematic for me, as I'm trying to get the symlink itself.
For example, doing fs::exists("some_symlink") because, although some_symlink exists, its referent does not exist. I want this to give me back true, and in the older versions of boost it supports it: https://www.boost.org/doc/libs/1_32_0/libs/filesystem/doc/operations.htm#symbolic_link_exists
However, now it doesnt. Is there any good way of doing this?
You can use boost::filesystem::symlink_status to get a file_status, and then check its type().
#include <boost/filesystem.hpp>
#include <iostream>
#include <iomanip>
int main(){
auto a = boost::filesystem::symlink_status("a_symlink");
auto b = boost::filesystem::symlink_status("main.cpp");
auto c = boost::filesystem::symlink_status("not_existing");
auto d = boost::filesystem::symlink_status("a_broken_symlink");
std::cout << std::boolalpha
<< (a.type() == boost::filesystem::file_not_found) << " "
<< (b.type() == boost::filesystem::file_not_found) << " "
<< (c.type() == boost::filesystem::file_not_found) << " "
<< (d.type() == boost::filesystem::file_not_found) << "\n";
}
Execution:
$ touch f
$ ln -s main.cpp a_symlink
$ ln -s f a_broken_symlink
$ rm f
$ ls -l
total 4
lrwxrwxrwx 1 2001 2000 1 Jun 3 23:33 a_broken_symlink -> f
lrwxrwxrwx 1 2001 2000 8 Jun 3 23:33 a_symlink -> main.cpp
-rw-rw-rw- 1 2001 2000 637 Jun 3 23:33 main.cpp
$ g++ -std=c++14 -Wall -Wextra -pedantic -lboost_filesystem -lboost_system main.cpp && ./a.out
false false true false
Live on Coliru

Cern ROOT 5.34 error message using functions

I'm using the Cern ROOT version 5.34 and I have a problem using functions. The same message error always appear.
For example (using a very simple function):
*******************************************
* *
* W E L C O M E to R O O T *
* *
* Version 5.34/36 5 April 2016 *
* *
* You are welcome to visit our Web site *
* http://root.cern.ch *
* *
*******************************************
ROOT 5.34/36 (v5-34-36#v5-34-36, Apr 05 2016, 10:25:45 on win32)
CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0] #include <iostream>
Note: File "iostream" already loaded
root [1] using namespace std;
root [2] void hello(){cout << "Hi!" << endl;}
Limitation: Function can not be defined in a command line or a tempfile
You need to write it in a source file (tmpfile)(1)
*** Interpreter error recovered ***
root [3]
How can I fix this?
If you used root 6, which supports all C++11 features, you could define a lambda function instead, like so
auto hello = [](){ cout << "Hi!" << endl; };
You can then call it just like a regular function
hello();

Splitting a vector according to a table

A premise, I'm not a programmer, I'm a physicist and I use c++ as a tool to analyze data (ROOT package). My knowledge might be limited!
I have this situation, I read data from a file and store them in a vector (no problem with that)
vector<double> data;
with this data I want to plot a correlation plot, so I need to split them up in two different subsets one of which will be the X entries of a 2D histogram and the other the Y entries.
The splitting must be as follow, I have this table (I only copy a small part of it just to explain the problem)
************* LBA - LBC **************
--------------------------------------
Cell Name | Channel | PMT |
D0 | 0 | 1 |
A1-L | 1 | 2 |
BC1-R | 2 | 3 |
BC1-L | 3 | 4 |
A1-R | 4 | 5 |
A2-L | 5 | 6 |
BC2-R | 6 | 7 |
BC2-L | 7 | 8 |
A2-R | 8 | 9 |
A3-L | 9 | 10 |
A3-R | 10 | 11 |
BC3-L | 11 | 12 |
BC3-R | 12 | 13 |
D1-L | 13 | 14 |
D1-R | 14 | 15 |
A4-L | 15 | 16 |
BC4-R | 16 | 17 |
BC4-L | 17 | 18 |
A4-R | 18 | 19 |
A5-L | 19 | 20 |
...
None | 31 | 32 |
as you can see there are entries like A1-L and A1-R which corresponds to the left and right side of one cell, to this left and right side are associated an int that corresponds to a channel, in this case 1 and 4. I wish these left and right side to be on the X and Y axis of my 2D histogram.
The problem is then to associate to the vector of data somehow this table so that I can pick the channels that belongs to the same cell and put them one on the X axis and the other on the Y axis. To complicate the things there are also cells that don't have a partner like in this example D0 and channels that don't have a cell associated like channel 31.
My attempted solution is to create an indexing vector
vector<int> indexing = (0, 1, 4, ....);
and an ordered data vector
vector<double> data_ordered;
and fill the ordered vector with something like
for( vector<int> iterator it = indexing.begin(); it != indexing.end(); ++it)
data_ordered.push_back(data.at(*it));
and then put the even index of data_ordered on the X axis and the odd values on the Y axis but I have the problem of the D0 cell and the empty ones!
Another idea that I had is to create a struct like
struct cell{
string cell_name;
int left_channel;
int right_channel;
double data;
....
other informations
};
and then try to work with that, but there it comes my lack of c++ knowledge! Can someone give me an hint on how to solve this problem? I hope that my question is clear enough and that it respects the rules of this site!
EDIT----------
To clarify the problem I try to explain it with an example
vector<double> data = (data0, data1, data2, data3, data4, ...);
do data0 has index 0 and if I go to the table I see it corresponds to the cell D0 which has no other partner and let's say can be disregarded for now. data1 has index 1 and it corresponds to the left part of the cell A1 (A1-L) so I need to find the right partner which has index 4 in the table and ideally leads me to pick data4 from the vector containing the data.
I hope this clarify the situation at least a little!
Here is an engine that does what you want, roughly:
#include <vector>
#include <map>
#include <string>
#include <iostream>
enum sub_entry { left, right, only };
struct DataType {
std::string cell;
sub_entry sub;
DataType( DataType const& o ): cell(o.cell), sub(o.sub) {};
DataType( const char* c, sub_entry s=only ):
cell( c ),
sub( s )
{}
DataType(): cell("UNUSED"), sub(only) {};
// lexographic weak ordering:
bool operator<( DataType const& o ) const {
if (cell != o.cell)
return cell < o.cell;
return sub < o.sub;
}
};
typedef std::vector< double > RawData;
typedef std::vector< DataType > LookupTable;
typedef std::map< DataType, double > OrganizedData;
OrganizedData organize( RawData const& raw, LookupTable const& table )
{
OrganizedData retval;
for( unsigned i = 0; i < raw.size() && i < table.size(); ++i ) {
DataType d = table[i];
retval[d] = raw[i];
}
return retval;
}
void PrintOrganizedData( OrganizedData const& data ) {
for (OrganizedData::const_iterator it = data.begin(); it != data.end(); ++it ) {
std::cout << (*it).first.cell;
switch( (*it).first.sub ) {
case left: {
std::cout << "-L";
} break;
case right: {
std::cout << "-R";
} break;
case only: {
} break;
}
std::cout << " is " << (*it).second << "\n";
}
}
int main() {
RawData test;
test.push_back(3.14);
test.push_back(2.8);
test.push_back(-1);
LookupTable table;
table.resize(3);
table[0] = DataType("A1", left);
table[1] = "D0";
table[2] = DataType("A1", right);
OrganizedData org = organize( test, table );
PrintOrganizedData( org );
}
The lookup table stores what channel maps to what cell name and side.
Unused entries in the lookup table should be set to DataType(), which will flag their values to be stored in an "UNUSED" location. (It will still be stored, but you can discard it afterwards).
The result of this is a map from (CellName, Side) to the double data. I included a simple printer that just dumps the data. If you have graphing software, you can figure out a way to make a graph from it. Skipping "UNUSED" is an exercise that involves checking (*it).first.cell == "UNUSED" in that printing loop.
I believe everything is C++03 compliant. A bunch of the above becomes prettier if you had a C++11 compiler.