I found the below code through Google. It almost does what I want it to do, except it doesn't provide a way to indicate the precision like '%.*f' does in C-type format strings. Also, it doesn't provide anything further than 5 decimal places. Am I going to have to stick with C strings and snprintf?
#include <string>
#include <sstream>
#include <iostream>
template <class T>
std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))
{
std::ostringstream oss;
oss << f << t;
return oss.str();
}
int main()
{
std::cout<<to_string<double>(3.1415926535897931, std::dec)<<std::endl;
return 0;
}
You want to use the std::setprecision manipulator:
int main()
{
std::cout << std::setprecision(9) << to_string<long>(3.1415926535897931, std::dec)
<< '\n';
return 0;
}
C++ wouldn't be successful if it couldn't do something C could.
You need to check out manipulators.
If you want C-style formatting (which I do prefer, it's more terse), check out Boost.Format.
Have you looked at Boost::format?
Edit: It's not entirely clear what you want. If you just want to write to a string, with formatting, you can use normal manipulators on a stringstream. If you want to use printf-style formatting strings, but retain type-safety, Boost::format can/will do that.
Taking the almost-correct answer (note that std::dec is redundant in this simple case):
int main()
{
std::cout << std::setprecision(9) << std::dec << 3.1415926535897931 << std::endl;
return 0;
}
However, if you wanted the to_string function to behave as desired, that's a bit more difficult. You'd need to pass setprecision(9) to the to_string<T> function, and it doesn't accept arguments of that type. You'd want a templated version:
template <class T, class F>
std::string to_string(T t, F f)
{
std::ostringstream oss;
oss << f << t;
return oss.str();
}
int main()
{
std::cout << to_string<double>(3.1415926535897931, std::setprecision(9)) << std::endl;
return 0;
}
This works because you really didn't need std::dec in to_string. But if you needed to pass more manipulators, the simple solution is to add template <class T, class F1, class F2> std::string to_string(T t, F1 f1, F2 f2) etcetera. Technically this doesn't scale very well, but it's going to be so rare that you probably don't need it at all.
Related
Let's say I have a C++ function
void foo(std::string str) {
std::cout << str << "\n";
}
Now, in the equivalent Java I could call the function with a combination of various types and it would automatically be concatenated, for example:
foo("test " + intValue + " " + stringValue + "...");
This does not work in C++, but is there a way in modern C++ to achieve the same? The only solution I have found is to create a stringstream variable and do the concatenation there. However, that seems like a lot of overhead for such a common use case.
You can wrap std::stringstream in a function and use that:
#include <string>
#include <sstream>
void foo(std::string){}
template<typename...Args>
std::string concat(Args&&...args){
std::stringstream ss;
(ss << ... << args);
return ss.str();
}
int main(){
int intValue=12;
std::string stringValue="hello";
foo(concat("test ",intValue," ",stringValue,"..."));
}
std::string supports concatenation by +, but primitives types do not. So, you can wrap them in std::to_string but that is not so nice.
Allowing "hello"+5 is too dangerous because "hello" is one easy step from being const char* which would trigger pointer arithmetic instead.
From C++20, there is std::format.
You could create a string builder class that wrapps the boilerplate of the std::stringstream a bit:
#include <iostream>
#include <string>
#include <sstream>
struct Builder {
std::stringstream s;
template<typename T>
Builder(const T& x) {
s << x;
}
template<typename T>
friend Builder&& operator+(Builder&& b, const T& val) {
b.s << val;
return std::move(b);
}
operator std::string() const {
return s.str();
}
};
Call site could use it like this:
foo(Builder("test ") + 3 + " " + "stringValue" + "...");
Live example here.
You can achieve the same by using to_string() on integer values.
foo("test " + to_string(intValue) + " " + stringValue + "...");
I programmed a log class that logs messages in color in the terminal. I want it to be able to log anything
I give it to log. I guess templates are the way to go. But can't i use auto as an argument type, then check if it is a string and if not call the tostring method of the object ?
Since c++20 you can use auto and overload for the other types you want to handle differently.
void log(auto test) {
std::cout << std::to_string(test) << std::endl;
}
void log(const std::string &str) {
std::cout << "str: " << str << std::endl;
}
int main()
{
log(std::string("test"));
log(10);
}
You could indeed use templates, then just add a template specialization for std::string that doesn't invoke std::to_string
#include <iostream>
#include <string>
template <typename T>
void ToLog(T t)
{
std::cout << std::to_string(t) << '\n';
}
template <>
void ToLog<std::string>(std::string str)
{
std::cout << str << '\n';
}
int main()
{
ToLog(5);
ToLog(12.0);
ToLog(std::string("hello"));
return 0;
}
Output
5
12.000000
hello
No, auto needs to determine the type of a variable in compile time, which can't be done until C++20. If you are using C++ standard, either you use templates, preprocessor macros (as some logging libraries do) or directly some to_string function before passing the argument.
But, as said, with C++20 it can be done, and behaves like a template.
You might find this question useful.
Suppose I have a function from string to string, such as for example:
string identity(string text) {
return text;
}
How can I print the function applied to input to output, avoiding explicit variables, input and output handling? Something like interact in Haskell.
int main() {
std::interact(identity);
}
This would really cut down obvious code, and let the algoritmh and the logic stand out instead.
Example usage would be:
$./enhanced_cat
Example
Example
$
You can easily write such a thing yourself using std::function. Example:
#include <string>
#include <iostream>
#include <functional>
std::string identity(std::string const& text) {
return text;
}
void interact(std::function<std::string(std::string const&)> f)
{
std::string input;
std::getline(std::cin, input);
std::cout << f(input);
}
int main()
{
interact(identity);
}
But that certainly doesn't look like idiomatic C++. Even though C++ supports functional programming to a certain extent, it's not a functional programming language, and you should not try to write Haskell in C++.
template<class F>
struct interacter_t {
F f;
void operator()( std::istream& is = std::cin, std::ostream& os = std::cout ) {
std::string in;
while( getline( is, in ) ) {
os << f(std::move(in)) << '\n';
}
}
};
template<class F>
interacter_t<std::decay_t<F>> interact( F&& f ) {
return {std::forward<F>(f)};
}
then:
int main() {
auto io = interact(identity);
std::cout << "Start:\n";
io();
std::cout << "End.\n";
}
I added the separate invocation to creation of the interactor object.
You can do it on one line:
std::cout << "Start:\n";
interact(identity)();
std::cout << "End.\n";
or you can modify interact to run the interactor_t instead of returning it. I personally like that distinction: creation and execution are different things.
live example.
This version reads everything from the input stream until it ends. Reading less than that is easy, just replace the body of operator().
You could roll your own interact, something like the below. (Note: probably won't actually compile as is.)
void interact(string (*function)(string))
{
string input;
getline(cin, input);
cout << function(input) << endl;
}
Consider the following code.
int id = 666;
stringstream stream(stringstream::in | stringstream::out);
stream << "Object " << id << " active.";
file.write(stream.str());
It combines all the values preceded by << in a string quite nicely. I would love to discover a shorter, easier to use version with less code duplication. Furthermore, the above code is just an example, and the command should accept arbitrary combinations of variables and strings. Ideally something like:
int id = 666;
WRITE("Object ", id, " active.");
Is this possible in C++ in a portable way, even with Boost.Preprocessor, inlined functions and all the bag of tricks.
You can accomplish this without type checking using a macro:
//filewrite.h
#define WRITE(first, second, third) \
{\
stringstream stream(stringstream::in | stringstream::out);\
stream << first << second << third;\
file.write(stream.str());\
}
Or, cleaner, with a template function:
template<typename T1, typename T2, typename T3>
void WRITE(T1 const& first, T2 const& second, T3 const& third, fstream& file)
{
stringstream stream(stringstream::in | stringstream::out);
stream << first << second << third;
file.write(stream.str());
}
If you really don't want type-checking don't use C++, it's a statically-typed language!
If you just mean you want it to work for any type, either use a macro (eurgh) or use variadic templates, something like https://gitlab.com/redistd/redistd/blob/master/include/redi/printers.h which supports:
#include <redi/printers.h>
using redi::println;
int main()
{
int id = 666;
println("Object ", id, " active."); // write arguments to stdout
}
The println function takes any number of arguments and was shamelessly stolen from inspired by some example code from Howard Hinnant.
It would be quite easy to adapt that to write to an fstream instead of std::cout e.g. by adding
inline
void
fprintln()
{ file << std::endl; }
template<typename T0, typename... T>
inline
void
fprintln(const T0& t0, const T&... t)
{
print_one(file, t0);
fprintln(t...);
}
Then:
fprintln("Object ", id, " active."); // write arguments to 'file'
You don't need (nor want) macros. This is what templates were designed
for:
template <typename T>
void
write( std::string const& prefix, T const& value, std::string const& suffix )
{
std::ostringstream fmt;
fmt << prefix << value << suffix;
file.write( fmt.str() );
}
On the other hand, why bother? Why not just let the client code use the
idiomatic:
file << prefix << value << suffix;
I wish I could just print contents of a set/vector/map by using cout << . It doesn't seem so difficult for the stl designers to implement : Assuming that << is defined for T, << for a container could just iterate through the elements and print them using ofstream << .
Is there an easy way to print them that I dont know of?
If not, Is there an easy solution? I have read at places that extending stl classes is a bad idea. Is that so, and why?
how about defining an something like an overloaded print function?
EDIT:
I am looking for a recursive function which can handle containers of containers of ...
I agree that different people would like different formats, but something overridable is better than nothing
Probably the easiest way to output an STL container is
std::copy(cont.begin(), cont.end(),
std::ostream_iterator<Type>(std::cout, " "));
where Type is the type of the elements of cont (e.g. if cont is of type std::vector<int> then Type must be int).
Of course instead of std::cout you can use any ostream.
In C++11 you can use range-based for:
for (auto& i: container) cout << i << " ";
cout << endl;
The easiest eay to dump a container is probably just using std::copy(). For example I typically use something like this:
template <typename C>
std::string format(C const& c) {
std::ostringstream out;
out << "[";
if (!c.empty()) {
std::copy(c.begin(), --c.end(),
std::ostream_iterator<typename C::value_type>(out, ", "));
out << c.back();
}
out << "]";
return out.str();
}
Yes, this doesn't always work but works for my needs. This actually shows one of the problems why there is no output for containers in the standard library: there are many different ways how containers can be formatted. To make matters worse, the formatted output should be readable where thing become real fun. All of this is doable but I'm not aware of a corresponding proposal.
It doesn't seem so difficult for the stl designers to implement : Assuming that << is defined for T, << for a container could just iterate through the elements and print them using ofstream << .
Of course it is not hard for them. However, ask yourself: Does the format of the output make sense for every client? The standard library is about reuse and genericity. Coupling containers with some arbitrary output formatting rules makes them less generic for the sake of only some.
The recommended solution therefore is to provide your own operator<<(std::ostream &, T) and/or to take other generic algorithms, as found in e.g. <algorithms>.
Are you looking something like this?
#include <iostream>
#include <set>
template <typename T>
std::ostream& operator<< (std::ostream& os, const std::set<T>& s)
{
for( auto i: s ) {
os << i << " ";
}
return os;
}
Then you just may use it this way:
std::set<int> my_set = { 11, 12, 13 };
std::cout << my_set << std::endl;
Using Template template parameter makes it easy, in order to make it working for each collection you need both template<class, class...> class X and class... Args as template parameters:
template<class T, template<class, class...> class X, class... Args>
std::ostream& operator <<(std::ostream& os, const X<T, Args...>& objs) {
os << "{";
bool commoFlag = false;
for (auto const& obj : objs) {
os << (commoFlag ? ", " : "") << obj;
commoFlag = true;
}
os << "}";
return os;
}
vector<float> f_vec{ 1.3f , 5.134f, 5.78f };
list<char> c_lst{ 'F','O', 'M', 'S', 'A' };
set<int> i_st{ 17,14, -70 };
std::cout << f_vec << std::endl;
std::cout << c_lst << std::endl;
std::cout << i_st << std::endl;
output:
{1.3, 5.134, 5.78}
{F, O, M, S, A}
{-70, 14, 17}