How to convert a string to json format in c++? - c++

So I'm reading some values from a sensor via SPI. I already converted those values to a string (don't know if I should but I was trying something). Now I can't convert them to json format.
Here is my code:
#include "ad7490Spi.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
string IntToString (int a2dVal)
{
ostringstream oss;
oss << a2dVal;
return oss.str();
}
int main(void)
{
ad7490Spi a2d("/dev/spidev0.0", SPI_MODE_0, 1000000, 16);
int i = 5;
int a2dVal = 0;
int a2dChannel = 0;
unsigned char data[3];
while(i > 0)
{
data[0] = 1; // first byte transmitted -> start bit
data[1] = 0b1000000000000000 |( ((a2dChannel & 15) << 4)); // second byte transmitted -> (SGL/DIF = 1, D2=D1=D0=0)
data[2] = 0; // third byte transmitted....don't care
a2d.spiWriteRead(data, sizeof(data) );
a2dVal = 0;
a2dVal = (data[1]<< 8) & 0b1100000000; //merge data[1] & data[2] to get result
a2dVal |= (data[2] & 0xff);
sleep(1);
i--;
string result = IntToString (a2dVal);
cout << " " + result + " ";
}
return 0;
}
This is the result:
1023 1023 1023 1023 1023
I want the result to be this way:
{
"values": [ "1023", "1023", "1023", "1023", "1023" ]
}
Can you guys help me with this?

this code:
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
void print_values(std::ostream& os, const std::vector<int>& v)
{
using namespace std;
os << "{\n";
os << "\t\"values\" : [";
auto sep = " ";
for (const auto& i : v) {
os << sep << quoted(to_string(i));
sep = ", ";
}
os << " ]\n";
os << "}\n";
}
auto main() -> int
{
print_values(std::cout, {1,2,3,4,5,6});
return 0;
}
results in:
{
"values" : [ "1", "2", "3", "4", "5", "6" ]
}
update:
this version will behave correctly with a c++11 compiler (and highlights some 'new' features of c++14 - but let's not live in the stone age too long eh?)
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
#if __cplusplus >= 201402L
#else
std::string quoted(const std::string& s) {
using namespace std;
return string(1, '"') + s + '"';
}
#endif
void print_values(std::ostream& os, const std::vector<int>& v)
{
using namespace std;
os << "{\n";
os << "\t\"values\" : [";
auto sep = " ";
for (const auto& i : v) {
os << sep << quoted(to_string(i));
sep = ", ";
}
os << " ]\n";
os << "}\n";
}
auto main() -> int
{
using namespace std;
print_values(cout,
#if __cplusplus >= 201402L
{1,2,3,4,5,6}
#else
[]() -> vector<int> {
vector<int> v;
for (int i = 1 ; i < 7 ; ++i )
v.push_back(i);
return v;
}()
#endif
);
return 0;
}

As you appear to be using C++ and the STL in an embedded system, I would recommend you using picojson. It is just a 1-header library and would be better than implementing the serialization yourself with some string manipulation. If you do so, it will get uglier later on if you extend your json output.

Related

Build incremental std::string

I try to build an std::string in the form of "start:Pdc1;Pdc2;Pdc3;"
With following code I can build the repeated "Pdc" and the incremental string "123" but I'm unable to combine the two strings.
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iterator>
#include <numeric>
int main()
{
std::ostringstream ss;
std::string hdr("start:");
std::fill_n(std::ostream_iterator<std::string>(ss), 3, "Pdc;");
hdr.append(ss.str());
std::string v("abc");
std::iota(v.begin(), v.end(), '1');
std::cout << hdr << std::endl;
std::cout << v << std::endl;
std::cout << "Expected output: start:Pdc1;Pdc2;Pdc3;" << std::endl;
return 0;
}
How can I build this string? Preferable without a while or for loop.
The expected output is: start:Pdc1;Pdc2;Pdc3;
std::strings can be concatenated via their operator+ (or +=) and integers can be converted via std::to_string:
std::string res("start:");
for (int i=0;i<3;++i){
res += "Pdc" + std::to_string(i+1) + ";";
}
std::cout << res << "\n";
If you like you can use an algorithm instead of the handwritten loop, but it will still be a loop (your code has 2 loops, but only 1 is needed).
Code to generate your expected string, though with a small for loop.
#include <iostream>
#include <string>
#include <sstream>
std::string cmd(const std::size_t N)
{
std::ostringstream os;
os << "start:";
for(std::size_t n = 1; n <= N; ++n) os << "Pdc" << n << ";";
return os.str();
}
int main()
{
std::cout << cmd(3ul);
return 0;
}

How to take delimiter as -0 between array size and array value of integer in c++

How to take delimiter as -0 between array size and array value of integer in c++.
for example: 2 -0 1,2 -0
array-size '-0' 1st array values separated by "," '-0'
If I take input in a string using get line then how to separate size from the string and take input of array.
int main(){
string s,t;
getline(cin,s);
stringstream x(s);
while(getline(x,t,"-0")){
cout << t;
}
}
I cannot understand delimiter concept properly from google, can you explain it and take input in the: " array-size '-0' 1st array values separated by ',' '-0' " form.
Given the input, the easiest way is to check the string token as being the -0 delimiter.
#include <iostream>
#include <sstream>
#include <string>
using std::cin;
using std::cout;
using std::getline;
using std::string;
using std::stringstream;
int main(){
string s,t;
getline(cin, s);
stringstream x(s);
char const* sep = "";
while (x >> t) {
if (t == "-0") {
cout << sep << "<DELIMITER>";
} else {
cout << sep << t;
}
sep = " ";
}
cout << "\n";
}
That gives:
echo '2 -0 1,2 -0' | ./a.out
2 <DELIMITER> 1,2 <DELIMITER>
Update
Storing the values into a std::vector<int>.
#include <cstddef>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::getline;
using std::ostream;
using std::runtime_error;
using std::size_t;
using std::stoi;
using std::string;
using std::stringstream;
using std::vector;
static auto MakeVecInt(string line) -> vector<int> {
auto result = vector<int>();
auto ss = stringstream(line);
auto value = string{};
while(getline(ss, value, ',')) {
result.push_back(stoi(value));
}
return result;
}
static auto operator<<(ostream& out, vector<int> const& v) -> ostream& {
char const* sep = "";
for (auto i : v) {
out << sep << i;
sep = " ";
}
return out;
}
int main() {
auto line = string{};
getline(cin, line);
auto ss = stringstream(line);
auto count = size_t{};
auto delimiter1 = string{};
auto values = string{};
auto delimiter2 = string{};
if (!(ss >> count >> delimiter1 >> values >> delimiter2))
throw runtime_error("bad input");
if (delimiter1 != "-0" || delimiter2 != "-0")
throw runtime_error("bad input");
auto vec = MakeVecInt(values);
if (count != vec.size())
throw runtime_error("bad input");
cout << vec << "\n";
}
Update
Note in the above code the vector<int> output routine:
static auto operator<<(ostream& out, vector<int> const& v) -> ostream&
It outputs each element in the vector, with a space between each element. It does not output a space before the first element.

Unexpected Behaviour in Cereal while Retrieving Object From Ignite Server using Redis Client

Below is my sample code through which i'm trying to benchmark hiredis client with IgniteServer to Store and Retrieve a C++ Class Object after serializing.
#include <cassert>
#include <sstream>
#include <string>
#include <unordered_map>
#include <time.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
#include <chrono>
#include <time.h>
#include <hiredis/hiredis.h>
#include <cereal/archives/binary.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/unordered_map.hpp>
using namespace std::chrono;
struct Person
{
friend class cereal::access;
template <typename Archive>
void serialize(Archive& archive) {
// archive(orgId,firstName, lastName,resume,salary,other);
archive & orgId & firstName & lastName & resume & salary & other;
}
Person() {}
Person(int32_t orgId, const std::string& firstName,
const std::string& lastName, const std::string& resume, double sal, const std::string& other) :
orgId(orgId),
firstName(firstName),
lastName(lastName),
resume(resume),
salary(sal),
other(other)
{
// No-op.
}
int64_t orgId;
std::string firstName;
std::string lastName;
std::string resume;
double salary;
std::string other;
};
auto redis_context = redisConnect("127.0.0.1", 6379);
int _set(int32_t key, Person p){
std::ostringstream oss;
cereal::BinaryOutputArchive archive{oss};
archive(p.orgId,p.firstName, p.lastName,p.resume,p.salary,p.other);
const auto set_reply =
redisCommand(redis_context, "SET %ld %b",(long)key,oss.str().c_str(), oss.str().length());
freeReplyObject(set_reply);
}
int _get(int32_t key){
const auto get_reply =
static_cast<redisReply*>(redisCommand(redis_context, "GET %ld",(long)key));
std::string repr{get_reply->str, static_cast<size_t>(get_reply->len)};
if(static_cast<size_t>(get_reply->len) <= 0) {
std::cout << "No key is matching" << std::endl;
return -1;
}
std::istringstream iss{repr};
cereal::BinaryInputArchive input(iss);
Person g;
input(g);
std::cout << g.orgId << " Name: " << g.firstName << " Last: " << g.lastName << "Resume: " << g.resume<< " Salary: " << g.salary << " Other: " << g.other <<std::endl;
freeReplyObject(get_reply);
iss.clear();
// redisFree(redis_context);
}
int _remove(int32_t key){
const auto del_reply =
static_cast<redisReply*>(redisCommand(redis_context, "DEL %ld",(long)key));
freeReplyObject(del_reply);
_get(key);
}
int main(int argc, char **argv) {
int start =1 ;
int range =3;
std::cout << "Starting Redis Testing " << std::endl;
clock_t begin_time = clock();
high_resolution_clock::time_point t1 = high_resolution_clock::now();
**//Person P{10,"John","Cena","Analyst",450000,"Summa"};// Works Fine when object is created in this way**
**Person P;
for (int32_t i = start ; i < range ; ++i)
{
P.orgId = i;
P.firstName = "Gibbi";
P.lastName = "Prakash";
P.resume = "Analyst";
P.salary = 45000;
P.other = "Summa";
_set(i,P);
}
for (int32_t i = start; i < range; ++i)
{
try{
_get(i);
//break;
}catch(cereal::Exception e){
std::cout << "Caught Exception " << std::endl;
}
}
for (int32_t i = start; i < range; ++i)
{
_remove(i);
}
}
When object is created Person P{10,"John","Cena","Analyst",450000,"Summa"}; in this way the program works as expected.
OUTPUT:
Starting Redis Testing
1 Name: John Last: CenaResume: Analyst Salary: 450000 Other: Summa
2 Name: John Last: CenaResume: Analyst Salary: 450000 Other: Summa
No key is matching
No key is matching
when i created object First then assign values
(
Person P; //when object is created first then values are assigned to it.
P.orgId = i;
P.firstName = "Gibbi";
P.lastName = "Prakash";
P.resume = "Analyst";
P.salary = 45000;
P.other = "Summa";
), the output is empty or the client just hangs.
I'm not sure what was happening behind the scenes since i'm very new to using cereal library. I feel the issue is with cereal, but i couldn't figure it.

Boost, how to parse following string to date/time

I have the following milli/micro second accuracy string to parse into some sort of boost datetime.
std::string cell ="20091201 00:00:04.437";
I have seen documentation regarding facets. Something like this
date_input_facet* f = new date_input_facet();
f->format("%Y%m%d %F *");
but I don't know how to use them.
I tried this program with code scavenged from StackOverflow, but I can't get the millis to show:
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include <map>
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time.hpp>
namespace bt = boost::posix_time;
const std::locale formats[] =
{
std::locale(std::locale::classic(),new bt::time_input_facet("%Y%m%d %H:%M:%S.f")),
std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
};
const size_t formats_n = sizeof(formats) / sizeof(formats[0]);
std::time_t pt_to_time_t(const bt::ptime& pt)
{
bt::ptime timet_start(boost::gregorian::date(1970,1,1));
bt::time_duration diff = pt - timet_start;
return diff.ticks()/bt::time_duration::rep_type::ticks_per_second;
}
void seconds_from_epoch(const std::string& s)
{
bt::ptime pt;
for(size_t i = 0; i < formats_n; ++i)
{
std::istringstream is(s);
is.imbue(formats[i]);
is >> pt;
if(pt != bt::ptime()) break;
}
bt::time_duration td = pt.time_of_day();
long fs = td.fractional_seconds();
std::cout << " ptime is " << pt << '\n';
std::cout << " seconds from epoch are " << pt_to_time_t(pt) << " " << fs << '\n';
}
int main(int, char *argv[])
{
std::string cell ="20091201 00:00:04.437";
seconds_from_epoch(cell);
int enterAnumber;
std::
cin >> enterAnumber;
}
boost::posix_time::time_from_string is very rigid when it comes to parsing formats.
You are looking for a different way to create a boost::posix_time::ptime from an std::string. You want to imbue a stringstream with the format, as such:
const std::string cell = "20091201 00:00:04.437";
const std::locale loc = std::locale(std::locale::classic(), new boost::posix_time::time_input_facet("%Y%m%d %H:%M:%S%f"));
std::istringstream is(cell);
is.imbue(loc);
boost::posix_time::ptime t;
is >> t;
Then
std::cout << t << std::endl;
gives
2009-Dec-01 00:00:04.437000

How to convert Byte Array to Hexadecimal String in C++?

I am looking for a fastest way to convert a byte array of arbitrary length to a hexadecimal string. This question has been fully answered here at StackOverflow for C#. Some solutions in C++ can be found here.
Are there any "turnkey" or "ready-made" solutions to a problem? C-style solutions are welcome.
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
#include <sstream>
#include <iomanip>
int main()
{
std::vector<unsigned char> v;
v.push_back( 1 );
v.push_back( 2 );
v.push_back( 3 );
v.push_back( 4 );
std::ostringstream ss;
ss << std::hex << std::uppercase << std::setfill( '0' );
std::for_each( v.cbegin(), v.cend(), [&]( int c ) { ss << std::setw( 2 ) << c; } );
std::string result = ss.str();
std::cout << result << std::endl;
return 0;
}
Or, if you've got a compiler that supports uniform initialization syntax and range based for loops you can save a few lines.
#include <vector>
#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>
int main()
{
std::vector<unsigned char> v { 1, 2, 3, 4 };
std::ostringstream ss;
ss << std::hex << std::uppercase << std::setfill( '0' );
for( int c : v ) {
ss << std::setw( 2 ) << c;
}
std::string result = ss.str();
std::cout << result << std::endl;
}
Use boost::alogorithm::hex
std::vector<unsigned char> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
std::string res;
boost::algorithm::hex(v.begin(), v.end(), back_inserter(res));
You can use the C++ Standard Library and or you can use boost::lexical_cast
#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <sstream>
#include <iomanip>
#include <algorithm>
using namespace std;
// use this macro for c++11 feature
#define USE_CPP11
int main(int argc, char* argv[])
{
array<unsigned char, 3> hexArr = {0x01, 0xff, 0x55};
const char separator = ' '; // separator between two numbers
ostringstream os;
os << hex << setfill('0'); // set the stream to hex with 0 fill
#ifdef USE_CPP11
std::for_each(std::begin(hexArr), std::end(hexArr), [&os, &separator] (int i)
{
os << setw(2) << i << separator;
});
#else // c++03
typedef array<unsigned char, 3>::const_iterator const_iterator;
for (const_iterator it = hexArr.begin(); it != hexArr.end(); ++it)
{
os << setw(2) << int(*it) << separator;
}
#endif
os << dec << setfill(' '); // reset the stream to "original"
// print the string
cout << "the string array is: " << os.str() << endl;
return EXIT_SUCCESS;
}
One of the fastest way I know in C++ 11:
template <size_t byteCount>
string BytesArrayToHexString( const std::array<byte, byteCount>& src )
{
static const char table[] = "0123456789ABCDEF";
std::array<char, 2 * byteCount + 1> dst;
const byte* srcPtr = &src[0];
char* dstPtr = &dst[0];
for (auto count = byteCount; count > 0; --count)
{
unsigned char c = *srcPtr++;
*dstPtr++ = table[c >> 4];
*dstPtr++ = table[c & 0x0f];
}
*dstPtr = 0;
return &dst[0];
}
A good compiler should not have any problem to apply SSE optimization on this....