Выключение строки С++
Какой самый простой способ конвертировать С++ std::string в другой std::string, который содержит все непечатаемые символы?
Например, для строки из двух символов [0x61,0x01] строка результата может быть "a\x01" или "a% 01".
Ответы
Ответ 1
Взгляните на библиотеку Boost String Algorithm Library. Вы можете использовать свой is_print классификатор (вместе с его перегрузкой оператором), чтобы выбрать непечатаемые символы и find_format() функции могут заменить их любым форматированием, которое вы хотите.
#include <iostream>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
struct character_escaper
{
template<typename FindResultT>
std::string operator()(const FindResultT& Match) const
{
std::string s;
for (typename FindResultT::const_iterator i = Match.begin();
i != Match.end();
i++) {
s += str(boost::format("\\x%02x") % static_cast<int>(*i));
}
return s;
}
};
int main (int argc, char **argv)
{
std::string s("a\x01");
boost::find_format_all(s, boost::token_finder(!boost::is_print()), character_escaper());
std::cout << s << std::endl;
return 0;
}
Ответ 2
Предполагается, что набор символов выполнения является надмножеством ASCII, а CHAR_BIT равно 8. Для того, чтобы OutIter передавал back_inserter (например, к вектору <char> или другой строке), ostream_iterator или любому другому подходящему выходному итератору.
template<class OutIter>
OutIter write_escaped(std::string const& s, OutIter out) {
*out++ = '"';
for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) {
unsigned char c = *i;
if (' ' <= c and c <= '~' and c != '\\' and c != '"') {
*out++ = c;
}
else {
*out++ = '\\';
switch(c) {
case '"': *out++ = '"'; break;
case '\\': *out++ = '\\'; break;
case '\t': *out++ = 't'; break;
case '\r': *out++ = 'r'; break;
case '\n': *out++ = 'n'; break;
default:
char const* const hexdig = "0123456789ABCDEF";
*out++ = 'x';
*out++ = hexdig[c >> 4];
*out++ = hexdig[c & 0xF];
}
}
}
*out++ = '"';
return out;
}
Ответ 3
Один человек непечатаемый символ - другой многобайтовый символ. Поэтому вам нужно будет определить кодировку, прежде чем вы сможете определить, какие байты сопоставляются с какими символами, а какие из них непечатаемы.
Ответ 4
Вы видели статью о том, как Сгенерировать escape-строку с использованием Spirit.Karma?
Ответ 5
Предполагая, что "самый простой способ" означает короткий и все же легко понятный, хотя он не зависит от каких-либо других ресурсов (например, libs), я бы пошел следующим образом:
#include <cctype>
#include <sstream>
// s is our escaped output string
std::string s = "";
// loop through all characters
for(char c : your_string)
{
// check if a given character is printable
if(isprint(c))
s += c;
else
{
std::stringstream stream;
// if the character is not printable
// we'll convert it to a hex string using a stringstream
// note that since char is signed we have to cast it to unsigned first
stream << std::hex << (unsigned int)(unsigned char)(c);
std::string code = stream.str();
s += std::string("\\x")+(code.size()<2?"0":"")+code;
// alternatively for URL encodings:
//s += std::string("%")+(code.size()<2?"0":"")+code;
}
}