Я пробовал код в тестовом HTML-файле, который я просто вводил из текстового файла через stdin
с помощью перенаправления, и это, казалось, прекрасно работало при повторных чтениях до fgets()
. Тогда я подозреваю, что проблема заключается в форматировании строковых данных в вашем файле с отображением в памяти. Я подозреваю, что где-то в вашем файле отображения памяти есть завершающий ноль символ, так что если вы просто используете сам файл отображения памяти в качестве буфера символов, он заканчивает строку намного раньше, чем вы ожидали.
Во-вторых, вы возвращаете только первое совпадение плюс оставшуюся строку, что будет означать весь файл, начиная с первого совпадения, если вы используете указатель на файл отображения памяти в качестве параметра str
. Я подозреваю, что ваша "реальная" реализация немного отличается, если вы хотите токенизировать файл?
EDIT
Я смотрел на ваш концептуальный код, и, похоже, он работает в целом. Я сделал пару изменений, чтобы помочь мне распечатать вещи, но вот что я компилирую (очень грязно для отображения файловой памяти, просто чтобы проверить, работает ли код регулярного выражения):
#include <regex.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#define REG_MATCH_SIZE 10
#define FILE_SIZE 60000
static int total_matches = 0;
char * reg_strstr(const char *str, const char *pattern)
{
char *result = NULL;
regex_t re;
regmatch_t match[REG_MATCH_SIZE];
if (str == NULL)
return NULL;
if (regcomp( &re, pattern, REG_ICASE | REG_EXTENDED) != 0) {
regfree( &re );
return NULL;
}
if (!regexec(&re, str, (size_t) REG_MATCH_SIZE, match, 0)) {
fprintf( stderr, "@@@@@@ Match from %2d to %2d @@@@@@@@@\n",
match[0].rm_so,
match[0].rm_eo);
total_matches++;
if ((str + match[0].rm_so) != NULL) {
result = strndup(str + match[0].rm_so, strlen(str + match[0].rm_so));
}
}
regfree( &re );
return result;
}
int main()
{
int filedes = open("testhtml.txt", O_RDONLY);
void* buffer = mmap(NULL, FILE_SIZE, PROT_READ, MAP_PRIVATE, filedes, 0);
char* str_result;
char* temp_buffer = strdup((char*)buffer);
while(str_result = reg_strstr(temp_buffer, "<div"))
{
char* temp_print = strndup(str_result, 30);
fprintf(stderr, "reg_strstr result: '%s' ..\n\n", temp_print);
free(temp_print);
free(temp_buffer);
temp_buffer = strdup(str_result + 1);
free( str_result) ;
}
fprintf(stderr, "Total Matches: %d\n", total_matches);
return 0;
}
Просто используя простое совпадение для "<div"
, если я запускаю его на всем исходном HTML-коде для страницы, подобной этой здесь, на Bloomberg , я получаю в общей сложности 87 совпадений и что-то получаю это эквивалентно тому, что вы получите при повторном вызове стандарта strstr()
. Например, пример выходных данных выглядит следующим образом (примечание: я обрезал совпадение возвращаемой строки после 30 символов для здравого смысла):
@@@@@@ Match from 5321 to 5325 @@@@@@@@@
reg_strstr result: '<div id="noir_dialog" class="p' ..
@@@@@@ Match from 362 to 366 @@@@@@@@@
reg_strstr result: '<div id="container" class="mod' ..
Соответствующие индексы меняются конечно, поскольку новая входная строка короче, чем предыдущая входная строка, поэтому вы видите совпадение, которое начинается с 5321, но затем следующее совпадение - с 362 ... общее смещение будет на 5683 в исходной строке. Я уверен, что с другим регулярным выражением вы получите другие результаты, но в целом кажется, что ваша концепция работает или, по крайней мере, работает так, как strstr()
будет работать, то есть она возвращает всю строку, начиная с совпадения, к подстрока полностью до конца строки.
Если вы не получаете ожидаемых результатов (я не уверен, что именно вы не получаете), то я бы сказал, что проблема либо в самом регулярном выражении, либо в цикле, в что у вас может быть отключено индексирование (т. е. с помощью totok--
вы можете создать цикл для себя, который просто будет возвращать совпадение в той же точке строки).