2010-12-07 326 views
0

如何在C(++)中将"A\r\nB\tC\nD"转换为"A\\r\\nB\\tC\\nD"将特殊字符(如 n)转换为其转义版本

对于纯C和纯C++解决方案,理想情况下只使用标准库和红利upvote。

+0

什么是保存的原始字符串?例如字符(即0x0D和0x0A)或字符序列(即\,后面跟着n)是否是`\ r` /`\ n`? – Nim 2010-12-07 14:11:20

回答

3

当然,与wchar_tstd::stringstd::wstring,如果你使用的是宽字符串替换char

std::string input(/* ... */); 
std::string output; 
for(std::string::const_iterator it = input.begin(); it != input.end(); ++it) 
{ 
    char currentValue = *it; 
    switch (currentValue) 
    { 
    case L'\t': 
     output.append("\\t"); 
     break; 
    case L'\\': 
     output.append("\\\\"); 
     break; 
    //.... etc. 
    default: 
     output.push_back(currentValue); 
    } 
} 

你可以做到这一点在C,但它的将是更困难的,因为你不知道提前缓冲区大小(虽然你可以使原字符串的大小2倍的最坏情况下的猜测) 。即

//Disclaimer; it's been a while since I've written pure C, so this may 
//have a bug or two. 
const char * input = // ...; 
size_t inputLen = strlen(input); 
char * output = malloc(inputLen * 2); 
const char * inputPtr = input; 
char * outputPtr = output; 
do 
{ 
    char currentValue = *inputPtr; 
    switch (currentValue) 
    { 
    case L'\t': 
     *outputPtr++ = '\\'; 
     *outputPtr = 't'; 
     break; 
    case L'\\': 
     *outputPtr++ = '\\'; 
     *outputPtr = '\\'; 
     break; 
    //.... etc. 
    default: 
     *outputPtr = currentValue; 
    } 
} while (++outputPtr, *inputPtr++); 

(记住添加错误处理到C版本之类的malloc故障;))

+0

这就是为什么我希望有一些图书馆功能;但是谢谢。 – mbq 2010-12-07 14:38:03

+0

@mbq:然后只使用C++版本;我一直在使用它多年,并知道它没有错误:)(地狱,如果你在C++中,那么你**使用`std :: string`,对吧?:)) – 2010-12-07 14:41:52

+0

@ Bill当然,除非因为与其他代码交互而不得不混淆C,而且问题很简单,比如strlen。 – mbq 2010-12-07 15:37:02

1

我怀疑是否有任何标准库函数直接执行此操作。最有效的方法是简单地遍历输入缓冲区字符,有条件地复制到输出缓冲区,用一些特殊的状态机逻辑来处理'\'等。

我确定有办法做这与strchr()等的各种组合有关,但在一般情况下可能效率较低。

0

我将创建的32个const char*文字,一个用于每个控制码(ASCII 0到ASCII的查找表31)。然后,我会迭代原始字符串,将非控制字符(ASCII> = 32)复制到输出缓冲区,并将查找表中的值替换为ASCII 0-31。

注1:ASCII 0为C字符串明显特殊(未所以对于C++。)

注2:该查找表将包含C转义序列具有他们代码(\n\r等)和反斜杠加上十六进制/八进制/十进制代码。

0

这是C#中的一个算法。也许你可以把它当作伪代码并将其转换为C++。

public static string EscapeChars(string Input) string Output =“”;

foreach (char c in Input) 
{ 
    switch (c) 
    { 
     case '\n': 
      Output += "\\n"; 
      break; 
     case '\r': 
      Output += "\\r"; 
      break; 
     case '\t': 
      Output += "\\t"; 
      break; 
     default: 
      Output += c; 
      break; 
    }     
} 
return Output; 

}

2

这里是我想出了...

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

inline char needs_escaping(char val) { 
     switch(val) { 
       case '\n': return 'n'; 
       case '\r': return 'r'; 
       case '\t': return 't'; 
     } 
     return 0; 
} 

char *escape_string(char *in) { 
     unsigned int needed = 0, j = 0, length = strlen(in), i; 
     for(i = 0; i < length; i++) { 
       if(needs_escaping(in[i])) needed++; 
     } 

     char *out = malloc(length + needed + 1); 
     for(i = 0; i < length; i++) { 
       char escape_val = needs_escaping(in[i]); 
       if(escape_val) { 
         out[j++] = '\\'; 
         out[j++] = escape_val; 
       } 
       else { 
         out[j++] = in[i]; 
       } 
     } 
     out[length + needed] = '\0';  
     return out; 
} 

int main() { 
     char *in = "A\r\nB\tC\nD"; 
     char *out = escape_string(in); 
     printf("%s\n", out); 
     free(out); 
     return 0; 
}