Reputation: 911
When I want to special characters in a string I should use "\":
std::string text("item \t new_item\n")
But, if I print this string, obviously, it will print:
item new_item
Is there a way set std::cout to print all special characters:
item \t new_item \n
Upvotes: 2
Views: 19367
Reputation: 89965
There is no built-in way to do this. You will need to escape characters manually. For example, in C, it'd be something like:
for (const char* p = text; *p != '\0'; ++p)
{
int c = (unsigned char) *p;
switch (c)
{
case '\\':
printf("\\\\");
break;
case '\n':
printf("\\n");
break;
case '\r':
printf("\\r");
break;
case '\t':
printf("\\t");
break;
// TODO: Add other C character escapes here. See:
// <https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences>
default:
if (isprint(c))
{
putchar(c);
}
else
{
printf("\\x%X", c);
}
break;
}
}
(Note that I wrote the above answer while the question was still tagged with C, and I used printf
because I find it to be simpler (especially for demonstrative purposes) than going through C++'s iostream formatting mechanism.)
Upvotes: 5
Reputation: 145259
The C++ standard library has no direct support for escaping strings.
You can implement it fairly directly, but this runs into three problems:
There are non-standard escapes such as \e
for ASCII's escape character (code 27), supported by e.g. g++.
The number of bits per char
(CHAR_BIT
from <limits.h>
), and hence the necessary number of digits in a numerical escape, is system-dependent.
Whether a character is printable or not, i.e. whether it needs escaping, depends on the locale. And this gets further complicated by the number of competing indicators of current locale: the C level global locale, the C++ level global locale, or e.g. the locale imbued in cout
?
With some hardwired choices about that, implementation code can look like this:
#include <stdio.h> // ::sprintf
#include <ctype.h> // ::isprint
#include <string> // std::string
#include <unordered_map> // std::unordered_map
namespace my{
using std::string;
using std::unordered_map;
auto string_from( char const ch )
-> string
{ return string( 1, ch ); } // Note: "string{1,ch}" is something else.
auto is_printable( char const ch )
-> bool
{ return !!::isprint( static_cast<unsigned char>( ch ) ); }
auto escaped( char const ch )
-> string
{
static unordered_map<char, string> const escapes =
{
{ '\a', "\\a" }, // 7, ^G, alert (bell)
{ '\b', "\\b" }, // 8, ^H, backspace
{ '\t', "\\t" }, // 9, ^I, tab
{ '\n', "\\n" }, // 10, ^J, newline / linefeed
{ '\v', "\\v" }, // 11, ^K, vertical tab
{ '\f', "\\f" }, // 12, ^L, formfeed
{ '\r', "\\r" }, // 13, ^M, carriage return
{ 27, "\\e" }, // 27, ^[, escape (NON-STANDARD)
{ '\\', "\\\\" } // backslash
};
auto const it = escapes.find( ch );
if( it != escapes.end() )
{
return it->second;
}
else if( is_printable( ch ) )
{
return string_from( ch );
}
else
{
int const code = static_cast<unsigned char>( ch );
char buf[] = "\\xDDDD";
sprintf( buf + 2, "%04X", code );
return buf;
}
}
auto escaped( string const& s )
-> string
{
string result;
for( char const ch: s )
{
result += escaped( ch );
}
return result;
}
} // namespace my
#include <iostream>
#include <locale.h>
using namespace std;
auto main()
-> int
{
using my::escaped;
auto const text = "item \t \xC7\x81new_item\n"s;
setlocale( LC_ALL, "" );
cout << escaped( text ) << '\n';
}
Upvotes: 1
Reputation: 9888
\t
and \n
will print a tab(4 white spaces) and a new line respectively.
If you want to print \t
and \n
as output. You have to add an extra \
as prefix before \t
and \n
.
std::string text("item \\t new_item \\n")
Upvotes: 6