字符串格式 %80[^,] 在 C 中是什么意思?

What does the string format %80[^,] mean in C?

给定以下几行:

char szInline[80];
char szDescription[80] = { NULL };
float fCost = 0;
sscanf (szInline, "%80[^,], %f", szDescription, &fCost);

%80[^,] 有什么作用?

读取最多 80 个字符直到下一个 , 逗号。

顺便说一句,szDescription 缓冲区太小了 1。

以下是 sscanf(szInline, "%80[^,], %f", szDescription, &fCost) 的步骤:

  • sscanf180 之间不同于 , 的字符解析为数组 szDescription,
  • 如果成功,则它期望匹配 , 个字符;
  • 如果找到,它将忽略任何白色space字符(包括'\n');
  • if 最后尝试将浮点数表示形式转换为 float 类型的变量 fCost
  • 它将 return 成功转换的次数或 EOF 是早期失败的情况。

里面有潜在的问题:

  • 目标数组 szDescription 对于 80 个字符加上一个 '[=23=]' 终止符来说太短了,但幸运的是,输入数组 szInline 的长度也是 80。如果它包含一个正确的字符串,最多 79 个字符将被 sscanf 匹配,因此不会发生溢出。在这种特殊情况下实际上不需要大小说明符。
  • , 之后的 space 是多余的。 %f 总是忽略前导白色space.

注意 sscanf() 将 return EOF 在此输入上:,1 因为有 no 个字符不同于 , 从输入字符串的开头开始解析。即使是高级 C 程序员也常常忽视这种特殊情况。

如果你想在,之前接受一个可能为空的字符串,你不能直接使用sscanf(),但是你可以使用这个:

/* compute the length of the initial sequence upto `,` if any */
size_t len = strcspn(szInline, ",");
/* len < 80 because sizeof(szInline) == 80 */
/* copying the initial string */
memcpy(szDescription, szInline, len);
szDescription[len] = '[=10=]';
if (sscanf(szInline + len, ",%f", &fCost) != 1) {
    /* conversion error: no `,` or no number past it */
    ...
}

sscanf() 有很多怪癖,众所周知,除了最琐碎的解析任务外,很难正确使用它。很少使用的标准函数 strspn()strcspn() 是有用的替代方法。