Подсчет слогов в массиве - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь сосчитать все слоги в каждом слове строки, которые я передал в массив.

Слог считается как два гласных, смежных друг с другом (a, e, i, o, u,у).Например, «ee» в «peel» считается как 1 слог.Но «и» и «е» в «juked» считаются 2 слогами.Буква «е» в конце слова не считается слогом.Кроме того, каждое слово имеет как минимум 1 слог, даже если предыдущие правила не применяются.

У меня есть файл, который содержит большую строку (слова, пробелы и новые строки), которые я передал в массив.У меня есть код, который считает каждое слово путем подсчета пробелов между ними и переводами строки.См. Ниже:

for (i = 0; i < lengthOfFile; i++)
{
    if (charArray[i] == ' ' || charArray[i] == '\n')
    {
      wordCount++;
    }
  }

Где charArray - это файл, который передается в массив (freads), а lengthOfFile - это общее количество байтов в файле, подсчитанное как (fseek), а wordCount - общееКоличество слов.

Отсюда мне нужно как-то подсчитать слоги в каждом слове в массиве, но не знаю, с чего начать.

1 Ответ

0 голосов
/ 11 февраля 2019

Если у вас все еще есть проблема, это только потому, что вы переосмысливаете проблему.Всякий раз, когда вы считаете, определяете частоту и т. Д., Вы обычно можете упростить вещи, используя «State-Loop».Цикл состояний - это не что иное, как цикл, в котором вы зацикливаете каждый символ (или любой другой) и обрабатываете любое состояние, в котором находитесь, например:

  • Я прочитал какие-нибудь символы?(если нет, обработайте это состояние);
  • является ли текущий символ пробелом?(если это так, если для простоты не использовать несколько пробелов, вы достигли конца слова, обработайте это состояние);
  • является ли текущий символ непробельным и не гласным?(если так, если моим последним символом был гласный, увеличьте количество слогов);и
  • что мне нужно делать независимо от классификации текущего символа?(выведите его, установите last = current и т. д.)

По сути, это все и может быть переведено в один цикл с несколькими тестами для обработки каждого состояния.Вы также можете добавить проверку, чтобы убедиться, что такие слова, как "my" и "he", считаются как один слог, проверяя, равен ли ваш слог нулю, когда вы достигаете конца слова.

Если поставить его полностью, вы могли бы написать базовую реализацию, например:

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

int main (void) {

    char c, last = 0;                       /* current & last char */
    const char *vowels = "AEIOUYaeiouy";    /* vowels (plus Yy) */
    size_t syllcnt = 0, totalcnt = 0;       /* word syllable cnt & total */

    while ((c = getchar()) != EOF) {        /* read each character */
        if (!last) {                        /* if 1st char (no last) */
            putchar (c);                    /* just output it */
            last = c;                       /* set last */
            continue;                       /* go get next */
        }

        if (isspace (c)) {                  /* if space, end of word */
            if (!syllcnt)                   /* if no syll, it's 1 (he, my) */
                syllcnt = 1;
            printf (" - %zu\n", syllcnt);   /* output syll cnt and '\n' */
            totalcnt += syllcnt;            /* add to total */
            syllcnt = 0;                    /* reset syllcnt to zero */
        }   /* otherwise */
        else if (!strchr (vowels, c))       /* if not vowel */
            if (strchr (vowels, last))      /* and last was vowel */
                syllcnt++;                  /* increment syllcnt */

        if (!isspace (c))                   /* if not space */
            putchar (c);                    /* output it */
        last = c;                           /* set last = c */
    }
    printf ("\n  total syllables: %zu\n", totalcnt);
}

( note: , как упоминалось выше, в этом простом примере реализации не учитывается несколько пробелов между словами - которые вы можете просто добавить какЕще одно необходимое условие, проверив, !isspace (last). Можете ли вы выяснить, где должна быть добавлена ​​эта проверка, подсказка: она добавлена ​​к существующей проверке с помощью && - вам оставлена ​​точная настройка)

Пример использования / Вывод

$ echo "my dog eats banannas he peels while getting juked" | ./syllablecnt
my - 1
dog - 1
eats - 1
banannas - 3
he - 1
peels - 1
while - 1
getting - 2
juked - 2

  total syllables: 13

Если вам нужно прочитать слова из файла, просто перенаправьте файл в качестве ввода в программу на stdin, например,

./syllablecnt < inputfile

Редактировать - Чтение из файла в динамически распределенный буфер

Следуя комментариям о желании прочитать из файла (или stdin) в динамически изменяемый буфер и т.Затем, пройдя через буфер для вывода слогов по каждому слову и общего слога, вы можете сделать что-то вроде следующего: просто считывает все символы из файла в буфер, первоначально выделенный с 8 символами, и перераспределяется по мере необходимости (удваивая размер выделения каждыйвремя realloc необходимо).Это довольно стандартная и достаточно эффективная стратегия роста буфера.Вы можете увеличивать его до любого размера, который вам нравится, но избегайте множества небольших перераспределений кроличьих шариков, поскольку выделение памяти относительно дорого с вычислительной точки зрения.

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

#define NCHAR 8     /* initial characters to allocate */

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

    char c, last = 0, *buffer;              /* current, last & pointer */
    const char *vowels = "AEIOUYaeiouy";    /* vowels */
    size_t syllcnt = 0, totalcnt = 0,       /* word syllable cnt & total */
            n = 0, size = NCHAR;
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("fopen-file");
        return 1;
    }

    /* allocate/validate initial NCHAR buffer size */
    if (!(buffer = malloc (size))) {
        perror ("malloc-buffer");
        return 1;
    }

    while ((c = fgetc(fp)) != EOF) {        /* read each character */
        buffer[n++] = c;                    /* store, increment count */
        if (n == size) {                    /* reallocate as required */
            void *tmp = realloc (buffer, 2 * size);
            if (!tmp) {                     /* validate realloc */
                perror ("realloc-tmp");
                break;      /* still n good chars in buffer */
            }
            buffer = tmp;   /* assign reallocated block to buffer */
            size *= 2;      /* update allocated size */
        }
    }
    if (fp != stdin)        /* close file if not stdin */
        fclose (fp);

    for (size_t i = 0; i < n; i++) {        /* loop over all characters */
        c = buffer[i];                      /* set to c to reuse code */
        if (!last) {                        /* if 1st char (no last) */
            putchar (c);                    /* just output it */
            last = c;                       /* set last */
            continue;                       /* go get next */
        }

        if (isspace(c) && !isspace(last)) { /* if space, end of word */
            if (!syllcnt)                   /* if no syll, it's 1 (he, my) */
                syllcnt = 1;
            printf (" - %zu\n", syllcnt);   /* output syll cnt and '\n' */
            totalcnt += syllcnt;            /* add to total */
            syllcnt = 0;                    /* reset syllcnt to zero */
        }   /* otherwise */
        else if (!strchr (vowels, c))       /* if not vowel */
            if (strchr (vowels, last))      /* and last was vowel */
                syllcnt++;                  /* increment syllcnt */

        if (!isspace (c))                   /* if not space */
            putchar (c);                    /* output it */
        last = c;                           /* set last = c */
    }
    free (buffer);      /* don't forget to free what you allocate */

    printf ("\n  total syllables: %zu\n", totalcnt);
}

(вы можете сделать то же самое, используя fgetsили используя POSIX getline, или выделите все сразу с помощью fseek/ftell или stat и затем fread всего файла в буфер за один вызов - до вас)

Использование памяти / проверка ошибок

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

Обязательно, чтобы вы использовали памятьпрограмма проверки ошибок, чтобы убедиться, что вы не пытаетесь получить доступ к памяти или писать за пределами / за пределами выделенного блока, пытаться прочитать или основать условный переход на неинициализированном значении и, наконец, подтвердитьЕсли вы освободите всю память, которую вы выделили.

Для Linux valgrind - нормальный выбор.Для каждой платформы есть похожие проверки памяти.Все они просты в использовании, просто запустите вашу программу через нее.

$ valgrind ./bin/syllablecnt_array dat/syllables.txt
==19517== Memcheck, a memory error detector
==19517== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==19517== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==19517== Command: ./bin/syllablecnt_array dat/syllables.txt
==19517==
my - 1
dog - 1
eats - 1
banannas - 3
he - 1
peels - 1
while - 1
getting - 2
juked - 2

  total syllables: 13
==19517==
==19517== HEAP SUMMARY:
==19517==     in use at exit: 0 bytes in 0 blocks
==19517==   total heap usage: 5 allocs, 5 frees, 672 bytes allocated
==19517==
==19517== All heap blocks were freed -- no leaks are possible
==19517==
==19517== For counts of detected and suppressed errors, rerun with: -v
==19517== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

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

Посмотрите вещии дайте мне знать, если у вас есть дополнительные вопросы.

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