首先让我说我不是C的专家。我一直在审查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;
}
这个代码实际工作原理的一般性总结真的很棒,我的印象是它正在“美化”JSON字符串,这是正确的吗?
乍一看似乎是用r取代\ r \ n,但这有什么意义呢?
我一直在研究sprintf的功能,但是对于简单的事情,例如打印货币值或其他格式问题。但是我还没有弄清楚sprintf函数在这里做了什么:
sprintf(ptr2,"u%04x",token);ptr2+=5;
ptr2 + = 5的目的是什么?
对此的任何见解都会有所帮助。
答案 0 :(得分:1)
此代码正在执行的操作是将非打印字符(例如U + 000A(换行符)替换为字符串中的转义序列,例如\n
(两个字符\\
和{{1} })。
变量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';
答案 1 :(得分:1)
该函数正在转义字符串内容,而不是美化它 - 例如它将回车字符(ASCII代码13)转换为字符串\r
,它会转换其代码中的其他不可打印字符。 / p>
sprintf(ptr2,"u%04x",token);
将ptr2
的十六进制表示放入token
(x
),用0
填充为长度为四个字符(04
) ,并以u
为前缀 - 以下
ptr2+=5;
将ptr2
指针移到刚刚由sprintf
生成的字符串后面 - 这是5个字符长。
答案 2 :(得分: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
。