Есть ли способ прочитать файловый поток, пока не будет найден период (.).Тогда повторить? - PullRequest
1 голос
/ 08 мая 2019

Я довольно плохо знаком с C и не уверен, как бы я это сделал. Я нашел похожие вопросы, но ничего не хотел.

Что я хочу сделать, так это прочитать необработанный текстовый файл «предложение за предложением», в котором конец предложения считается точкой (.) Или переводом строки (\ n). Без предполагаемой максимальной длины для любых структур данных.

Моя первая мысль была getline(), но версия C, которую я должен использовать, похоже, не имеет такой функции. Поэтому я попытался использовать fgets(), а затем проанализировать данные на sscanf() с помощью набора сканирования. sscanf(charLine, "%[^.]s", sentence);

Проблема в том, что если существует более одного периода (.), Он остановится в первый и не начнется снова в этот период (.), Чтобы собрать остальные.

Мне кажется, что я на правильном пути, но просто не могу подробно остановиться на этом.

    while(fgets (charLine, size, readFile) == NULL)
    {
         sscanf(charLine, "%[^.]s", sentence);
         // something here...
    }

1 Ответ

3 голосов
/ 08 мая 2019

Вы можете написать функцию, которая читает поток, пока не будет найден . или символ новой строки. Дэвид С.Ранкин предположил, что простое сканирование на . может быть слишком ограничительным, в результате чего встроенные периоды в www.google.com будут действовать как разрыв предложения. Можно остановиться на ., если за ним следует пробел:

#include <ctype.h>
#include <stdio.h>

/* alternative to fgets to stop at `.` and newline */
char *fgetsentence(char *dest, size_t size, FILE *fp) {
    size_t i = 0;
    while (i + 2 < size) {
        int c = getc(fp);
        if (c == EOF)
            break;
        dest[i++] = (char)c;
        if (c == '\n')
            break;
        if (c == '.') {
            int d = getc(fp);
            if (d == EOF)
                break;
            if (isspace(d)) {
                dest[i++] = (char)d;
                break;
            }
            ungetc(d, fp);
        }
    }
    if (i == 0)
        return NULL;
    dest[i] = '\0';
    return dest;
}

Если вы хотите обрабатывать произвольные длинные предложения, вы должны взять указатели на dest и size и перераспределить массив при необходимости.

Обратите внимание, что было бы очень непрактично использовать fscanf(fp, "%[^.\n]", dest), поскольку невозможно передать максимальное число байтов для хранения в dest в качестве оцениваемого аргумента, и нужно было бы использовать в особых случаях пустые строки и предложения.

Также обратите внимание, что остановка на ., даже с учетом вышеупомянутого ограничения на то, что за ним должен следовать пробел, по-прежнему приводит к ложным срабатываниям: предложения могут содержать вложенные точки, за которыми следуют пробелы, которые не являются концом предложения. Пример: Спасибо Дэвиду К. Ранкину за комментарии к моему ответу.

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