C: поиск строки в файле - PullRequest
       3

C: поиск строки в файле

3 голосов
/ 03 февраля 2010

Если у меня есть:

const char *mystr = "cheesecakes";
FILE *myfile = fopen("path/to/file.exe","r");

Мне нужно написать функцию, чтобы определить, содержит ли myfile вхождения mystr. Кто-нибудь может мне помочь? Спасибо!

ОБНОВЛЕНИЕ: получается, что платформа, на которой мне нужно развернуться, не имеет memstr Кто-нибудь знает о бесплатной реализации, которую я могу использовать в своем коде?

Ответы [ 6 ]

11 голосов
/ 03 февраля 2010

Если вы не можете поместить весь файл в память, и у вас есть доступ к расширению GNU memmem(), то:

  • Прочитайте как можно больше в буфер;
  • Поиск в буфере с помощью memmem(buffer, len, mystr, strlen(mystr) + 1);
  • Отменить все, кроме последних strlen(mystr) символов буфера, и переместить их в начало;
  • Повторяйте до достижения конца файла.

Если у вас нет memmem, вы можете реализовать его в простом C, используя memchr и memcmp, например:

/*
 * The memmem() function finds the start of the first occurrence of the
 * substring 'needle' of length 'nlen' in the memory area 'haystack' of
 * length 'hlen'.
 *
 * The return value is a pointer to the beginning of the sub-string, or
 * NULL if the substring is not found.
 */
void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
{
    int needle_first;
    const void *p = haystack;
    size_t plen = hlen;

    if (!nlen)
        return NULL;

    needle_first = *(unsigned char *)needle;

    while (plen >= nlen && (p = memchr(p, needle_first, plen - nlen + 1)))
    {
        if (!memcmp(p, needle, nlen))
            return (void *)p;

        p++;
        plen = hlen - (p - haystack);
    }

    return NULL;
}
3 голосов
/ 03 февраля 2010

Поскольку нет memmem или memstr для поиска строки в двоичном массиве (другие предлагали прочитать ее в память и использовать strstr - нет, это не работает), вы должны читать ее побайтно с помощью "fgetch"написать небольшой конечный автомат, чтобы соответствовать ему во время чтения.

1 голос
/ 03 февраля 2010

Смотрите здесь:

http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm

для реализации Бойера-Мура в C99. Это очень распространенный алгоритм поиска строк, который работает в O (n).

0 голосов
/ 04 февраля 2010

Вот функция, которая будет искать строку в буфере.

Ограничения: он не обрабатывает широкие символы (в случае интернационализации). Вам нужно написать свой собственный код, чтобы прочитать файл в память. Шаблон не будет найден, если шаблон разделен на 2 буфера чтения.

/*****************************************************
const char *buffer    pointer to your read buffer (the larger, the better).
size_t bufsize        the size of your buffer
const char *pattern   pattern you are looking for.

Returns an index into the buffer if pattern is found.
-1 if pattern is not found.

 Sample:
    pos = findPattern (buffer, BUF_SIZE, "cheesecakes");
*****************************************************/

int findPattern (const char *buffer, size_t bufSize, const char *pattern)
{
    int i,j;
    int patternLen;

    // minor optimization. Determine patternLen so we don't 
    // bother searching buffer if fewer than patternLen bytes remain.
    patternLen = strlen (pattern);

    for (i=0; i<bufSize-patternLen; ++i)
    {
        for (j=0; j<patternLen; ++j)
        {
            if (buffer[i+j] != pattern[j])
            {
                break;
            }
        }
        if (j == patternLen)
        {
            return i;
        }
    }
    return -1;
}
0 голосов
/ 03 февраля 2010

Вот его версия.У него нет проверки ошибок и, возможно, есть ошибки переполнения.Но я думаю, что он находит желаемую строку и учитывает возврат, необходимый для частичных совпадений подстрок.Я сомневаюсь, что осталось более 15 ошибок.

Редактировать: Был хотя бы один в первом ответе.Я проснулся посреди ночи и понял, что проверка возврата была неправильной.Он не нашел «12123» в «1212123».Это может все еще быть неправильно, но по крайней мере это находит это теперь.

int main( int argc, char* argv[] )
{
    FILE *fp;
    char *find, *hist;
    int  len, pos=0, hl=0, i;
    char c;

    fp = fopen( argv[1], "r" );
    find = argv[2];
    len = (int)strlen( find );
    hist = malloc( len );
    memset( hist, 0, len );
    while ( !feof( fp )) {
        c = fgetc( fp );
        if ( find[pos++] == c ) {
            if ( pos == len ) {
                printf( "Found it\n" );
                return 1;
            }
        }
        else {
            // check history buffer (kludge for backtracking)
            if ( pos > 0 ) {
                pos = 0;
                for ( i = 0; i < len - 1; i++ )
                    if ( 0 == memcmp( hist+len-i-1, find, i + 1 )) {
                    // we had a mismatch, but the history matches up to len i
                    pos = i;
                }
            }
        }
        // update history buffer - this is innefficient - better as circular buffer
        memmove( hist, hist + 1, len - 1 );
        hist[len-1] = c;
    }
    printf( "Not found\n" );
}
0 голосов
/ 03 февраля 2010
 chat match = "findthis";
 int depth = 0;
 while(not eof)
 {
     char ch = getonebyte();
     if(ch == match[depth])
     {  
         if (depth == strlen(match))
            break;
         else
            depth++;
      }
      else 
           depth = 0;
 }

примерно (я уверен, что там одни)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...