Подсчет слогов по одному символу за раз [C] - PullRequest
0 голосов
/ 07 февраля 2010

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

Итак, имея в виду, вот как работает моя программа:

while(character != EOF)
{
    check if the character is a end-of-sentence marker (?:;.!)
    check if the character is whitespace (' ' \t \n)
    (must be a letter now)
    check if the letter is a vowel
}

Используя подход конечного автомата, каждый раз, когда проходит цикл, определенные триггеры либо 1, либо 0, и это влияет на счет. У меня не было проблем с подсчетом предложений или слов, но слоги доставляют мне неприятности. Определение слога, которое я использую, гласит, что любой гласный или группа гласных считается как 1 слог, однако один e в конце слова не считается слогом.

Имея это в виду, я создал код такой, что

if character = 'A' || 'E' ... || 'o' || 'u'
    if the last character wasnt a vowel then
    set the flag for the letter being a vowel.
    (so that next time through, it doesnt get counted)
    and add one to the syllable count.
    if the last character was a vowel, then dont change the flag and don't
    add to the count. 

Теперь у меня проблема с моим счетом для данного текстового файла, очень низкая. Данный счет составляет 57 слогов, 36 слов и 3 предложения. Я получаю правильные предложения, то же самое со словами, но мой слог только 35.

У меня также есть настройки, чтобы когда программа читала!:;.? или пробел, он будет смотреть на последний прочитанный символ, и, если это e, он уберет один из числа слогов. Это заботится о том, чтобы быть в конце слова, не считая гласной.

Итак, помня об этом, я знаю, что с моей методологией должно быть что-то не так, чтобы получить такую ​​огромную разницу. Я должен что-то забыть.

У кого-нибудь есть предложения? Я не хотел включать всю свою программу, но при необходимости могу включить некоторые блоки.

РЕДАКТИРОВАТЬ: некоторый код ...

У меня есть if (маркер конца предложения), затем else if (пробел), а затем заключительный, что влечет за собой то, что в этом блоке будут только буквы, которые могут образовывать слова. Это единственный блок кода, который должен оказывать влияние на подсчет слогов ...

if(chrctr == 'A' || chrctr == 'E' || chrctr == 'I' || chrctr == 'O' || chrctr == 'U' || chrctr == 'a' || chrctr == 'e' || chrctr == 'i' || chrctr == 'o'  || chrctr == 'u')
        {
            if(chrctr == 'E' || chrctr == 'e')
            {
                isE = 1;
            }
            else
            {
                isE = 0;
            }
            if(skipSylb != 1)
            {
                endSylb = 1;
                skipSylb = 1;
            }
            else
            {
                endSylb = 0;
                skipSylb = 1;
            }
        }
        else
        {
            endSylb = 0;
            skipSylb = 0;

        }

Итак, чтобы объяснить ... endSylb, если 1, позже в программе добавится один к количеству слогов. skipSylb используется для отметки, если последний символ был также слогом. Если skipSylb = 1, то это блок гласных, и мы хотим добавить только один в счетчик. Теперь у меня есть переменная isE, которая в следующий раз просто сообщает программе, что последней буквой была буква E. Это означает, что в следующий раз в цикле while это конец предложения или пробел, а последняя буква была E (то есть E = 1), тогда мы добавили слишком много слогов.

Надеюсь, это поможет.

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

 if(isE == 1)
       {
           countSylb --;
       } 

Это утверждение происходит, когда символ является пробелом или символом конца предложения. Я не могу думать ни о чем другом, но я все еще чувствую, что я не включаю достаточно Ну что ж, дайте мне знать, если что-то неясно.

Ответы [ 3 ]

2 голосов
/ 07 февраля 2010

У меня также есть его настройка, чтобы, когда программа читает!:;.? или пробел, он будет смотреть на последний прочитанный символ, а если это символ e, он уберет один из числа слогов.

Это звучит неправильно. А как насчет слов, как "умереть" и "увидеть"? Очевидно, что вы можете уменьшить счетчик только в том случае, если слово насчитывает более одного слога.

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

Если это не поможет: Может быть, вы не снимаете флажок гласного после чтения согласного? Я не могу сказать из вашего кода.

Что действительно может вам помочь - это отладка выходных данных. Пусть программа расскажет вам, что она делает:

«Читайте гласную: e»

"Не считая гласного, потому что [...]"

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

Вам нужен Конечный автомат


В некотором смысле каждая программа является конечным автоматом, но обычно в программной ракетке под словом " конечный автомат " мы подразумеваем строго организованный цикл, который выполняет что-то вроде:

while (1) {
  switch(current_state) {
    case STATE_IDLE:
      if (evaluate some condition)
        next_state = STATE_THIS;
      else
        next_state = STATE_THAT;
      break
    case STATE_THIS:
      // some other logic here
      break;
    case STATE_THAT:
      // yet more
      break;
  }
  state = next_state;
}

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

По крайней мере, организуя поток управления в конечный автомат, вы сжимаете часть логики в одну плоскость, и становится намного проще визуализировать операции и вносить отдельные изменения. Создается структура, которая, хотя редко является кратчайшим из возможных выражений, по крайней мере, легко модифицируется и постепенно изменяется.

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

Глядя на ваш код, я подозреваю, что некоторая логика потерялась в чрезмерном размере. Ваш основной фрагмент выглядит примерно так:

chrctr = tolower(chrctr);

if (strchr(chrctr, "aeiou")) {
    isE = (chrctr == 'e');
    endSylb = !skipSylb;
    skipSylb = 1; // May not be you want, but it's what you have.
}
else {
    skipSylb = endSylb = 0;
}

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

...