给定计数字符串(字符数组或类似std::string
的包装器),是否有一种“正确”的方法可以在C或C ++中转义和/或取消它,这样“特殊”字符(如空字符)变成C风格转义,“普通”字符保持原样?
或者我必须手工完成吗?
答案 0 :(得分:10)
这是一个处理单个字符的函数:
/*
** Does not generate hex character constants.
** Always generates triple-digit octal constants.
** Always generates escapes in preference to octal.
** Escape question mark to ensure no trigraphs are generated by repetitive use.
** Handling of 0x80..0xFF is locale-dependent (might be octal, might be literal).
*/
void chr_cstrlit(unsigned char u, char *buffer, size_t buflen)
{
if (buflen < 2)
*buffer = '\0';
else if (isprint(u) && u != '\'' && u != '\"' && u != '\\' && u != '\?')
sprintf(buffer, "%c", u);
else if (buflen < 3)
*buffer = '\0';
else
{
switch (u)
{
case '\a': strcpy(buffer, "\\a"); break;
case '\b': strcpy(buffer, "\\b"); break;
case '\f': strcpy(buffer, "\\f"); break;
case '\n': strcpy(buffer, "\\n"); break;
case '\r': strcpy(buffer, "\\r"); break;
case '\t': strcpy(buffer, "\\t"); break;
case '\v': strcpy(buffer, "\\v"); break;
case '\\': strcpy(buffer, "\\\\"); break;
case '\'': strcpy(buffer, "\\'"); break;
case '\"': strcpy(buffer, "\\\""); break;
case '\?': strcpy(buffer, "\\\?"); break;
default:
if (buflen < 5)
*buffer = '\0';
else
sprintf(buffer, "\\%03o", u);
break;
}
}
}
这是处理以null结尾的字符串的代码(使用上面的函数):
void str_cstrlit(const char *str, char *buffer, size_t buflen)
{
unsigned char u;
size_t len;
while ((u = (unsigned char)*str++) != '\0')
{
chr_cstrlit(u, buffer, buflen);
if ((len = strlen(buffer)) == 0)
return;
buffer += len;
buflen -= len;
}
}
答案 1 :(得分:1)
而不是分配一个新缓冲区来包含转义字符串,而不是在我将其写入流时转义字符串。
以下函数可以实现可读和简洁的代码。
struct Escaped
{
const char* str;
friend inline std::ostream& operator<<(std::ostream& os, const Escaped& e)
{
for (const char* char_p = e.str; *char_p != '\0'; char_p++)
{
switch (*char_p)
{
case '\a': os << "\\a"; break;
case '\b': os << "\\b"; break;
case '\f': os << "\\f"; break;
case '\n': os << "\\n"; break;
case '\r': os << "\\r"; break;
case '\t': os << "\\t"; break;
case '\v': os << "\\v"; break;
case '\\': os << "\\\\"; break;
case '\'': os << "\\'"; break;
case '\"': os << "\\\""; break;
case '\?': os << "\\\?"; break;
default: os << *char_p;
}
}
return os;
}
};
int main()
{
std::cout << Escaped{ "foo\n\tbar" } << std::endl;
}
可生产
foo\n bar
答案 2 :(得分:0)
//convert '\n' literal to escape code for '\n'
#define STRING "hello\\\\\nworld\\n"
char *p = malloc(strlen(STRING) + 1);
strcpy(p,STRING);
char *s = p;
char c;
for(;*p;++p)
{
while(*p == '\\')
{
++p;
switch(*p){
case '\\':
c = '\\';
goto gstat;
case 'n':
c = '\n';
default:
{
gstat:
strcpy(p-1,p);
*(p-1) = c;
}
break;
}
}
}
printf("%s",s);