Получить текст до и после strstr в C - PullRequest
0 голосов
/ 30 ноября 2018

Мне нужно иметь возможность извлекать символы до и после подстроки, в настоящее время у меня есть следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]){

   char *text = (char *) malloc (10000000);
   char *word = argv[1];
   int rep;

   FILE *f;

   if(argc < 2)
   {
       printf("Usage: GET <website> | ./word_counter <word>\n");
       exit(1);
   }

   fread(text, 100, 10000000, stdin);

   const char *tmp = text;

   f = fopen("output.txt", "w");
   fprintf(f, "%s\n", "REPS");

   while(tmp = strstr(tmp, word)){
      printf("%.50s\n", tmp);
      rep++;
      tmp++;
   }

   printf("Word count: %d\n", rep);
   fclose(f);
   system("gedit output.txt");

   return 0;
}

Я сделал копию исходного ввода, чтобы я мог оставить его без изменений и получитьсимволы "before" из него.

Используя strstr () для tmp (исходной входной копии), я могу найти искомые слова и распечатать первые 50 символов.Но, зная это, как я могу получить доступ к 50 символам ДО этого экземпляра?

Любая помощь будет оценена.Спасибо!

1 Ответ

0 голосов
/ 30 ноября 2018

Помимо самого вопроса о печати, в вашем коде есть пара ошибок.Я исправил большинство из них;краткий список:

  1. Всегда проверка, если malloc выполнен успешно.
  2. fread(text, 100, 10000000, ..) читает слишком много текста.100 * 10000000 = 1000000000, почти полный гигабайт.Вы выделили достаточно памяти только для 10 Мб.
  3. Вы читаете из текстового файла и обрабатываете эти данные как строку.Следовательно, вы должны убедиться, что данные заканчиваются на 0, иначе такие функции, как printf и strstr будут пытаться продолжить чтение после окончания.
  4. Ваша переменная rep начинается неинициализированной ипоэтому вы всегда будете видеть случайное число.
  5. Всегда освобождайте выделенную память.

Тем не менее, несколько эффективнее использовать выделенную функцию для распечатки текста - если тольконе вкладывать слишком много в main.А поскольку это функция, вы можете добавить в нее столько полезных параметров, сколько захотите;Я добавил переменные before и after, чтобы вы могли изменять количество отображаемых символов.

Для дополнительной точности эта функция печатает правильное количество пробелов, когда фраза найдена до минимального числа before символов, поэтому результаты выстраиваются в очередь.Кроме того, поскольку распечатка таких символов, как табуляция и символы новой строки, испортит ваш вывод, я заменил их на ?.

По общему признанию, есть некоторое повторение в print_range, но в этом случае я пошел для ясности, а не краткость.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH  10000000

void print_range (char *source_text, int startindex, int before, int after, int phrase_length)
{
    int i;

    if (before > startindex)
    {
        for (i=0; i<before-startindex; i++)
            printf (" ");
        startindex = before;
    }

    for (i=0; i<before; i++)
    {
        if (strchr ("\t\r\n", source_text[startindex-before+i]))
            printf ("?");
        else
            printf ("%c", source_text[startindex-before+i]);
    }
    for (i=0; i<phrase_length; i++)
    {
        if (strchr ("\t\r\n", source_text[startindex+i]))
            printf ("?");
        else
            printf ("%c", source_text[startindex+i]);
    }
    for (i=0; i<after; i++)
    {
        if (!source_text[startindex+phrase_length+i])
            break;
        if (strchr ("\t\r\n", source_text[startindex+phrase_length+i]))
            printf ("?");
        else
            printf ("%c", source_text[startindex+phrase_length+i]);
    }
    printf ("\n");
}

int main (int argc, char *argv[]){

    char *text = (char *) malloc (MAX_LENGTH);
    char *word = argv[1];
    int rep = 0;

    if (!text)
        return -1;

    if(argc < 2)
    {
         printf("Usage: GET <website> | ./word_counter <word>\n");
         exit(1);
    }

    fread(text, 1, MAX_LENGTH, stdin);
    text[MAX_LENGTH] = 0;

    const char *tmp = text;

    do
    {
        tmp = strstr(tmp, word);
        if (!tmp)
            break;
        print_range (text, tmp-text, 16,16, strlen(word));
        rep++;
        tmp++;
    } while (1);

    free (text);

    printf ("Word count: %d\n", rep);

    return 0;
}

Результат выполнения этого в своем исходном коде:

~/Documents $ ./wordcounter printf < wordcounter.c
tindex; i++)????printf (" ");???starti
-before+i]))????printf ("?");???else??
"?");???else????printf ("%c", source_t
before+i]);??}??printf ("{");??for (i=
rtindex+i]))????printf ("?");???else??
"?");???else????printf ("%c", source_t
tindex+i]);??}??printf ("}");??for (i=
_length+i]))????printf ("?");???else??
"?");???else????printf ("%c", source_t
length+i]);??}??printf ("\n");?}??int 
argc < 2)??{??? printf("Usage: GET <we
?free (text);???printf ("Word count: %
Word count: 12
...