C++ how to cout and write at the same time - c++

After reading this: C++ Writing to file and Console Output at the same time with simple code , I am trying to write a function to handle what I have in the for-loop. But I don't know how to pass a piece of code like this :setw(3) << right << get<0>(*it_party) << setw(9) << "" altogether as an argument into a function so that both cout and file can use it.
The helper function I am trying to write:
void print(std::ostream &os1, std::ostream &os2, const [I don't know what to put in here])
{
os1 << the argument; // cout
os2 << the argument; // file
}
ofstream file;
file.open("test.txt");
for (auto it_party = parties_.begin(); it_party != parties_.end(); ++it_party) {
cout << setw(3) << right << get<0>(*it_party) << setw(9) << "";
file << setw(3) << right << get<0>(*it_party) << setw(9) << "";
cout << setw(7) << left << get<1>(*it_party) << setw(1) << "";
file << setw(7) << left << get<1>(*it_party) << setw(1) << "";
...
...
}

If you want to string outputs together like that, you'll probably find it easier to use some kind of "tee" class:
class Tee {
private:
std::ostream &os1, &os2;
public:
Tee(std::ostream &os1, std::ostream &os2) : os1(os1), os2(os2) { }
template <typename T>
Tee& operator<<(const T &thing) {
os1 << thing;
os2 << thing;
return *this;
}
};
This'll take a template argument, so it won't care whether you're passing right or setw(3). You can use it like:
Tee t(std::cout, std::cout);
t << setw(10) << "right" << " Thing" << setw(9);

You can easily do this using std::stringstream. I don't know what get<>() is but here is a basic example:
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
void fn(std::string output) {
std::ofstream file("file.txt");
std::cout << output;
file << output;
}
int main() {
std::stringstream buffer;
buffer << "some random text" << std::endl;
fn(buffer.str());
return 0;
}

Unfortunately, you cannot pass all that stuff as only one argument. But there are some advanced techniques, that can help you, such as variadic templates and C++17 fold expressions.
Variadic templates are a feature that allows you, for example, to pass an unknown at compile-time amount of arguments of different types. You can see some examples of such in a standard library, such as std::tuple.
Fold expressions are yet another feature used in combination with the former one. It allows you to write pretty simple variadic-templated code:
template<typename ...Args>
void printer(const Args &... args) {
(std::cout << ... << args) << '\n';
}
Here we see a function, that takes some const & to some arguments (we don't know their count or distinct types), but we have such fancy thing as args, a parameter pack, that represents our arguments, and Args as their types "packed" together;
You can use that to pass arbitrary arguments to your streams:
template<typename ...Args>
void printer(const Args &... args) {
(std::cout << ... << args);
(file << ... << args);
}
There are some other things to improve in this solution, such as perfect forwarding, but these are for further study.

Related

Output a number that may be one of three types

I have a variable x.
It may either be of type char, uint8_t or std::string.
I wish to output the number (not character), using the same expression involving std::cout. This is because I use this expression in generated code.
At code-generation-time, I currently don't know if x will be char, uint8_t or std::string.
std::cout << x << std::endl does not work if x is of type char, since it will output the character and not the number.
std::cout << +x << std::endl does not work if x is of type std::string.
std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? +x : x) << std::endl does not work if x is of type std::string.
std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? static_cast<int>(x) : x) << std::endl does not work if x is of type std::string.
I am aware that std::cout can be configured in various ways by piping std::hex or std::boolalpha, but I know of no possible way to configure std::cout to output a char as a number, without casting the char first.
Is there a way to use reflection, operator overloading, templates or something else
so that one can have a single unified statement for outputting x, as a number?
For example, if x is 65 with type char, the desired output is 65, not A.
Just format a helper and specialize the versions you want to customize appropriately. For example:
#include <iostream>
template <typename T>
struct formatter {
T const& value;
};
template <typename T>
formatter<T> format(T const& value) {
return formatter<T>{value};
}
template <typename T>
std::ostream& operator<< (std::ostream& out, formatter<T> const& v) {
return out << v.value;
}
std::ostream& operator<< (std::ostream& out, formatter<char> const& v) {
return out << int(v.value);
}
template <std::size_t N>
std::ostream& operator<< (std::ostream& out, formatter<char[N]> const& v) {
return out << '\'' << v.value << '\'';
}
int main() {
std::cout << "char=" << format('c') << " "
<< "int=" << format(17) << " "
<< "string=" << format("foo") << " "
<< "\n";
}
I guess you are working within generic context. So your basic problem is that you need static dispatch. The trigraph operator ? : does not provide this. it is evaluated at run time and will always invoke the same operator<<.
So you have two options:
use a helper class with partial specialization.
use static if. I.e.:
if constexpr (std::is_integral<decltype(x)>::value)
std::cout << static_cast<int>(x) << std::endl;
else
std::cout << x << std::endl;
The latter requires C++17.
This solution worked for me. It outputs the char as a number by using the output function together with template specialization and if constexpr:
#include <cstdint>
#include <iostream>
#include <string>
using namespace std::string_literals;
template <typename T> void output(std::ostream& out, T x)
{
if constexpr (std::is_integral<decltype(x)>::value) {
out << static_cast<int>(x);
} else {
out << x;
}
}
int main()
{
char x = 65;
uint8_t y = 66;
std::string z = "hi"s;
// output: A
std::cout << x << std::endl;
// output: 65
output(std::cout, x);
std::cout << std::endl;
// output: B
std::cout << y << std::endl;
// output: 66
output(std::cout, y);
std::cout << std::endl;
// output: "hi"
output(std::cout, z);
std::cout << std::endl;
return 0;
}
Thanks to Dietmar Kühl and Marcel for the helpful answers.

Constructing std::string using << operator

If we want to construct a complex string, say like this:
"I have 10 friends and 20 relations" (where 10 and 20 are values of some variables) we can do it like this:
std::ostringstream os;
os << "I have " << num_of_friends << " friends and " << num_of_relations << " relations";
std::string s = os.str();
But it is a bit too long. If in different methods in your code you need to construct compound strings many times you will have to always define an instance of std::ostringstream elsewhere.
Is there a shorter way of doing so just in one line?
I created some extra code for being able to do this:
struct OstringstreamWrapper
{
std::ostringstream os;
};
std::string ostream2string(std::basic_ostream<char> &b)
{
std::ostringstream os;
os << b;
return os.str();
}
#define CreateString(x) ostream2string(OstringstreamWrapper().os << x)
// Usage:
void foo(int num_of_friends, int num_of_relations)
{
const std::string s = CreateString("I have " << num_of_friends << " and " << num_of_relations << " relations");
}
But maybe there is simpler way in C++ 11 or in Boost?
#include <string>
#include <iostream>
#include <sstream>
template<typename T, typename... Ts>
std::string CreateString(T const& t, Ts const&... ts)
{
using expand = char[];
std::ostringstream oss;
oss << std::boolalpha << t;
(void)expand{'\0', (oss << ts, '\0')...};
return oss.str();
}
void foo(int num_of_friends, int num_of_relations)
{
std::string const s =
CreateString("I have ", num_of_friends, " and ", num_of_relations, " relations");
std::cout << s << std::endl;
}
int main()
{
foo(10, 20);
}
Online Demo
You could use Boost.Format:
#include <iostream>
#include <boost/format.hpp>
using boost::format;
int main()
{
std::cout << boost::format("I have %1% friends and %2% relations")
% num_of_friends % num_of_relations;
}

C++ Serializing a std::map to a file

I have a C++ STL map, which is a map of int and customType.
The customType is a struct, which has string and a list of string, How can i serialize this to a file.
sample struct:
struct customType{
string;
string;
int;
list<string>;
}
If you are not afraid of BOOST, try BOOST Serialize:
(template code, here can be some errors...)
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/list.hpp>
struct customType{
string string1;
string string2;
int i;
list<string> list;
// boost serialize
private:
friend class boost::serialization::access;
template <typename Archive> void serialize(Archive &ar, const unsigned int version) {
ar & string1;
ar & string2;
ar & i;
ar & list;
}
};
template <typename ClassTo>
int Save(const string fname, const ClassTo &c)
{
ofstream f(fname.c_str(), ios::binary);
if (f.fail()) return -1;
boost::archive::binary_oarchive oa(f);
oa << c;
return 0;
}
Usage:
Save< map<int, customType> >("test.map", yourMap);
A simple solution is to output each member on a line on its own, including all the strings in the list. Each record start with the key to the map, and ends with a special character or character sequence that can not be in the list. This way you can read one line at a time, and know the first line is the map key, the second line the first string in the structure and so on, and when you reach your special record-ending sequence you know the list is done and it's time for the next item in the map. This scheme makes the files generated readable, and editable if you need to edit them outside the program.
C++ doesn't have reflection capabilities like Java and others, so there's no 'automatic' way of doing that. You'll have to do all the work yourself: open the file, output each element in a loop, and close the file. Also there's no standard format for the file, you'd need to define one that meets your needs. Of course, there are libraries out there to help in this, but they aren't part of the language. Take a look at this question:
Is it possible to automatically serialize a C++ object?
Also take a look at:
http://s11n.net/
If you are asking this, then probably you already know that you cannot serialize this by means of:
file.write( (const char *) &mapOfCustom, sizeof( mapOfCustom ) );
The problem has to do with complex objects (and in C++, even a string variable is a complex object), i.e., those objects that are not self-contained. Actually, even simple serialization has problems, which range from platform compatibilty to even compiler compatibilty (different paddings, etc.).
One way to go is use a simple XML library such as tinyXML:
http://www.grinninglizard.com/tinyxml/
And write save to XML, and restore from XML procedures.
You can try this: cxx-prettyprint
Hi I wrote a standalone C11 header to achieve this. Your example
of a map of custom classes, I just added - to make sure it worked 8)
https://github.com/goblinhack/simple-c-plus-plus-serializer
#include "c_plus_plus_serializer.h"
class Custom {
public:
int a;
std::string b;
std::vector c;
friend std::ostream& operator<<(std::ostream &out,
Bits my)
{
out << bits(my.t.a) << bits(my.t.b) << bits(my.t.c);
return (out);
}
friend std::istream& operator>>(std::istream &in,
Bits my)
{
in >> bits(my.t.a) >> bits(my.t.b) >> bits(my.t.c);
return (in);
}
friend std::ostream& operator<<(std::ostream &out,
class Custom &my)
{
out << "a:" << my.a << " b:" << my.b;
out << " c:[" << my.c.size() << " elems]:";
for (auto v : my.c) {
out << v << " ";
}
out << std::endl;
return (out);
}
};
static void save_map_key_string_value_custom (const std::string filename)
{
std::cout << "save to " << filename << std::endl;
std::ofstream out(filename, std::ios::binary );
std::map< std::string, class Custom > m;
auto c1 = Custom();
c1.a = 1;
c1.b = "hello";
std::initializer_list L1 = {"vec-elem1", "vec-elem2"};
std::vector l1(L1);
c1.c = l1;
auto c2 = Custom();
c2.a = 2;
c2.b = "there";
std::initializer_list L2 = {"vec-elem3", "vec-elem4"};
std::vector l2(L2);
c2.c = l2;
m.insert(std::make_pair(std::string("key1"), c1));
m.insert(std::make_pair(std::string("key2"), c2));
out << bits(m);
}
static void load_map_key_string_value_custom (const std::string filename)
{
std::cout << "read from " << filename << std::endl;
std::ifstream in(filename);
std::map< std::string, class Custom > m;
in >> bits(m);
std::cout << std::endl;
std::cout << "m = " << m.size() << " list-elems { " << std::endl;
for (auto i : m) {
std::cout << " [" << i.first << "] = " << i.second;
}
std::cout << "}" << std::endl;
}
void map_custom_class_example (void)
{
std::cout << "map key string, value class" << std::endl;
std::cout << "============================" << std::endl;
save_map_key_string_value_custom(std::string("map_of_custom_class.bin"));
load_map_key_string_value_custom(std::string("map_of_custom_class.bin"));
std::cout << std::endl;
}
Output:
map key string, value class
============================
save to map_of_custom_class.bin
read from map_of_custom_class.bin
m = 2 list-elems {
[key1] = a:1 b:hello c:[2 elems]:vec-elem1 vec-elem2
[key2] = a:2 b:there c:[2 elems]:vec-elem3 vec-elem4
}
Let me know if this helps - or you find bugs. It's quite a simple serializer and really just a learning tool for me. Heavier weight approaches like Cereal might work for you better.

is there a good way to combine stream manipulators?

If I wanted to output a fixed width hex number with 4 digits on a stream, I would need to do something like this:
cout << "0x" << hex << setw(4) << setfill('0') << 0xABC;
which seems a bit long winded. Using a macro helps:
#define HEX(n) "0x" << hex << setw(n) << setfill('0')
cout << HEX(4) << 0xABC;
Is there a better way to combine the manipulators?
Avoid the macros when you can! They hide code, making things hard to debug, don't respect scope, etc.
You can use a simple function as KenE provided. If you want to get all fancy and flexible, then you can write your own manipulator:
#include <iostream>
#include <iomanip>
using namespace std;
ostream& hex4(ostream& out)
{
return out << "0x" << hex << setw(4) << setfill('0');
}
int main()
{
cout << hex4 << 123 << endl;
}
This makes it a little more general. The reason the function above can be used is because operator<< is already overloaded like this: ostream& operator<<(ostream&, ostream& (*funtion_ptr)(ostream&)). endl and some other manipulators are also implemented like this.
If you want to allow the number of digits to be specified at runtime, we can use a class:
#include <iostream>
#include <iomanip>
using namespace std;
struct formatted_hex
{
unsigned int n;
explicit formatted_hex(unsigned int in): n(in) {}
};
ostream& operator<<(ostream& out, const formatted_hex& fh)
{
return out << "0x" << hex << setw(fh.n) << setfill('0');
}
int main()
{
cout << formatted_hex(4) << 123 << endl;
}
If the size can be determined at compile-time, however, might as well just use a function template [thanks to Jon Purdy for this suggestion]:
template <unsigned int N>
ostream& formatted_hex(ostream& out)
{
return out << "0x" << hex << setw(N) << setfill('0');
}
int main()
{
cout << formatted_hex<4> << 123 << endl;
}
Why a macro - can't you use a function instead?
void write4dhex(ostream& strm, int n)
{
strm << "0x" << hex << setw(4) << setfill('0') << n;
}
In C++20 you'll be able to use std::format to make this much less verbose:
std::cout << std::format("0x{:04x}", 0xABC);
Output:
0x0abc
You can also easily reuse the format string by storing it in a constant.
In the meantime you can use the {fmt} library, std::format is based on. {fmt} also provides the print function that makes this even easier and more efficient (godbolt):
fmt::print("0x{:04x}", 0xABC);
Disclaimer: I'm the author of {fmt} and C++20 std::format.

C++: what benefits do string streams offer?

could any one tell me about some practical examples on using string streams in c++, i.e. inputing and outputing to a string stream using stream insertion and stream extraction operators?
You can use string streams to convert anything that implements operator << to a string:
#include <sstream>
template<typename T>
std::string toString(const T& t)
{
std::ostringstream stream;
stream << t;
return stream.str();
}
or even
template <typename U, typename T>
U convert(const T& t)
{
std::stringstream stream;
stream << t;
U u;
stream >> u;
return u;
}
I use them mostly as memory buffers, in creating messages:
if(someVector.size() > MAX_SIZE)
{
ostringstream buffer;
buffer << "Vector should not have " << someVector.size() << " eleements";
throw std::runtime_error(buffer.str());
}
or to construct complex strings:
std::string MyObject::GenerateDumpPath()
{
using namespace std;
std::ostringstream dumpPath;
// add the file name
dumpPath << "\\myobject."
<< setw(3) << setfill('0') << uniqueFileId
<< "." << boost::lexical_cast<std::string>(state)
<< "_" << ymd.year
<< "." << setw(2) << setfill('0') << ymd.month.as_number()
<< "." << ymd.day.as_number()
<< "_" << time.hours()
<< "." << time.minutes()
<< "." << time.seconds()
<< ".xml";
return dumpPath.str();
}
It is useful because it brings all the extensibility of std::streams to using character buffers (ostreams extensibility and locales support, buffer memory management is hidden and so on).
Another example I've seen was the error reporting in gsoap library, using dependency injection: soap_stream_fault takes an ostream& parameter to report error messages in.
If you want you can pass it std::cerr, std::cout or an std::ostringstream implementation (I use it with a std::ostringstream implementation).
They can be used anywhere a normal stream can be used.
So in situations where you were reading from a file you could potentially read from a string stream.
void compile(std::istream& str)
{
CPlusPlusLexer lexer(str);
CPlusPlusParser parser(lexer);
BackEnd backend(parser);
backend.compile();
}
int main()
{
std::fstream file("Plop.cpp");
compile(file);
std::stringstream test("#include <iostream>\n int main() { std::cout << \"H World\n\";}");
compile(test);
}
Besides advantages there is one point to carefully consider if you use gcc 4.3.1. I didn't checked preceding versions of gcc.