在C中使用regex.h执行RE。匹配&计算String中的任何数字

时间:2013-08-01 23:21:55

标签: c regex linux

我正在尝试从文件中提取数字。我有限制,我只需要使用open()read()close()

我已成功读取数据并保存在缓冲区中。不,我需要将它与RE匹配。 我正在使用RE = ^ [0-9] *

这是我的代码

char buffer[1024] = { NULL };
int count = 0;
int fRead;

fRead = open("file.in", O_RDONLY);
read(fRead, buffer, sizeof(buffer));
printf("\nFile Opened %s, %lu", buffer, sizeof(buffer));

/* Compile regular expression */
regex_t re;
int reti = regcomp(&re, "^[1-9]*", 0);
if (reti) {
    fprintf(stderr, "Could not compile regex\n");
    exit(1);
}

/* Execute regular expression */
reti = regexec(&re, buffer, 0, NULL, 0);
if (!reti) {
    printf("\nMatch: %d", reti);
} else if (reti == REG_NOMATCH) {
    puts("No match");
} else {
    char msgbuf[100];
    regerror(reti, &re, msgbuf, sizeof(msgbuf));
    fprintf(stderr, "Regex match failed: %s\n", msgbuf);
    exit(1);
}
close(fRead);

现在问题是我想计算并显示我在文件中找到的数字。 例如,我的文件可能包含文本some thing 2 to 3 makes 5,在这种情况下,我的输出必须是 OUTPUT: 2,3,5 count = 3

1 个答案:

答案 0 :(得分:3)

看看man page for regexec。正如您使用的那样,regexec的返回值为0表示成功或正错误代码。但是,regexec的其他参数是如何获得有关匹配的更多信息。

为方便起见,这里是regexec的定义:

int regexec(const regex_t *preg, const char *string, size_t nmatch,
            regmatch_t pmatch[], int eflags);

pmatch参数是函数在找到它们时匹配的位置,而nmatch参数告诉函数pmatch参数有多少元素,因此它不会溢出。这类似于其他语言“匹配”函数,其中pmatch的第一个索引将具有完整的正则表达式匹配,而以下索引将具有子组匹配。这意味着您需要使用子组匹配来获取字符串中的数字,然后您需要循环遍历字符串以查找后续子组匹配。

首先,实例化一个regmatch_t堆栈变量来保存结果。这只需要大小为2,因此您可以将完整匹配存储在0索引中,并将子组匹配存储在1索引中。您还需要更改正则表达式,以便它匹配整个字符串,直到它到达一个数字。我们将它传递给regexec函数及其nmatch的大小。

每次找到匹配项时,您都需要向前移动字符串的开头,以便下次调用regexec时,您将获得下一个数字而不是同一个。< / p>

首先更新正则表达式字符串。

/* if we use .* in the regex it will be greedy and match the last number, not the first.
   We need to use a + instead of a * for the number so we know there is at least 1. */
int reti = regcomp(&re, "[^0-9]*([0-9]+)", REG_EXTENDED);

然后循环找到所有匹配。

/* regmatch_t is defined in regex.h */
regmatch_t matches[2];
int start;
int end;  

while (1) {
  reti = regexec(&re, buffer, 2, matches, 0);

  /* rm_so is the start index of the match */
  start = matches[1].rm_so;
  /* rm_eo is the end index of the match */
  end = matches[1].rm_eo;
  /* break if we didn't find a match */
  if (reti) break;

  /* print the substring that contains the match */
  printf("%.*s, ", (end - start), (buffer + start));
  /* increment the count of matches */
  count = count + 1;

  /* This is really important!
     Move the start of the string forward so we don't keep matching the same number! */
  buffer = buffer + end;
} 

/* print the count */
printf("count = %d", count);