Capturing and formatting cout - c++

How can I capture the input of cout?
Example:
if I enter:
std::cout<<"Some normal text here" << fout <<"Test %, %", 1, 2<< "works 100% fine."<<std::endl
then it would print:
"Some normal text here Test 1, 2 works 100% fine."
The 100% isn't formatted because of the << operator. Only things directly after the fout would be formatted until it met the << operator.
Can I do that?
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
std::ostream& fout (std::ostream& I)
{
//Some how format my text here.. Then return it as the ostream.
return I;
}
int main(int argc, char* argv[])
{
std::cout<< fout << "Test %", 1 << "Other stuff 20%.";
//So Anything after fout<< should be stolen and formatted then given back to cout.. Other stuff 20% isn't formatted because of the <<.
}
I know it seems silly but I really want to know how it's done. I saw that boost does something similar by doing Format("%20") % SomeVar
But I want to figure out how to do it with the insertion operator and using the comma operator. Any ideas or anything similar?

You would need to define a new type for your << and , operators to uniquely work on.
Something like this.
struct fout
{
// To establish the formatting string (returns *this)
fout& operator << ( const std::string &format_string );
// To insert data into the formatted string (returns *this)
template < typename T >
fout& operator , ( const T &data );
// To produce a type that can be sent to std::cout, etc.
operator std::string ();
};
This would allow code like this:
cout << "Normal text " << (fout() << "Test %, %", 1, 2 ) << "works";
// ^^ A fout object is being constructed here.
If you don't like those parenthesis, rename the struct and create a single instance called fout.

Related

How to read strings with spaces from a ifstream using istream_iterator?

I want to read a text file, line by line, using istream_iterator, but it fails when there is a white space in the line.
This is a sample code:
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>
int main(int argc, char** argv)
{
if (argc != 2) {
std::cout << argv[0] << " <file-name>" << std::endl;
return 10;
}
std::ifstream _in(argv[1]);
if (!_in.good()) {
std::cout << "error reading " << argv[1] << std::endl;
return 20;
}
_in.unsetf(std::ios_base::skipws);
std::istream_iterator<std::string> _ite(_in);
std::istream_iterator<std::string> _end;
std::string _s(*_ite);
std::cout << "line read " << _s << std::endl;
}
For example, in this input file:
1;3.14;bla bla
-3;0.923;let me go
The first string read is 1;3.14;bla
Is there a way to do it, or should I give up and use getline?
When a std::string is read it reads until the first space character is found. What qualifies as a space character is defined by the stream’s std::locale, more precisely its std::ctype<char> facet. You can create a std::ctype<char> facet which considers only ’\n’ as a space, create a std::locale object containing that facet, imbue() the stream with the corresponding std::locale and it should work.
No. Do not give up. Use the C++ approach. Although I will also use std::getline, I think it is rather C-Style. And therefor I will wrap this functrion in a proxy class.
I find your idea good, to use a std::istream_iterator. This is the "more modern" C++ way of doing things. And the big advantage is that you can use the istream_iterator in algorithms.
The only problem to solve is, to implement the abstract model of a "line" into a class. And as I will show below that is fairly easy.
Using a proxy class is the standard approach and you will find a lot of examples here on SO doing exactly that.
Please see:
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <sstream>
#include <ios>
std::istringstream testFile{R"(Line1Word1 Line1Word2 Line1Word3
Line2Word1 Line2Word2
Line3Word1 Line3Word2 Line3Word3 Line3Word4
Line4Word1 Line4Word2 Line4Word3
)"};
struct Line // ! This is a proxy for the input_iterator and output iterator!
{
// Input function. Read on line of text file and split it in columns
friend std::istream& operator>>(std::istream& is, Line& line) {
return std::getline(is, line.lineTemp );
}
// Output function.
friend std::ostream& operator<<(std::ostream& os, const Line& line) {
return os << line.lineTemp;
}
// cast to needed result
operator std::string() const { return lineTemp; }
// Temporary Local storage for line
std::string lineTemp{};
};
int main()
{
std::cout << "\n\nTest 1. Read all lines into a vector:\n";
std::vector<std::string> allLines {std::istream_iterator<Line>(testFile),std::istream_iterator<Line>() };
std::copy(allLines.begin(), allLines.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
std::cout << "\n\nTest 2: Display fist 2 in file\n";
testFile.clear(); testFile.seekg(0,std::ios::beg);
std::copy_n(std::istream_iterator<Line>(testFile),2,std::ostream_iterator<std::string>(std::cout, "\n"));
testFile.clear(); testFile.seekg(0,std::ios::beg);
std::cout << "\n\nTest 3: Number of lines in File\n"
<< std::distance(std::istream_iterator<Line>(testFile),std::istream_iterator<Line>());
std::cout << "\n\nTest 4: Use iterator separately\n";
testFile.clear(); testFile.seekg(0,std::ios::beg);
// Define the iterator
std::istream_iterator<Line> lineIterator(testFile);
// Dereference iterator
std::cout << *lineIterator << "\n";
return 0;
}

How can I convert the output from a ostream_iterator to a string?

I am implementing a toString method in C++ primarily using the ostream_iterator.
std::ostream_iterator<int> output(std::cout, " ");
After printing to the console, however, I wish to return the output of the ostream_iterator as a string. Is this direct conversion possible?
Yes, just replace cout with stringstream and you can create string from it.
std::stringstream ss; // #include <sstream>
std::ostream_iterator<int> output(ss, " ");
std::string s(ss.str());
Is this direct conversion possible?
I think, no, because ostream_iterator is used to send data to stream one way, so if the destination is std::cout you cannot use ostream_iterator to get data back.
But you can use some other destination, e.g. ostringstream object, and then use it for both output through cout and use again as you like.
Consider simple example:
std::stringstream buff;
std::ostream_iterator<int> output(buff, " ");
std::istringstream str("10 3 ABC 7 1");
// just copy only first integer values from str (stop on the first non-integer)
std::copy(std::istream_iterator<int>(str), std::istream_iterator<int>(), output);
// output as a string to std output
std::cout << buff.str() << std::endl;
// do something else
buff.seekp(0, std::ios::end);
std::cout << "String size is " << buff.tellp() << std::endl;
If you want a string-like object that uses the std::ostream interface rather than the STL container interface, that’s std::stringstream, or the deprecated std::strstream The closest thing to a generic wrapper that turns anything that can be serialized with cout << into a std::string would be to write to a std::stringstream and then read the data back out. This will end up making at least one expensive copy, however. Here’s an implementation:
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
using std::cout;
using std::endl;
using isit = std::istream_iterator<char>;
template <typename T> std::string to_string(const T& x)
// Must be able to print a T with std::ostream::operator<<.
{
std::stringstream buffer;
buffer << x;
const isit begin(buffer); // The start of the stream object.
static const isit end; // Default object is the end-of-stream iterator.
return std::string( begin, end );
}
int main(void)
{
const std::string output_string = to_string("Testing:") + " " +
to_string(1) + ", " + to_string(2ULL) + ", " + to_string(3.0) +
to_string('.');
cout << output_string << endl;
return EXIT_SUCCESS;
}
You can use a std::ostream_iterator<char> to write to a std::stringstream, rather than <<, and then a std::istream_iterator<char> as shown to copy from that to a string.
You can write data from a std::istream to a std::string with a std::istream_iterator. Sort of. The formatting can be wonky.
If you want to read data from a std::string using an iterator, its iterator type is std::string::iterator and an iterator to the front of the string is s.begin(), like other STL containers.
If you just have a bunch of data stored in memory that you want to send to both an output iterator and a string, you can use one of its other constructors.

stream does not append new line character

I call the function write in a loop. I need to append several lines.
I pass
std::fstream file(filename);
to
write(info, &file);
The following code doesn't append new line character, or at least Notepad++ does not display it.(i get just a whitespace) :
void IO::write(const std::string& name, std::iostream* stream)
{
(*stream) << "usr" << name << " === " << "\n";
}
What is wrong? How to append the new line to the text file?
To elaborate on my rather harsh comment, there is nothing wrong with your newline, but...
...use the correct types...
#include <iostream>
#include <fstream>
// ...
std::ofstream file( filename );
// ...
...and if you want to print info to the stream, just do it instead of going through some function...
// ...
file << "usr" << info << " === " << "\n";
// ...
...if you really want to make it a function, at least use references and the proper types...
void IO::write( std::ostream & stream, const std::string & name )
{
stream << "usr" << name << " === \n";
}
// ...
IO::write( file, info );
// ...
...but the "traditional" way of doing output in C++ is to overload the operator<< for the class in question, and have the implementation for printing an instance sit right alongside the class member implementations instead of going through C-style functions...
class MyClass
{
// ...
friend std::ostream & operator<<( std::ostream & stream, const MyClass & obj );
// ...
};
std::ostream & operator<<( std::ostream & stream, const MyClass & obj )
{
stream << "usr" << obj.name << " ===\n";
return stream;
}
// ...
MyClass mine;
file << "Hello\n" << mine << 42 << "\n";
I would also recommend that you use std::endl rather than "\n". std::endl flushs the file, "\n" does not.
After file is flushed (std::endl used or file closed). Try different editors to be sure, but end of line should be visible.
Jean

handle empty string case extracting a string from std::istream

Using the following code to extract a string from a std::istream :
#include <sstream>
#include <iostream>
void parse(std::istream & is, std::string & out)
{
is >> out;
}
int main(int argc, char** argv)
{
if (argc>1)
{
std::istringstream is(argv[1]);
std::string out("__INIT__");
std::cout << "good:" << is.good() << " fail:"<< is.fail() << " eof:"<< is.eof() << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
parse(is, out);
std::cout << "good:" << is.good() << " fail:"<< is.fail() << " eof:"<< is.eof() << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
}
}
With a non-empty string the output looks like :
$./a.out "TEST"
good:1 fail:0 eof:0 in_avail:4 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:TEST
With an empty string the output looks like :
$./a.out ""
good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:1 eof:1 in_avail:0 value:__INIT__
Instead of this, I would expect :
good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:
The operator>> does not extract an empty string. The result is the same with an empty string or and no data.
Any suggestion to handle this situation will be appreciated.
If you're using your parse function exclusively for extraction, you can simply make it out to be a check for an empty buffer. If there is, simply clear the string:
void parse(std::istream& is, std::string& out)
{
if (is.eof() || is.peek() == std::char_traits<char>::eof())
{
out.clear();
return;
}
is >> out;
}
There is no difference between an empty value and no value.
That's just your assumption, and it's not really true.
If you attempt to extract a string, it is expected that there are characters to extract. Before characters are available, it is impossible to perform any extraction, let alone one that results in extraction to a particular object.
This is entirely expected behaviour.
I guess your confusion stems from your prior check for argc > 1, but although the shell pretended ./myProgram "" had some argument, as far as your stream is concerned there is nothing in that argument.
If you wish to make your own handling for it, simply stick an if condition on is.fail() after the read.
#include <sstream>
#include <iostream>
int main(int argc, char** argv)
{
if (argc>1)
{
std::istringstream is(argv[1]);
std::string out;
is >> out;
if (is.fail()) {
std::cout << "Well, you gave me an argument, but it was empty, biatch!\n";
}
}
}
Don't bother checking is.eof(); it'll be set when you reached the end of input whether it contained any characters or not.

Quoting strings in C++

In Pascal Lazarus/Delphi, we have a function QuotedStr() that wraps any string within single quotes.
Here's an example of my current C++ code:
//I need to quote tblCustomers
pqxx::result r = txn.exec( "Select * from \"tblCustomers\" ");
Another one:
//I need to quote cCustomerName
std::cout << "Name: " << r[a]["\"cCustomerName\""];
Similar to the above, I have to frequently double-quote strings. Typing this in is kind of slowing me down. Is there a standard function I can use for this?
BTW, I develop using Ubuntu/Windows with Code::Blocks. The technique used must be compatible across both platforms. If there's no function, this means that I must write one.
C++14 added std::quoted which does exactly that, and more actually: it takes care of escaping quotes and backslashes in output streams, and of unescaping them in input streams. It is efficient, in that it does not create a new string, it's really a IO manipulator. (So you don't get a string, as you'd like.)
#include <iostream>
#include <iomanip>
#include <sstream>
int main()
{
std::string in = "\\Hello \"Wörld\"\\\n";
std::stringstream ss;
ss << std::quoted(in);
std::string out;
ss >> std::quoted(out);
std::cout << '{' << in << "}\n"
<< '{' << ss.str() << "}\n"
<< '{' << out << "}\n";
}
gives
{\Hello "Wörld"\
}
{"\\Hello \"Wörld\"\\
"}
{\Hello "Wörld"\
}
As described in its proposal, it was really designed for round-tripping of strings.
Using C++11 you can create user defined literals like this:
#include <iostream>
#include <string>
#include <cstddef>
// Define user defined literal "_quoted" operator.
std::string operator"" _quoted(const char* text, std::size_t len) {
return "\"" + std::string(text, len) + "\"";
}
int main() {
std::cout << "tblCustomers"_quoted << std::endl;
std::cout << "cCustomerName"_quoted << std::endl;
}
Output:
"tblCustomers"
"cCustomerName"
You can even define the operator with a shorter name if you want, e.g.:
std::string operator"" _q(const char* text, std::size_t len) { /* ... */ }
// ...
std::cout << "tblCustomers"_q << std::endl;
More info on user-defined literals
String str = "tblCustomers";
str = "'" + str + "'";
See more options here
No standard function, unless you count std::basic_string::operator+(), but writing it is trivial.
I'm somewhat confused by what's slowing you down - quoted( "cCustomerName" ) is more characters, no? :>
You could use your own placeholder character to stand for the quote, some ASCII symbol that will never be used, and replace it with " just before you output the strings.
#include <iostream>
#include <string>
struct quoted
{
const char * _text;
quoted( const char * text ) : _text(text) {}
operator std::string () const
{
std::string quotedStr = "\"";
quotedStr += _text;
quotedStr += "\"";
return quotedStr;
}
};
std::ostream & operator<< ( std::ostream & ostr, const quoted & q )
{
ostr << "\"" << q._text << "\"";
return ostr;
}
int main ( int argc, char * argv[] )
{
std::string strq = quoted( "tblCustomers" );
std::cout << strq << std::endl;
std::cout << quoted( "cCustomerName" ) << std::endl;
return 0;
}
With this you get what you want.
What about using some C function and backslash to escape the quotes?
Like sprintf_s:
#define BUF_SIZE 100
void execute_prog() {
//Strings that will be predicted by quotes
string param1 = "C:\\users\\foo\\input file.txt", string param2 = "output.txt";
//Char array with any buffer size
char command[BUF_SIZE];
//Concating my prog call in the C string.
//sprintf_s requires a buffer size for security reasons
sprintf_s(command, BUF_SIZE, "program.exe \"%s\" \"%s\"", param1.c_str(),
param2.c_str());
system(command);
}
Resulting string is:
program.exe "C:\users\foo\input file.txt" "output.txt"
Here is the documentation.