sscanf返回1读取字符串

sscanf返回1读取字符串,c,C,当它返回一个时意味着什么 谁能帮我找出我的问题所在 char* line = "\"ThisId\":\"\""; char key[32], value[512]; if (sscanf(line, "\"%31[^\"]\":\"%511[^\"]\"", key, value) != 2) { return false; } 我想读取key=ThisId 及 在这种情况下,值应为空 看起来key得到了整个字符串,因此value不会得到任何值 原因是格式说明符[…]与空输入不匹配。

当它返回一个时意味着什么

谁能帮我找出我的问题所在

char* line = "\"ThisId\":\"\"";
char key[32], value[512];
if (sscanf(line, "\"%31[^\"]\":\"%511[^\"]\"", key, value) != 2) {
    return false;
}
我想读取key=ThisId

在这种情况下,值应为空


看起来key得到了整个字符串,因此value不会得到任何值

原因是格式说明符
[…]
与空输入不匹配。例如,赋予链接C标准草案中的含义,并注明“非空”(重点是我的):

[…匹配一组预期字符(扫描集)中的非空字符序列

因此,“空”值,即两个
\“
之间没有任何字符的输入,将与格式不匹配,这就是为什么在这种情况下
scanf
的结果不是
2


不管怎样,
scanf
有几种输入格式,中间有几个字符,这通常会变得非常棘手,而且容易出错。我建议你读完整的一行,例如使用
fgets
,然后解析它,例如使用
strtok
,或者
strchr
。因为你手头已经有一行,你当然会跳过
f获取
-thing.

原因是格式说明符[…]与空输入不匹配。例如,请授予链接的C标准草案中的的的含义,并注意“非空”(重点是我的):

[…匹配一组预期字符(扫描集)中的非空字符序列

因此,“空”值,即两个
\“
之间没有任何字符的输入,将与格式不匹配,这就是为什么在这种情况下
scanf
的结果不是
2

不管怎样,
scanf
有几种输入格式,中间有几个字符,这通常会变得非常棘手,而且容易出错。我建议你读完整的一行,例如使用
fgets
,然后解析它,例如使用
strtok
,或者
strchr
。因为你手头已经有一行,你当然会跳过
f获取
-对象。

这是因为
[^\“]
将读取字符,直到到达
\”
。因为您的输入
“\“ThisId\”:\“\”;
不包含第二个字符串的任何额外字符。
sscanf
没有读取
值的任何内容

如果您打算读取空值,请按如下所示在输入中输入
'

char* line = "\"ThisId\":\" \"";
这是因为
[^\“]
将读取字符,直到到达
\”
。因为您的输入
“\“ThisId\”:\“\”;
不包含第二个字符串的任何额外字符。
sscanf
没有读取
值的任何内容

如果您打算读取空值,请按如下所示在输入中输入
'

char* line = "\"ThisId\":\" \"";
我的问题在哪里

char* line = "\"ThisId\":\"\"";
char key[32], value[512];
if (sscanf(line, "\"%31[^\"]\":\"%511[^\"]\"", key, value) != 2) {
    return false;
}
当说明符无法匹配任何内容时,
sscanf()
的预期不正确


由于
没有匹配的
%511[^\“]”
,因此扫描停止。
值[]
不变,
scanf()
报告在这种情况下成功扫描的
1
说明符的数量


还有一个问题

使用下面的
line2
sscanf()
值[]
填充为
“xyz”
sscanf()
按预期返回2

char* line2 = "\"ThisId\":\"xyz\"";
使用下面的
line3
sscanf()
值[]
填充为
“xyz”
sscanf()
返回2,即使
line3
没有最终的
“\”

使用下面的
line4
sscanf()
值[]
填充为
“xyz”
sscanf()
返回2,即使
line4
在最后的
“\”
之后会有额外的垃圾


OP的目标是匹配两种不同的
sscanf
格式中的任何一种。我发现使用字符串文字连接使代码更容易理解和维护

#define KEY_FMT "\"%31[^\"]\"
#define SEP_FMT ":"
#define VAL_FMT "\"%511[^\"]\"
#define EMPTY_FMT "\"\"

KEY_FMT SEP_FMT VAL_FMT      /* key and value */
KEY_FMT SEP_FMT EMPTY_FMT    /* key and empty value */
一个简单的解决方案是扫描字符串两次,然后测试扫描是否结束。代码可以使用最后一个%n”来测试这一点,以记录到目前为止扫描到的字符数(如果扫描到该点)

一个有用的变化是分部分扫描

int n = 0;
sscanf(line, KEY_FMT SEP_FMT N_FMT, key, &n);
if (n == 0) {
  return false; // Key or separator not found
}
line += n; // advance

n = 0;
sscanf(line, VALUE_FMT N_FMT, &n);
if (n > 0 && line[n] == '\0') {
  return true; // Found value
}

n = 0;
sscanf(line, EMPTY_FMT N_FMT, value, &n);
if (n > 0 && line[n] == '\0') {
  value[0] = '\0'; 
  return true; // Found empty value
}

return false;

最后,考虑在扫描的各个部分中允许空白。< /P>

#define KEY_FMT " \"%31[^\"]\"
#define SEP_FMT " :"
#define VAL_FMT " \"%511[^\"]\"
#define EMPTY_FMT " \"\"  
#define N_FMT " %n"
我的问题在哪里

char* line = "\"ThisId\":\"\"";
char key[32], value[512];
if (sscanf(line, "\"%31[^\"]\":\"%511[^\"]\"", key, value) != 2) {
    return false;
}
当说明符无法匹配任何内容时,
sscanf()
的预期不正确


由于
没有匹配的
%511[^\“]”
,因此扫描停止。
值[]
不变,
scanf()
报告在这种情况下成功扫描的
1
说明符的数量


还有一个问题

使用下面的
line2
sscanf()
值[]
填充为
“xyz”
sscanf()
按预期返回2

char* line2 = "\"ThisId\":\"xyz\"";
使用下面的
line3
sscanf()
值[]
填充为
“xyz”
sscanf()
返回2,即使
line3
没有最终的
“\”

使用下面的
line4
sscanf()
值[]
填充为
“xyz”
sscanf()
返回2,即使
line4
在最后的
“\”
之后会有额外的垃圾


OP的目标是匹配两种不同的
sscanf
格式中的任何一种。我发现使用字符串文字连接使代码更容易理解和维护

#define KEY_FMT "\"%31[^\"]\"
#define SEP_FMT ":"
#define VAL_FMT "\"%511[^\"]\"
#define EMPTY_FMT "\"\"

KEY_FMT SEP_FMT VAL_FMT      /* key and value */
KEY_FMT SEP_FMT EMPTY_FMT    /* key and empty value */
一个简单的解决方案是扫描字符串两次,然后测试扫描是否结束。代码可以使用最后一个%n”来测试这一点,以记录到目前为止扫描到的字符数(如果扫描到该点)

一个有用的变化是分部分扫描

int n = 0;
sscanf(line, KEY_FMT SEP_FMT N_FMT, key, &n);
if (n == 0) {
  return false; // Key or separator not found
}
line += n; // advance

n = 0;
sscanf(line, VALUE_FMT N_FMT, &n);
if (n > 0 && line[n] == '\0') {
  return true; // Found value
}

n = 0;
sscanf(line, EMPTY_FMT N_FMT, value, &n);
if (n > 0 && line[n] == '\0') {
  value[0] = '\0'; 
  return true; // Found empty value
}

return false;