Is the C++ ostream at the start of a line? - c++

In C++, how do I detect if my std::ostream os is at the start of a line, in other words (I think) the most recent thing written to os is either os<<'\n' or os<<std::endl(), or else nothing has yet been written to os?
At first glance, this sounds unnecessary, because I can just keep track of the state myself. But a common scenario is the following, where keeping track would involve altering every os<<thing statement which could possibly be called from the try block, in a very unnatural way.
try {
do_something_which_writes_to(std::cout);
}
catch(const My_error&error) {
print_a_newline_if_necessary(std::cout);
std::cout<<error<<"\n";
}
(In reality, of course, we want to write error to std::cerr but that usually gets mixed in with std::cout unless one of them is redirected, so we still want to terminate the std::cout line before printing to std::cerr. I have deliberately simplified the example to avoid this distraction.)
You might imagine that os.tellp() would be the answer, but tellp() seems to work only on std::ofstream. For me at least, std::cout.tellp() always returns -1, indicating that it is not supported.

At least as I'm reading things, what you really want isn't the ability to get the position in the current line. Rather, what you really want is to be able to print something that is guaranteed to be at the start of a line--the current line if the immediately previous character was a newline (and, I'd guess also if it was a carriage return), but otherwise print a newline, then whatever follows.
Here's some code to do that:
#include <iostream>
class linebuf : public std::streambuf
{
std::streambuf* sbuf;
bool need_newline;
int sync() {
return sbuf->pubsync();
}
int overflow(int c) {
switch (c) {
case '\r':
case '\n': need_newline = false;
break;
case '\v':
if (need_newline) {
need_newline = false;
return sbuf->sputc('\n');
}
return c;
default:
need_newline = true;
break;
}
return sbuf->sputc(c);
}
public:
linebuf(std::streambuf* sbuf)
: sbuf(sbuf)
, need_newline(true)
{}
std::streambuf *buf() const { return sbuf; }
~linebuf() { sync(); }
};
class linestream : public std::ostream {
linebuf buf;
std::ostream &os;
public:
linestream(std::ostream& out)
: buf(out.rdbuf())
, std::ios(&buf)
, std::ostream(&buf)
, os(out)
{
out.rdbuf(&buf);
}
~linestream() { os.rdbuf(buf.buf()); }
};
void do_stuff() {
std::cout << "\vMore output\v";
}
int main() {
{
linestream temp(std::cout);
std::cout << "\noutput\n";
std::cout << "\voutput";
do_stuff();
std::cout << "\voutput\n";
std::cout << "\voutput\v";
}
std::cout << "\voutput\v";
}
Since it's almost never used otherwise, I've hijacked the vertical tab ('\v') to signify the special behavior.
To use it, you simply create a temporary object of type linestream (sorry, I'm too tired to think of a good name right now), passing it an ostream object that will get the new behavior when a \v gets written to it. When that temporary object goes out of scope, the stream will be restored to its original behavior (I doubt anybody uses \v often enough to care, but who knows maybe somebody care--it's mostly just a side effect of cleaning up after itself anyway).
In any case, the special behavior remains in place when do_stuff is called, so it's not just local to the function where the local linestream object is created, or anything like that--once it's created, the special behavior remains in effect until it's destroyed.
One other point though: when/if you mix output from cout and cerr, this won't help much. In particular, neither will be at all aware of the other's state. You'd probably much need some hooks into the output terminal (or something on that order) to be able to deal with that, since output redirection is normally handled by the OS, so inside the program there's no way to even guess whether data written to cout and cerr are going to the same place or not.

Related

Problems while opening a .dat file in c++

so basically I was trying to save a class inside a .dat file but in my code but it says this error No matching member function for call to 'open' but I put fstream header. I don't know if I'm writing something wrong. I use Xcode 10.
class memberinformation
{
string name; //name
long int phonenumber; // phone number
int memberid; // member id
public :
memberinformation()
{ name="not assigned" ;
phonenumber=0;
memberid=0;
}
int option3();
int option2();
int option1();
int option4();
};
void wrt_file() //file function
{
memberinformation k;
fstream f;
f.open ("information.dat",ios::app,ios::binary) //this is where I get the error.
f.write((char*)&k,sizeof(k));
}
You are lucky to have been stopped by a simple error. #Alex44 has already shown how to get rid of the error:
f.open ("information.dat",ios::app|ios::binary); //this is where I get the error.
But the following line is even worse:
f.write((char*)&k,sizeof(k));
because the compiler will not show any error, while the content of the string will not be saved in the file. std::string is not trivially copiable and because of that, the memberinformation class is not either. So you should not try to write it to a file as raw bytes.
You should instead write a serialization function that writes to a binary stream (just a possible serialization way):
phonenumber as a long int (no problem there)
memberid as an int (no problem there)
name.size as a size_t
name.data as name.size bytes
The other two answers have answered:
Why its not compiling.
Why its a bad idea to write binary objects.
I would suggest that you serialize the object via the standard C++ technique of using the stream operators. This makes writting/reading the objects trivial and usually makes debugging problems easy.
Using the format suggested by #serge-ballesta in his post:
class memberinformation
{
string name; //name
long int phonenumber; // phone number
int memberid; // member id
public :
// OLD STUFF GOES HERE
void swap(memberinformation& other) noexcept
{
using std::swap;
swap(name, other.name);
swap(phonenumber, other.phonenumber);
swap(memberid, other.memberid);
}
friend std::ostream& operator<<(std::ostream& str, memberinformation const& data)
{
return str << data.phonenumber << " "
<< data.memberid << " "
<< data.name.size() << " "
<< data.name << " ";
}
friend std::istream& operator<<(std::istream& str, memberinformation& data)
{
memberinformation tmp;
std::size_t nameSize
if (str >> tmp.phonenumber >> tmp.memberid >> nameSize) {
// All sizes were read correctly.
tmp.name.resize(nameSize);
if (str.ignore(1).read(&tmp.name[0], nameSize)) {
// ignored the space and read the name correctly.
// So now we update the "data" object
tmp.swap(data);
}
}
return str;
}
};
Now in your code:
int main()
{
memberinformation object;
std::cout << object;
std::cin >> object;
std::ofstream file("Data.dat");
file << object;
}
You miss a semicolon and you need to "bitwise or" your flags:
void wrt_file() //file function
{
memberinformation k;
fstream f;
f.open ("information.dat",ios::app|ios::binary); //this is where I get the error.
...
}
The answers above address your initial problem. I'm going to talk about two more.
First, you probably should f.close() at the end of your method. It may be perfectly fine to let it drop out of scope and clean up from there, but I personally think that's ugly, and I wouldn't count on it.
Second, I wouldn't store the data in binary unless there's a really good reason to do it. It won't be portable. Serge above suggests a serialization method. I'd consider an alternate approach. I'd write to the file in a human readable form such as JSON. Yes, it's a little more work, but...
-If you change your class, your old files will still be readable
-They are portable across environments
-You can actually look at them and readily understand what they contain
So Serge's suggestions above aren't horrible, but I'd pick a more modern serialization / deserialization style.
Note that your f.write won't work because your object contains other objects, you don't know how they work under the hood. That string, for instance, almost certainly can't be dumped the way you're trying to do it. Plus you aren't only dumping your data.
Also, you should printf the sizeof(k). You might find it interesting information. Try to account for every byte. You could printf the sizeof(k.name) to help you work some of it out.
I'm almost positive the information doing so would surprise you, but I haven't actually done it myself, because I would never try to raw memory copy C++ objects, and that's in effect what you're trying to do.

Extending std::cout

I want to extend the usage of std::cout to use my own console/cout wrapper class.
Ideally I would have 2 ostreams, one for regular printing and one that appends a new line.
std::ostream Write;
Write << "Hello, I am " << 99 << " years old.";
prints Hello, I am 99 years old.
std::ostream WriteLine;
WriteLine << "Hello, I am " << 99 << " years old.";
prints Hello, I am 99 years old.\n (an actual new line, not just it escaped)
I would then like to extend this to have error streams (Error and ErrorLine, for example) which prefix "ERROR: " before the message and prints in a different color.
I know I have to create my own streams to add in this functionality, and I followed C++ cout with prefix for prefixing std::cout which was almost what I wanted but not quite. I couldn't figure out how to add a new line to the end of the stream, and the prefix was unreliable, especially when I would do more than a single print statement.
I should also mention I don't want to use overloaded operators to achieve this effect, because I want to be able to daisy-chain things on.
What didn't work
If I did WriteLine >> "First"; then WriteLine << "Second"; I would get weird results like SecondFirst\n or Second\nFirst. My ideal output would be First\nSecond\n. I think it is due to not closing/flushing/resetting the stream properly, but nothing I tried got it to work reliably.
I could get it to work for a single statement, but as soon as I added another print statement, the things I tried to print would switch order, the post/pre fix wouldn't get added in the correct spot, or I would end up with garbage.
I don't care about wchars, because we will always only need a single byte for a single char. Also we will only be working on Windows 10.
This is what I have so far:
Console.h
#include <windows.h>
#include <iostream>
#include <sstream>
#include <string>
class Console {
using Writer = std::ostream;
Console() {}
static const char newline = '\n';
class error_stream: public std::streambuf {
public:
error_stream(std::streambuf* s) : sbuf(s) {}
~error_stream() { overflow('\0'); }
private:
typedef std::basic_string<char_type> string;
int_type overflow(int_type c) {
if(traits_type::eq_int_type(traits_type::eof(), c))
return traits_type::not_eof(c);
switch(c) {
case '\n':
case '\r':
{
SetColor(ConsoleColor::Red);
prefix = "ERROR: ";
buffer += c;
if(buffer.size() > 1)
sbuf->sputn(prefix.c_str(), prefix.size());
int_type rc = sbuf->sputn(buffer.c_str(), buffer.size());
buffer.clear();
SetColor(ConsoleColor::White);
return rc;
}
default:
buffer += c;
return c;
}
}
std::string prefix;
std::streambuf* sbuf;
string buffer;
};
class write_line_stream: public std::streambuf {
public:
write_line_stream(std::streambuf* s) : sbuf(s) {}
~write_line_stream() { overflow('\0'); }
private:
typedef std::basic_string<char_type> string;
int_type overflow(int_type c) {
if(traits_type::eq_int_type(traits_type::eof(), c))
return traits_type::not_eof(c);
switch(c) {
case '\n':
case '\r':
{
buffer += c;
int_type rc = sbuf->sputn(buffer.c_str(), buffer.size());
sbuf->sputn(&newline, 1);
buffer.clear();
return rc;
}
default:
buffer += c;
return c;
}
}
std::streambuf* sbuf;
string buffer;
};
static output_stream outputStream;
static error_stream errorStream;
static write_line_stream writeLineStream;
public:
static void Setup();
static Writer Write;
static Writer WriteLine;
static Writer Err;
};
Console.cpp
#include "Console.h"
Console::Writer Console::Write(nullptr);
Console::Writer Console::WriteLine(nullptr);
Console::Writer Console::Err(nullptr);
Console::error_stream Console::errorStream(std::cout.rdbuf());
Console::write_line_stream Console::writeLineStream(std::cout.rdbuf());
void Console::Setup() {
Write.rdbuf(std::cout.rdbuf());
Err.rdbuf(&errorStream);
WriteLine.rdbuf(&writeLineStream);
}
Main.cpp
int main() {
Console::Setup();
Console::Write << "First" << "Second";
Console::WriteLine << "Third";
Console::WriteLine << "Fourth";
Console::Write << "Fifth";
Console::Error << "Sixth";
Console::ErrorLine << "Seventh";
Console::WriteLine << "Eighth";
}
Which should give an output of
FirstSecondThird
Fourth
FifthERROR: SixthERROR: Seventh
Eighth
Press any key to continue...
Any help and/or suggestions are appreciated.
There are multiple concerns here which do require different approaches. Some of the description also seems that the actual desire isn't quite clear. The most problematic requirement is that a newline needs to be inserted apparently at the end of a statement. That's certainly doable but effectively does require a temporary being around.
Before going there I want to point out that most other languages offering a print-line(....) construct delineate what is going onto a line using a function call. There is no doubt where the newline goes. If C++ I/O would be created now I'd be quite certain that it would be based on a variadic (not vararg) function template. This way print something at the end of the expression is trivial. Using a suitable manipulator at the end of the line (although probably not std::endl but maybe a custom nl) would be an easy approach.
The basics of adding a newline at the end of expression would be using a destructor of a suitable temporary object to add it. The straight forward way would be something like this:
#include <iostream>
class newline_writer
: public std::ostream {
bool need_newline = true;
public:
newline_writer(std::streambuf* sbuf)
: std::ios(sbuf), std::ostream(sbuf) {
}
newline_writer(newline_writer&& other)
: newline_writer(other.rdbuf()) {
other.need_newline = false;
}
~newline_writer() { this->need_newline && *this << '\n'; }
};
newline_writer writeline() {
return newline_writer(std::cout.rdbuf());
}
int main() {
writeline() << "hello, " << "world";
}
This works reasonable nice. The notation in the question doesn't use a function call, though. So, instead of writing
writeline() << "hello";
it seems necessary to write
writeline << "hello";
instead and still add a newline. This complicates matters a bit: essentially, writeline now needs to be an object which somehow causes another object to jump into existence upon use so the latter can do its work in the destructor. Using a conversion won't work. However, overloading an output operator to return a suitable object does work, e.g.:
class writeliner {
std::streambuf* sbuf;
public:
writeliner(std::streambuf* sbuf): sbuf(sbuf) {}
template <typename T>
newline_writer operator<< (T&& value) {
newline_writer rc(sbuf);
rc << std::forward<T>(value);
return rc;
}
newline_writer operator<< (std::ostream& (*manip)(std::ostream&)) {
newline_writer rc(sbuf);
rc << manip;
return rc;
}
} writeline(std::cout.rdbuf());
int main() {
writeline << "hello" << "world";
writeline << std::endl;
}
The primary purpose of the overloaded shift operators is to create a suitable temporary object. They don't try to mess with the content of the character stream. Personally, I'd rather have the extra parenthesis than using this somewhat messy approach but it does work. What is kind of important is that the operator is also overloaded for manipulators, e.g., to allow the second statement with std::endl. Without the overload the type of endl can't be deduce.
The next bit is writing the prefix and mixing multiple streams. The important bit here is to realize that you'd want to one of two things:
Immediately write the characters to a common buffer. The buffer is most like just another stream buffer, e.g., the destination std::streambuf.
If the character should be buffered locally in separate stream buffers, the corresponding streams need be flushed in a timely manner, e.g., after each insertion (by setting the std::ios_base::unitbuf bit) or, latest, at the end of the expression, e.g., using an auxiliary class similar to the newline_writer.
Passing through the characters immediately is fairly straight forward. The only slight complication is to know when to write a prefix: upon the first non-newline, non-carriage-return return after a newline or a carriage return (other definitions are possibly and should be easily adaptable). The important aspect is that stream buffer doesn't really buffer but actually passes through the character to the underlying [shared] stream buffer:
class prefixbuf
: public std::streambuf {
std::string prefix;
bool need_prefix = true;
std::streambuf* sbuf;
int overflow(int c) {
if (c == std::char_traits<char>::eof()) {
return std::char_traits<char>::not_eof(c);
}
switch (c) {
case '\n':
case '\r':
need_prefix = true;
break;
default:
if (need_prefix) {
this->sbuf->sputn(this->prefix.c_str(), this->prefix.size());
need_prefix = false;
}
}
return this->sbuf->sputc(c);
}
int sync() {
return this->sbuf->pubsync();
}
public:
prefixbuf(std::string prefix, std::streambuf* sbuf)
: prefix(std::move(prefix)), sbuf(sbuf) {
}
};
The remaining business is to set up the relevant objects in the Console namespace. However, doing so is rather straight forward:
namespace Console {
prefixbuf errorPrefix("ERROR", std::cout.rdbuf());
std::ostream Write(std::cout.rdbuf());
writeliner WriteLine(std::cout.rdbuf());
std::ostream Error(&errorPrefix);
writeliner ErrorLine(&errorPrefix);
}
I except that the approach adding the newline creates a custom type I think that matches the original goes. I don't think the temporary object can be avoided to automatically create a newline at the end of a statement.
All that said, I think you should use C++ idioms and not try to replicate some other language in C++. The way to choose whether a line end in newline or not in C++ is to write, well, a newline where one should appear potentially by way of a suitable manipulator.

Tell `endl` not to flush

My program prints a large number of short lines to cout.
As a slightly contrived example, my lines look a little like this:
cout<<"The variable's value is: "<<variable<<endl;
I'd like the program to run fast and I do believe that endl is killing me because it initiates a buffer flush on cout every time it is used.
Now, some folks on the internet have said that I could do this instead:
cout<<"The variable's value is: "<<variable<<"\n";
But this does not seem like a good solution because endl abstracts the particular system-specific ways an end line might be specified, where as \n does not. This also seems like a poor solution because, should I need buffering in the future, I would then have to modify the whole code base.
Therefore, I ask, is there a way to disable the buffer-flushing aspect of endl?
EDIT
Further digging seems to indicate that both endl and \n respect the various ways an OS might choose to end it's lines. It also seems that the output stream detects if it's in a potentially interactive situation and buffers and flushes accordingly. Therefore: the problem may be solved by manually telling the output stream to perform aggressive buffering... if I can figure out how to do that.
endl abstracts the particular system-specific ways an end line might be specified, where as \n does not".
std::endl is defined to output '\n' followed by a flush. The correct abstraction of the system-specific newline thingy is just '\n'.
To prevent flushes, one just doesn't use std::endl. In addition, the standard output may be line-buffered if it is or may be connected to an interactive device, in this case the newline character will flush the stream. If that's an issue, use an ofstream connected to a named file. I think on Unix-like systems line buffering only happens when the standard output is a terminal.
endl flushes. If you don't want that behaviour, don't use endl. If you want to change your code easily, use your own manipulator:
inline std::ostream& myendl( std::ostream& os ){
os.put(os.widen('\n'));
return os;
}
That way you can easily change the behaviour of your myendl at one place.
According to http://en.cppreference.com/w/cpp/io/manip/endl
endl:: Inserts a endline character into the output sequence os and flushes it as if by calling os.put(os.widen('\n')) followed by os.flush().
So it appears you want to just write os.put(os.widen('\n')), which should, from this definition be safe and portable and correct, as well as meeting your primary needs.
There is std::nounitbuf which is documented to have some effect in this matter.
However, I didn't notice any difference. To bypass all of the ostream's ideas of when or when not to flush I tried this:
std::ostringstream oss;
// std::cout << std::nounitbuf;
for( int i = 0; i < 1000000; i++ ){
// std::cout << "Test " << "file" << '\n';
oss << "Test " << "file" << '\n';
}
std::cout << oss.str();
This improved execution time from ~33 sec to ~25csec.
IF your output goes to an xterm, your execution speed is severly limited by xterm's work to do scrolling etc. If you use a pipeline to filter out unnecessary lines you'll see a dramatic increase in speed, e.g.
./program | grep -v "The variable"
If flushing is the problem, you can implement a stream buffer that overrides the sync() member function to only flush to the external device if you specify so. It also obligates creating your own manipulators flush_on_endl and noflush_on_endl if you intend to change these preferences throughout the program.
#include <iostream>
static int disable() {
static int index(std::ios_base::xalloc());
return index;
}
class save_buffer
{
public:
save_buffer(std::ios& other)
: str(other), buf(other.rdbuf())
{ }
~save_buffer() { str.rdbuf(buf); }
private:
std::ios& str;
std::streambuf* buf;
};
class syncing_buffer_optional : public std::streambuf, private save_buffer
{
public:
syncing_buffer_optional(std::ostream& other)
: save_buffer(other),
buf(other.rdbuf()),
disable_sync(other.iword(disable()))
{ }
std::streambuf::int_type overflow(std::streambuf::int_type c)
{
buf->sputc(c);
return 0;
}
int sync()
{
return disable_sync? 0: buf->pubsync();
}
private:
std::streambuf* buf;
bool disable_sync;
};
std::ostream& flush_on_endl(std::ostream& os)
{
os.iword(disable()) = false;
return os;
}
std::ostream& noflush_on_endl(std::ostream& os)
{
os.iword(disable()) = true;
return os;
}
std::ostream& endl(std::ostream& os)
{
syncing_buffer_optional eb(os);
os.rdbuf(&eb);
return os << std::endl;
}
int main()
{
std::cout << noflush_on_endl << endl;
}

Is there a C++ equivalent to PHP's var_dump and die?

I know it's a simple question, but I'm looking to get my C++ groove on. I would imagine some sort of abort function could be used. But I don't think that'll return any text like die('hello'); would.
There is no "print a message, then exit" in C or C++. You can quite easily write your own function for die (or panic, as I prefer to call it), something like:
void die(const std::string& msg)
{
std::cerr << msg << std::endl;
exit(1);
}
Or, if you want to avoid the problems with creating a string, which may fail under low memory conditons:
void die(const char *msg)
...
(the rest should be the same as above). The drawback here is that you can't trivially concatenate strings, e.g. die(std::string("Could not open file ") + filename); won't work with const char *.
A function that does var_dump is much harder, as there is no direct way to actually fetch the content of a variable of a an arbitrary type, or an array, in C++. You could perhaps do something like this:
template<typename T>
void var_dump(const T& var)
{
std::cout << var << endl;
}
template<typename T, size_t N>
void var_dump(const T (&var)[N])
{
for(i : var)
{
std::cout << i << endl;
}
}
The latter is a bit like this PHP code: foreach($var as $i) echo $i . "\n";. And I may have the syntax slightly wrong, not sure.
I wouldn’t recommend calling std::abort, std::exit or anything like that.
It’s brute-force, and the semantics for proper cleanup are very complicated. You are essentially leaving (at least parts of) your program behind in a very messy state.
A much better way in C++ is to throw an exception which you then catch in main:
#include <stdexcept>
struct fatal_error : std::logic_error {
fatal_error(char const* message) : std::logic_error(message) { }
};
int main() try {
… the normal program flow starts here
} catch (fatal_error const& e) {
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
}
Then, instead of die, you’d simply say throw fatal_error("Something went wrong.");.
Assuming you need these equivalents for debugging purpose...
instead of die() you may invoke the debugger;
instead of var_export() you may inspect your variables content with the debugger.

Unit testing a functions whose purposes is side effects

How would you unit test do_int_to_string_conversion?
#include <string>
#include <iostream>
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) {
case 1:
s="1";
break;
case 2:
s="2";
break;
default:
s ="Nix";
}
}
int main(int argc, char** argv){
std::string little_s;
do_int_to_string_conversion(1, little_s);
do_int_to_string_conversion(2, little_s);
do_int_to_string_conversion(3, little_s);
}
Instead of worrying about how to test the function as it stands, I'd redesign the function to work a bit more sensibly, and test the re-designed version instead.
Right now, the function seems to have three separate (and only slightly related) responsibilities: do a conversion, modify an externally supplied string, and write some data to a stream. The stream to which it writes (std::cout) is also hard-coded -- a problem waiting to happen (e.g., conversion to a GUI environment is likely to be non-trivial).
I'd start by 1) splitting it up into logical functions, and 2) supplying the stream as a parameter.
std::string convert_int(int val) {
switch (val) {
case 1: return "1";
case 2: return "2";
default: return "Nix";
}
}
std::ostream &write_string(std::ostream &os, std::string const &s) {
return os << s;
}
I haven't included anything to (specifically) modify an externally supplied string -- obviously you can assign the return value from convert_int as you see fit, and the value of the string that was passed in wasn't being used anyway.
Truthfully, write_string is a good candidate to be eliminated entirely, but since you had that basic kind of capability, we'll retain it for the moment. Testing these is relatively simple -- for convert_int, we look at the string it returns, and compare to what we expect. For write_string, we can pass a stringstream instead of a normal ostream -- then we can use .str() to get that result as a string, and (again) compare to what we expect.
I assume this is just an example. Why can't you assert on the value of little_s after each call?
do_int_to_string_conversion(1, little_s);
assert_are_equal("1", little_s);
If you really need to ensure that the output has been written, you need to break your dependency on std::cout and use another std::ostream during tests.
This might be as simple as a global variable:
#if PRODUCTION
std::ostream my_output = std::cout;
#else
std::ostream my_output = std::ostringstream;
#endif
void setup()
{
my_output = std::ostringstream;
}
void print_hello()
{
my_output << "hello";
}
void test_hello_was_printed()
{
print_hello();
ASSERT("hello" == my_output.str());
}
Or something similar to that effect.
I'd change do_int_to_string_conversion so that it does just one thing (convert the in to a string).
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) { ... }
}
This has no side effects, so you can write a simple unit test that verifies the output (s).
If I needed a function that printed the result of the conversion, I'd put that in a separate function, and I'd parameterize the output stream.
void output_int(int i, ostream &stream) {
std::string s;
do_int_to_string_conversion(i, s);
stream << s;
}
To unit test that, I'd pass in a std::stringstream object and check the result.
You can use something like Expect to pass it some input and verify that its output is what it should be.