我试图找出我应该给sscanf的模式。 我有一个字符串abcde(1GB)。我想提取1和GB。我正在使用
char list[]= "abcde(1GB)";
int memory_size =0;
char unit[3]={0} ;
sscanf(list, "%*s%d%s" , &memory_size, unit);
打印时我没有看到提取的标记,我看到memory_size = 0和NULL单位。
由于
答案 0 :(得分:4)
您的sscanf()
字符串格式应为:
sscanf(list, "%*[^(](%d%[^)]" , &memory_size, unit);
%[^)]
表示捕捉字符串并在找到字符串)
或字符串结尾时停止连接%*[^(]
表示:
[^\(]
意味着捕捉字符并在找到字符(
时停止连接 - 而不是更传统的%s
- 捕捉字符并在找到空格字符时停止连接" *
表示"读取但不存储" 答案 1 :(得分:3)
格式字符串%s
中的scanf
转换说明符表示scanf
将读取一系列非空白字符。 *
中的%*s
称为分配抑制字符。这意味着scanf
将读取并丢弃非空白字符。
由于%s
匹配任何非空白字符序列,%*s
中的"%*s%d%s"
表示sscanf
将读取丢弃字符串{{1}中的所有字符}。 因此,数组list
中没有 left 可供阅读并分配给参数list
和&memory_size
。这就解释了为什么unit
和memory_size
保持不变。你需要的是格式字符串
unit
此处,格式为字符串sscanf(list, "%*[^(](%d%2[^)]%*s", &memory_size, unit);
-
"%*[^(](%d%2[^)]%*s"
表示%*[^(]
将首先阅读并丢弃不包含字符sscanf
的字符序列。(
表示(
会阅读并放弃sscanf
。(
表示%d
将读取十进制整数。sscanf
表示%2[^)]
最多会读取不包含sscanf
的{{1}}个字符序列,并将它们存储在相应的参数中。这是为了确保2
不会溢出缓冲区)
,以防要存储的字符串太大。它比sscanf
小一个,以节省终止空字节的空间,该字节由缓冲区末尾的unit
自动添加。unit
表示sscanf
将读取并丢弃任何剩余的非空白字符序列。答案 2 :(得分:2)
plz浏览sscanf()函数的以下链接。
现在,
按照MOHAMED的说法,%[^(]
用来抓住人物,直到"("
表示%*[^(]
截断字符串,直到(
之后%d
为整数数据,然后将字符串捕获到)
。
答案 3 :(得分:1)
接受答案后 - 补充
@MOHAMED答案很好,但下面是候选人改进。
1)始终检查sscanf()
结果,以确保按预期扫描数据。
if (sscanf(list, "%*[^(](%d%[^)]", &memory_size, unit) != 2) ScanFailure();
2)使用"%s"
或"%[]"
说明符时,请包含限制长度。 @ajay
char unit[3]={0} ;
// v--- 1 less than buffer size.
if (sscanf(list, "%*[^(](%d%2[^)]" , &memory_size, unit) != 2) ScanFailure();
3)附加"%n"
(保存扫描位置)是检测尾随)
的确定方法,并且额外的垃圾不在输入字符串的末尾。
"%n"
不会添加sscaanf()
结果。
int n = 0;
// )%n <--- Look for ) then save scan position
if (sscanf(list, "%*[^(](%d%2[^)])%n", &memory_size, unit, &n) != 2) ||
list[n] != '\0') ScanFailure();
4)为可选的空白区域腾出空间可能/可能没用。说明符已允许可选的前导空格。 3例外:%c %[] %n
"%*[^(](%d%2[^)])%n"
// v v v
" %*[^(](%d %2[^)]) %n"