2012-05-08 118 views
0

让我首先说我不是C中的专家。我一直在审查JSON解析器的代码。C中的JSON解析器(打印JSON)

我想了解这段代码。

/* Render the cstring provided to an escaped version that can be printed. */ 
static char *print_string_ptr(const char *str) 
{ 
    const char *ptr; 
    char *ptr2,*out; 
    int len=0; 
    unsigned char token; 

    if (!str) 
     return cJSON_strdup(""); 
    ptr = str; 
    while ((token = *ptr) && ++len) { 
     if (strchr("\"\\\b\f\n\r\t", token)) 
      len++; 
     else if (token < 32) 
      len += 5; 
     ptr++; 
    } 

    out = (char*)cJSON_malloc(len + 3); 
    if (!out) 
     return 0; 

    ptr2 = out; 
    ptr = str; 
    *ptr2++ = '\"'; 
    while (*ptr) { 
     if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\') 
      *ptr2++ = *ptr++; 
     else { 
      *ptr2++ = '\\'; 
      switch (token = *ptr++) { 
       case '\\':  *ptr2++='\\'; break; 
       case '\"':  *ptr2++='\"'; break; 
       case '\b':  *ptr2++='b'; break; 
       case '\f':  *ptr2++='f'; break; 
       case '\n':  *ptr2++='n'; break; 
       case '\r':  *ptr2++='r'; break; 
       case '\t':  *ptr2++='t'; break; 
       default: 
        /* escape and print */ 
        sprintf(ptr2, "u%04x", token); 
        ptr2 += 5; 
        break; 
      } 
     } 
    } 
    *ptr2++ = '\"'; 
    *ptr2++ = 0; 
    return out; 
} 

A的这段代码是如何工作将是真正伟大真是总体概述,我的印象是,它是“美化” JSON字符串,是正确的?

乍一看它似乎是用r替换\ r,但是这是什么意思?

我一直在研究sprintf的功能,但对于简单的事情,如打印出货币值或其他格式问题。但我还没有弄清sprintf函数在这里做什么:

sprintf(ptr2,"u%04x",token);ptr2+=5; 

ptr2 + = 5的目的是什么?

任何洞察到这真的会有所帮助。

回答

1

它所做的是将控制字符转换为您通常在C源代码中使用的转义序列。

if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 
    *ptr2++=*ptr++; 

这基本上是说:“如果我们有一个正常的角色就像一个字母,数字等,只需直接复制它从输入到输出。“

else 
{ 
    *ptr2++='\\'; 

否则,我们将在输出中的转义序列,将用反斜杠开始。

 switch (token=*ptr++) 
    { 
     case '\\':  *ptr2++='\\'; break; 
     case '\"':  *ptr2++='\"'; break; 
     case '\b':  *ptr2++='b'; break; 

然后,根据该控制字符找到,它生成的转义序列的第二个字符,所以在输入(将比较等于“\ b”)的一个实际的“退格”的字符将在输出产生两个字符'\”和‘b’。

  case '\f':  *ptr2++='f'; break; 
      case '\n':  *ptr2++='n'; break; 
      case '\r':  *ptr2++='r'; break; 
      case '\t':  *ptr2++='t'; break; 

和换页,换行,回车和制表符相同。

  default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; 

否则,呈现在十六进制控制字符,所以它变得像\1234

+0

很好解释,TY为它花时间! –

1

这段代码正在做的是替换不可打印的字符,如U + 000A(换行)与所述串中的转义序列如\n(两个字符,\\n)。

变量ptr2指向输出中的当前点,变量ptr指向正在写入输出的字符串中的当前点。

// Write "u" followed by a 4-digit hexadecimal number to the output 
sprintf(ptr2,"u%04x",token); 
// Advance the output pointer by five spaces 
ptr2 += 5; 

相比之下,

*ptr2++ = 'r'; 

是一样的,

// Write "r" to the output 
*ptr = 'r'; 
// Advance the output pointer one space 
ptr++; 
+0

艳太感谢你了 –

1

功能是逃避字符串内容,不美化它 - 例如把它转换一个回车符( ASCII代码13)转换为字符串\r,它转换其代码等中的其他非可打印字符。

sprintf(ptr2,"u%04x",token); 

地方到ptr2token(该x)的十六进制表示,填充与0 s至在lenght(该04)四个字符,并用u前缀 - 以下

ptr2+=5; 

移动ptr2指针紧跟在刚刚由sprintf生成的字符串之后 - 即5个字符长。