sscanf没有提取模式

时间:2014-04-17 07:35:59

标签: c regex scanf

我试图找出我应该给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单位。

由于

4 个答案:

答案 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这就解释了为什么unitmemory_size保持不变。你需要的是格式字符串

unit

此处,格式为字符串sscanf(list, "%*[^(](%d%2[^)]%*s", &memory_size, unit); -

  1. "%*[^(](%d%2[^)]%*s"表示%*[^(]将首先阅读并丢弃不包含字符sscanf的字符序列。
  2. (表示(会阅读并放弃sscanf
  3. (表示%d将读取十进制整数。
  4. sscanf表示%2[^)]最多会读取不包含sscanf的{​​{1}}个字符序列,并将它们存储在相应的参数中。这是为了确保2不会溢出缓冲区),以防要存储的字符串太大。它比sscanf小一个,以节省终止空字节的空间,该字节由缓冲区末尾的unit自动添加。
  5. unit表示sscanf将读取并丢弃任何剩余的非空白字符序列。

答案 2 :(得分:2)

plz浏览sscanf()函数的以下链接。

sscanf function description

现在,

按照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"