using namespace std;
string str{ "text" };
stringstream ss{ str };
cout.rdbuf(ss.rdbuf());
cout.flush(); //cout<<endl;
This code is expected to print text,but showing nothing.
I associate ss to stdout then flush it,but I don't know why it didn't work even if I refer to many illustration.
cout<<rdbuf(ss);
this is OK but where's the different? : (
I think you misunderstood this concept. The line
cout.rdbuf(ss.rdbuf());
sets the pointer to the buffer. It redirects cout to ss and not to console. If you write into cout it will be written to ss.
I hope this clears it for you
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::streambuf *backup;
backup = std::cout.rdbuf();
std::stringstream ss;
std::cout.rdbuf(ss.rdbuf());
std::cout << "Test" << std::endl;
std::cout.rdbuf(backup);
std::cout << ss.rdbuf();
return 0;
}
In the example code I create a copy of the current pointer of cout's buffer. Next I redirect the cout to ss. When I write into cout it is written into ss's buffer. Next I redirect cout back to console and print the content of ss.
If you want to manipulate the buffer you need somethink like
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
int main() {
std::stringstream ss{ "test" };
std::stringbuf *pbuf = ss.rdbuf();
char buffer[80];
pbuf->sgetn (buffer,80);
std::streambuf *pbuf2 = std::cout.rdbuf();
pbuf2->sputn (buffer, std::strlen(buffer));
return 0;
}
As a complement to #Thomas Sablik answer, here is a code example for printing "text" by redirecting streams:
std::stringstream ss;
ss.basic_ios<char>::rdbuf(std::cout.rdbuf());
ss << "text";
std::cout.flush();
If you want to copy the content of ss's streambuf to std::cout, you can use inserter directly:
std::string str{ "text" };
std::stringstream ss{ str };
std::cout << ss.rdbuf();
std::cout.flush();
http://wordaligned.org/articles/cpp-streambufs
Related
How can I store the output from cout into a variable of string or character type?
I have written following code but it doesn't work:
#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
string n;
n = (cout<<"\nHello world");
cout<<n;
return 0;
}
#include <sstream>
std::ostringstream a;
a << "Hello, world!";
std::string b = a.str(); // Or better, `std::move(a).str()`.
std::cout << b;
Other answers have shown you how to capture formatted output using a std::(o)stringstream object directly. But, if for some reason, you really need to capture the output of std::cout, then you can temporarily redirect std::cout to use a std::ostringstream's buffer, eg:
#include <iostream>
#include <sstream>
using namespace std;
int main(){
ostringstream oss;
auto cout_buff = cout.rdbuf(oss.rdbuf());
cout << "\nHello world";
cout.rdbuf(cout_buff);
string n = oss.str();
cout << n;
return 0;
}
Online Demo
Of course there's a way! But you have to use a different kind of stream:
std::ostringstream ss;
ss << "\nHello world";
std::string result = ss.str();
Also, in C++20, you can simply use std::format:
std::string n = std::format("Hello {}! I have {} cats\n", "world", 3);
// n == "Hello world! I have 3 cats\n"
My problem is really petty, but nevertheless I have not found any answer by asking google or by asking peers. The problem can be shown by the following code:
std::ostringstream oss("I am a ");
oss << "donkey";
std::cout << oss.str();
Expected Output: "I am a donkey"
Actual Output: "donkey"
What happens here? Is the initial string the stringstream had to begin with been discarded?
You have to add std::ios_base::ate to the constructor, otherwise it would overwrite from the beginning:
#include <iostream>
#include <sstream>
using namespace std;
int main() {
std::ostringstream oss("I am a ", std::ios_base::ate);
oss << "donkey";
std::cout << oss.str();
return 0;
}
https://ideone.com/IIfOkB
More information: https://en.cppreference.com/w/cpp/io/basic_ostringstream
Example: https://en.cppreference.com/w/cpp/io/basic_ostringstream/str
The next code returns an empty string in ss:
#include <string>
#include <iostream>
#include <sstream>
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
ss.basic_ios<char>::rdbuf(oss.rdbuf());
std::cout << ss.str() << "\n";
return 0;
}
How can I return from ss the text introduced in oss? I'm mainly interested in converting std::ostringstream into std::stringstream.
You could make use of the protected std::streambuf::swap member function that exchanges the contents of the stream buffer with those of another
To get access to it, you'll need a derived class:
#include <iostream>
#include <sstream>
struct swapper : std::streambuf {
using std::streambuf::streambuf;
void swap(std::streambuf& rhs) { // public proxy for protected swap
std::streambuf::swap(rhs);
}
};
// casting
void swapbuf(std::ostream& a, std::ostream& b) {
static_cast<swapper*>(a.rdbuf())->swap(*b.rdbuf());
}
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
swapbuf(oss, ss);
std::cout << "ss: " << ss.str() << "\n"; // prints Text
}
Following comments from #NathanOliver, I decided to convert std::ostringstream into std::stringstream by using str():
#include <string>
#include <iostream>
#include <sstream>
int main () {
std::ostringstream oss;
oss << "Text";
std::stringstream ss;
ss << oss.str();
std::cout << ss.str() << "\n";
return 0;
}
I want to create some text file in C++. For example: I will run a loop from 1 to 5 and create the following files:
1.txt
2.txt
3.txt
4.txt
5.txt
is it possible? I have made a sample code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
main()
{
FILE *fp;
int i;
for(i=1;i<=5;i++)
{
//fp=fopen("%d.txt","r",i); //what will go here??
}
}
I am confused about what I will write inside the loop. how can I create those files?
char i;
char fileName[] = "0.txt";
for(i='1';i<='5';i++)
{
fileName[0]=i;
fp=fopen(fileName,"r"); //what will go here??
//...
}
You can use sprintf if this is too simple for your case;
Since you tag c++, I think fstream string is the thing to use.
A simple c++ example
#include <fstream>
#include <string>
using namespace std;
int main(){
string base(".txt");
for(int i=1;i<=5;++i){
ofstream(to_string(i)+base);// to_string() need c++11
}
}
If you still don't have to_string (you don't have c++11 or your compiler just don't have this) you can use this simple version for now. (better put this in your own namespace)
#include <string>
#include <sstream>
std::string to_string(int i){
std::stringstream s;
s << i;
return s.str();
}
You can use a std::stringstream to compose the file name before passing it to the std::ofstream constructor as a std::string.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
int main()
{
std::cout << "How many files do you want to create? ";
int n;
std::cin >> n;
std::cout << "How many digits do you want to display? ";
int n_digits;
std::cin >> n_digits; // i.e. zeroes == 3 -> 001.txt
std::cout << "Enter a common prefix for all the files: ";
std::string prefix;
std::cin.ignore();
std::getline(std::cin, prefix); // i.e. prefix == "file" -> file001.txt
std::string ext(".txt");
for ( int i = 1; i <= n; ++i )
{ // use a stringstream to create a file names like: prefix001.txt
std::stringstream ss;
ss << prefix << std::setfill('0') << std::setw(n_digits) << i << ext;
// open the file. If not c++11 use ss.str().c_str() instead
std::ofstream file( ss.str() );
if ( !file )
{
std::cerr << "Error: failed to create file " << ss.str() << '\n';
break;
}
// write something to the newly created file
file << "This is file: " << ss.str() << "\n\nHello!\n";
if ( !file )
{
std::cerr << "Error: failed to write to file " << ss.str() << '\n';
break;
}
}
}
#include <iostream>
#include <fstream>
int main(void)
{
std::ofstream out; // you must call out.close() inside loop to be able to open another file for writting otherwise you'll get only the first one "a.txt"
std::string sFileName;
for(char c('a'); c < 'f'; c++)
{
sFileName = c;
sFileName += ".txt";
out.open(sFileName.c_str(), std::ios::out);
// std::ofstream out(sFileName.c_str(), std::ios::out); // here you are not obliged to call out.close() because the first out is not the very second and so on...
out.close(); // very important if you use the same ofstream to open another file
}
std::cout << std::endl;
return 0;
}
*** to be able to use one ostream object in opening many files you must close the precedent file to be able to open the next otherwise it fails trying creating the next one.
ostringstream ss;
ss << "(1,2)\n" << "(1,3)\n" << "(1,4)\n" ;
cout << ss.str();
should print the following:
(1,2)
(1,3)
(1,4)
How could i reverse the output by line so that it prints:
(1,4)
(1,3)
(1,2)
You could use a custom std::streambuf which internally keeps a stack of std::strings and puts them together upon using a str() member. For example:
#include <iostream>
#include <numeric>
#include <streambuf>
#include <string>
#include <vector>
class stackbuf
: public std::streambuf
{
std::vector<std::string> d_lines;
int overflow(int c) {
if (c != std::char_traits<char>::eof()) {
this->d_lines.back().push_back(c);
if (c == '\n') {
this->d_lines.push_back(std::string());
}
}
return std::char_traits<char>::not_eof(c);
}
public:
stackbuf(): d_lines(1) {}
std::string str() const {
return std::accumulate(this->d_lines.rbegin(),
this->d_lines.rend(),
std::string());
}
};
int main()
{
stackbuf sbuf;
std::ostream out(&sbuf);
out << "(1, 2)\n(1, 3)\n(1, 4)\n";
std::cout << sbuf.str();
}
For a real-world application you should, obviously, set up a buffer in the stream buffer to improve the performance. You may also want to create a custom stream directly initializing the stream's stream buffer.
Using your original code with C++98:
ostringstream ss;
ss << "(1,2)\n" << "(1,3)\n" << "(1,4)\n" ;
cout << ss.str();
//assign a string to the contents of the ostringstream:
string rawlines = ss.str();
//now create an input stringstream with the value of the rawlines
istringstream iss(rawlines);
string temp;//just a temporary object used for storage
vector<string> lines;//this is where your lines will be held
//now iterate over the stream and store the contents into the vector `lines`:
while(getline(iss, temp)) {
lines.push_back(temp);
}
//now reverse the contents:
reverse(lines.begin(), lines.end());
//see what's inside:
for (vector<string>::const_iterator it = lines.begin(); it != lines.end(); ++it) {
cout << *it << endl;
}
This will print:
(1,4)
(1,3)
(1,2)
As desired
NOTE: This strips the newlines from the the original string.
And, this requires:
//for `getline`:
#include <cstdlib>
//for `reverse`:
#include <algorithm>
//for `string`:
#include <string>
//for `vector`:
#include <vector>
You can use reverse iterators:
std::ostringstream ss{ "(1,2)\n(1,3)\n(1,4)\n" };
std::string str = ss.str();
std::copy( str.rbegin(), str.rend(),
std::ostream_iterator<std::string>{std::cout, "\n"} );
This code will require:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <sstream>
and basic C++11 support.
This would be the classic way, best leveraging the standard C++ library.
#include <iostream>
#include <sstream>
#include <stack>
#include <string>
using namespace std;
int main(int argv, char* arv[])
{
ostringstream oss;
oss << "(1,2)\n" << "(1,3)\n" << "(1,4)\n" ;
cout << oss.str() << "----------\n";
// Reverse lines
// Fill an istringstream with buffer contents of the ostringstream
istringstream iss(oss.str());
stack<string> stk;
while (iss) {
string s;
if (!getline(iss, s)) break; // Read a line
s += '\n'; // Put back newline stripped by readline
stk.push(s); // Push line to stack
}
oss.clear(); // Clear state of the ostringstream
oss.str(""); // Clear contents of the ostringstream for reuse
while (!stk.empty()) {
string s;
s = stk.top(); // Get top of stack
oss << s; // Output it to the ostringstream
stk.pop(); // Pop and throw away top of stack
}
cout << oss.str();
return 0;
}