【问题标题】:how to extract with sscanf using regex? (in C)如何使用正则表达式使用 sscanf 进行提取? (在 C 中)
【发布时间】:2021-04-30 16:12:20
【问题描述】:

我有字符串"pid:8792 byr:2000 cols:hkjdp\n",我只想提取byr: 之后的数字。我认为可以通过使用sscanf(str,"byr:%d",&number); 提取格式化字符串来完成。但不幸的是,您不能这样做,因为在数字之前和之后还有其他字符,所以我看到您可以使用某种正则表达式,就像在这个问题中提出的 How to use regex in sscanf

所以我尝试了这样的事情:sscanf(passport, "%*[^byr:]:%[^\h]%*[^\n]", byr); 其中 byr 现在定义为 char *byr;。但是你不能使用像\hfor whitespace 这样的正则表达式。 长话短说:有什么方法可以让我使用sscanf 解析许多字符串,并始终在byr: 之后提取该数字,我在哪里可以找到所有这些字符在格式化字符串中使用的备忘单? (当然我知道显而易见的%f %d %s %c等等,但这些在这种情况下并没有真正发挥作用。

【问题讨论】:

  • 也许你需要一个合适的正则表达式库?
  • 或者只是使用其他方式?如strstr后跟strtoul
  • 您可以使用sscanf"pid:%*d byr:%d cols:%*s" 之类的格式。像这样的 scanf 格式字符串中的* 表示“扫描,但不分配给任何东西”。
  • 但是不,scanf 没有也不能做真正的正则表达式,正如that other question 解释的那样。
  • man scanf 包含scanf 转换规范的完整描述。你不会在那里找到正则表达式,因为 scanf 不做正则表达式。在 C 语言中,像 \n 这样的转义序列在实际执行像 scanf 这样的函数之前很久就被编译器转换为相应的字符。在 scanf 格式字符串中,空白字符的处理方式相同,如man scanf 中所述;它们匹配输入中的任何空白字符序列。 (在大多数正则表达式库中,空格是 \s,而不是 \h。但它们都不是有效的 C 转义序列。)

标签: c parsing scanf


【解决方案1】:

scanf 不太适合这种情况。它不提供您需要的通用正则表达式支持。

如果您只关心“byr:”部分,则完全不同的方法是使用strstr 搜索该特定字符串。这是一个例子:

char *str = "pid:8792 byr:2000 cols:hkjdp\n";
char *tag = "byr:";
char *p = strstr(str, tag);
if(p != NULL) {
    int n = atoi(p + strlen(tag));
    printf("%s %d\n", tag, n);
}

str = "pid:8792 uid:412 byr:3000 cols:etfvq\n";
p = strstr(str, tag);
if(p != NULL) {
    int n = atoi(p + strlen(tag));
    printf("%s %d\n", tag, n);
}

tag = "uid:";
p = strstr(str, tag);
if(p != NULL) {
    int n = atoi(p + strlen(tag));
    printf("%s %d\n", tag, n);
}

通常不推荐使用atoi,因为它会悄悄地忽略尾随垃圾,但这正是您想要的。

这种技术的一个缺点是它会错误地找到例如“abyr:”标签。

【讨论】:

  • 似乎可以解决问题,但我有一个问题:为什么atoi(p + strlen); 只包含数字?指针现在不应该在数字的开头然后读取直到找到\n 吗?还是atoi() 只读取到下一个非数字元素?
  • @Phil:没错;当我说它“安静地忽略尾随垃圾,但这正是你想要的”时,这就是我所暗示的。
  • 知道了??。感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 2013-01-04
  • 2021-07-06
相关资源
最近更新 更多