Setting width in C++ output stream
You can create an object that overloads operator<<
and contains an iostream
object that will automatically call setw
internally. For instance:
class formatted_output
{
private:
int width;
ostream& stream_obj;
public:
formatted_output(ostream& obj, int w): width(w), stream_obj(obj) {}
template<typename T>
formatted_output& operator<<(const T& output)
{
stream_obj << setw(width) << output;
return *this;
}
formatted_output& operator<<(ostream& (*func)(ostream&))
{
func(stream_obj);
return *this;
}
};
You can now call it like the following:
formatted_output field_output(cout, 10);
field_output << x << y << endl;
Setting width of text mentioned inside printf
If I understand your question correctly, you want to sneak in the tidy output behind the scenes without "intruding" on the existing code.
First, replace printf
with a custom name. Then you can write a wrapper around it. If your compiler understands variadic macros, this may just be a macro. Otherwise you can roll your own printf
-like function with variadic arguments and vprintf
.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if VAR_ARG_MACRO_AVAILABLE
#define tprintf(fmt, ...) do { \
printf("%.*s", 24 - strlen(fmt), \
" "); \
printf(fmt, __VA_ARGS__); \
} while (0)
#else
#include <stdarg.h>
int tprintf(const char *fmt, ...)
{
va_list va;
int n;
va_start(va, fmt);
n = 24 - strlen(fmt);
if (n < 0) n = 0;
printf("%.*s", n, " ");
n += vprintf(fmt, va);
va_end(va);
return n;
}
#endif
int main()
{
tprintf("a = %d\n", 2);
tprintf("alpha = %d\n", 21);
tprintf("alphabetical = %d\n", 112);
return 0;
}
The macro solution relies on variable names of less than about twenty characters. Otherwise, the absolute value of the field width will be taken, which may mangle your layout.
Using strlen
(and not, for example, strchr(fmt, '=')
), is an approximation and will not work if you have format specifiers of different lengths, e.g. %zu
, %llu
and so on.
Width and setfill('-') in cpp
Here are two other ways to produce this line:
std::cout << "-------------------------------------\n";
std::setfill
+ std::setw
:
#include <iomanip>
std::cout << std::setfill('-') << std::setw(38) << '\n';
Using a std::string
:
#include <string>
std::cout << std::string(37, '-') << '\n';
Demo
How to clear width when outputting from a stream, after using std::setw?
Remember that the input operator >>
stops reading at whitespace.
Use e.g. std::getline
to get the remainder of the string:
std::stringstream ss("123ABCDEF1And then the rest of the string");
ss >> std::setw(3) >> nId
>> std::setw(6) >> sLabel
>> std::setw(1) >> bFlag;
std::getline(ss, sLeftovers);
Default positioning of fill characters for streams
setfill
is defined in [std.manip] as
template<class charT, class traits>
void f(basic_ios<charT, traits>& str, charT c) {
// set fill character
str.fill(c);
}
so we need to look at what happens to an ostream
's fill
function and that is detailed in [ostream.formatted.reqmts]/3 as
If a formatted output function of a stream os determines padding, it does so as follows. Given a
charT
character sequence seq wherecharT
is the character type of the stream, if the length of seq is less thanos.width()
, then enough copies ofos.fill()
are added to this sequence as necessary to pad to a width ofos.width()
characters. If(os.flags() & ios_base::adjustfield) == ios_base::left
istrue
, the fill characters are placed after the character sequence; otherwise, they are placed before the character sequence.
So unless left
is specified, the fill character come first. By default, left
is not a set flag for cout
and this is detail in Table 122: basic_ios::init() effects [tab:basic.ios.cons]
Using the iomanip directive
Unfortunately, no. You must use setw()
before almost every output operation. The problem is that operator<<
effectively calls setw(0)
after the output, thus you need to set width again. See here for a full list of operations that reset field width.
Note: setw
is just a wrapper around width()
, so using the latter won't help.
Is there a way to set the width of each field at one shot instead of setting every time using streamio?
Iostreams are fickle, and you cannot really rely on the various formatting flags to persist. However, you can use <iomanip>
to write things a bit more concisely:
#include <iomanip>
using namespace std;
o << setw(2) << setfill('0') << x;
Modifiers like o << hex
and o << uppercase
usually persist, while precision and field width modifiers don't. Not sure about the fill character.
printf field width : bytes or chars?
It will result in five bytes being output. And five chars. In ISO C, there is no distinction between chars and bytes. Bytes are not necessarily 8 bits, instead being defined as the width of a char.
The ISO term for an 8-bit value is an octet.
Your "niño" string is actually five characters wide in terms of the C environment (sans the null terminator, of course). If only four symbols show up on your terminal, that's almost certainly a function of the terminal, not C's output functions.
I'm not saying a C implementation couldn't handle Unicode. It could quite easily do UTF-32 if CHAR_BITS was defined as 32. UTF-8 would be harder since it's a variable length encoding but there are ways around almost any problem :-)
Based on your update, it seems like you might have a problem. However, I'm not seeing your described behaviour in my setup with the same locale settings. In my case, I'm getting the same output in those last two printf
statements.
If your setup is just stopping output after the first |
(I assume that's what you mean by abort but, if you meant the whole program aborts, that's much more serious), I would raise the issue with GNU (try your particular distributions bug procedures first). You've done all the important work such as producing a minimal test case so someone should even be happy to run that against the latest version if your distribution doesn't quite get there (most don't).
As an aside, I'm not sure what you meant by checking the od
output. On my system, I get:
pax> ./qq | od -t cx1
0000000 | n i 303 261 o | \n | n i 303 261 | \n
7c 20 6e 69 c3 b1 6f 7c 0a 7c 6e 69 c3 b1 7c 0a
0000020 | A 261 B | \n | A 261 B | \n
7c 41 b1 42 7c 0a 7c 41 b1 42 7c 0a
0000034
so you can see the output stream contains the UTF-8, meaning that it's the terminal program which must interpret this. C/glibc isn't modifying the output at all, so maybe I just misunderstood what you were trying to say.
Although I've just realised you may be saying that your od
output has only the starting bar on that line as well (unlike mine which appears to not have the problem), meaning that it is something wrong within C/glibc, not something wrong with the terminal silently dropping the characters (in all honesty, I would expect the terminal to drop either the whole line or just the offending character (i.e., output |A
) - the fact that you're just getting |
seems to preclude a terminal problem). Please clarify that.
Related Topics
How to Define a Move Constructor
How to Install Tensorflow on Windows
Sfinae and Partial Class Template Specializations
How to Do a C++ Style Compile-Time Assertion to Determine MAChine's Endianness
Member Initializer Does Not Name a Non-Static Data Member or Base Class
Template Class Member Function Only Specialization
When Do You Prefer Using Std::List<T> Instead of Std::Vector<T>
Purpose of Explicit Default Constructors
How to Create a Thread-Safe Singleton Pattern in Windows
What Data Structure, Exactly, Are Deques in C++
Why Does Not a Template Template Parameter Allow 'Typename' After the Parameter List
Google Protocol Buffers Compare
C++ Bool Returns 0 1 Instead of True False
How to Write an Adl-Enabled Trailing Return Type, or Noexcept Specification