for循环来计算Java中的音节

时间:2017-10-22 16:16:04

标签: java loops for-loop count

回到同一个项目的另一个问题! 该项目是针对编程课程(Java)的第一学期入门,对于该项目,我们必须仅使用我们迄今为止学到的知识来计算一些示例文本的FRI。

我的问题是:如何使用for循环计算音节。到目前为止,我已经设置了通过每个字母,检查元音,当它看到元音时停止,然后检查下一个字母是否有另一个元音或其他字符。

如果我用元音计算单词中的音节并遵循我的前两条规则,它就有效。

但是,我不知道如何将单个单词中没有任何元音作为单个音节计数。

以下是我们必须遵循的音节计数规则:

  
      
  1. 单词中包含的音节数基于元音的出现次数,即字符a,e,i,o,u with   以下修改:
  2.         

    一个。每组相邻的元音都算作一个音节。例如,   “真实,空气,声音,牙齿,肥皂”都是单音节词   “豪华”有两个音节,“连续”有三个和“排队”   一。 'y'的作用含糊不清。它可以是一个辅音(“年”,   “皇家”,“是”)和元音(“by”,“丑陋”,“很多”)。我们忽略'y'   模棱两可,你的程序必须把它作为辅音。

         

    湾单词末尾的'-e'或'-ed'不算作音节   例如,单词"验证"有四个元音但只有三个元音   音节。规则b消除实际的只有很少的单词   音节(例如't'或'd'之后的'-ed'不是沉默的),等等   遗漏不会严重扭曲测试结果。你应该   同时注意到最后双重'e'的单词不会丢失   他们统计的音节。例如,“委员会”有三个   音节数。该规则也可能会增加计数   实例无忧无虑的规则有三个音节,但听起来像   有两个。有一个重要的例子,当b被推翻为   在下一节c。

    中解释      

    ℃。每个单词至少有一个音节即使一个单词不包含   任何元音,或以前的规则给出的数量为零,它仍然是   算作有一个音节。例如,单词str,grrrr,   pp,the,she,he,fed,led“都有一个音节

这是我到目前为止的代码:

// While loop to count words and increment syllable count per word
while(countWords.hasNext()){
    String word = countWords.useDelimiter(WORD_DELIMITERS).next();

    if(word.compareTo("") != 0){
        numWords++;

        for(k=0; k < word.length(); k++){
            char letter = word.charAt(k);

            if(letter == 'A' || letter == 'a' 
                || letter == 'I' || letter == 'i' 
                || letter == 'O' || letter == 'o' 
                || letter == 'U' || letter == 'u'){
                if(k+1 < word.length()){
                    char nextLetter = word.charAt(k+1);

                    if(nextLetter == 'A' || nextLetter == 'a' 
                        || nextLetter == 'E' || nextLetter == 'e' 
                        || nextLetter == 'I' || nextLetter == 'i' 
                        || nextLetter == 'O' || nextLetter == 'o' 
                        || nextLetter == 'U' || nextLetter =='u' 
                        || nextLetter == ' '){
                        numSyllables++;
                    }
                    else{
                        numSyllables++;
                    }
                }
            }
            else if(letter == 'E' || letter == 'e'){
                if(k+1 < word.length()){
                    char nextLetter = word.charAt(k+1);

                    if(nextLetter != 'D' || nextLetter != 'd' 
                        || nextLetter != 'A' || nextLetter != 'a' 
                        || nextLetter != 'I' || nextLetter != 'i' 
                        || nextLetter != 'O' || nextLetter != 'o' 
                        || nextLetter != 'U' || nextLetter !='u' 
                        || nextLetter == ' '){
                        numSyllables++;
                    }
                }
            }
        }
        if(numSyllables == 0){
            numSyllables = 1;
        }
        System.out.println((numWords) + " " + word + " " + numSyllables);
        numSyllables = 0;
    }
}

打印输出示例:

  

1你好1 2世界1 3这1 4是1 5只是1 6 a 1 7测试1 8到   1 9见1 10 10如何1 11我的1 12程序2 13工作1 14 up 1 15   到1 16这1 17点2 18我&1 39 19 1 1肯定1 21我   1 22 22 3 2 2 24 2 1 1 2 2 1 1 26 27   1 28 I&#39; m 1 29不是1 30肯定1

1 个答案:

答案 0 :(得分:1)

评论您的代码

以下是您发布的代码的一些评论:

  1. 字符串相等与字符串排序

    word.compareTo("") != 0
    

    有点奇怪。 compareTo通常用于字母目的。也许您想使用!word.equals("")

  2. 多余if...else...

    if(nextLetter == 'A' || nextLetter == 'a' 
        || nextLetter == 'E' || nextLetter == 'e'
        || nextLetter == 'I' || nextLetter == 'i'
        || nextLetter == 'O' || nextLetter == 'o'
        || nextLetter == 'U' || nextLetter =='u'
        || nextLetter == ' '){
        numSyllables++;
    }
    else{
        numSyllables++;
    }
    

    因此,如果条件为true false,那么您最终会得到numSyllables++,因此没有条件拥有该条件。 ..此外,如果你只有无空格的话,nextLetter == ' '可能永远不会发生

  3. Final&#34; a&#34;,&#34; i&#34;,&#34; u&#34;,&#34; o&#34;被忽略了:

    if (letter == 'A' ...){
        if(k+1 < word.length()){
            ...
        }
    }
    

    这意味着如果k == word.length() - 1,你什么都不做。在单词Vienna中,您将忽略最后一个&#34; a&#34;。你为这封信做了同样的事情&#34; e&#34;这是最后的正确&#34; e&#34;必须被忽略

  4. 测试永远不会发生+最终&#34; ed&#34; /&#34; eD&#34;不要忽视

    if(nextLetter != 'D' || nextLetter != 'd' 
        || nextLetter != 'A' || nextLetter != 'a' 
        || nextLetter != 'I' || nextLetter != 'i' 
        || nextLetter != 'O' || nextLetter != 'o' 
        || nextLetter != 'U' || nextLetter !='u' 
        || nextLetter == ' '){
        numSyllables++;
    }
    

    如果nextLetterD or d:它是D,则nextLetter != 'd'为真,否则nextLetter != 'D'已经true接下来的测试永远不会发生。另外,你不要忽视最后的&#34; ed&#34;这里是因为如果它是eDnextLetter != 'd'是真的,如果它是ed那么nextLetter != 'D'就是真的

  5. 您似乎不会跳过连续的元音

  6. 循环计数

    我的建议是有两种专用方法,以便于阅读:

    1. 检查字母是否为元音的方法
    2. 计算音节数的方法
    3. 要检查的方法是字母是否是元音,显然是不区分大小写的:

      private static boolean isVowel(char letter) {
          return letter == 'A' || letter == 'a'
                  || letter == 'E' || letter == 'e'
                  || letter == 'O' || letter == 'o'
                  || letter == 'I' || letter == 'i'
                  || letter == 'U' || letter == 'u';
      }
      

      然后,计算给定单词的音节数的方法与你的相比有一些修改:

      1. 我使用 while循环:因为你需要跳过连续的元音,一个&#34;指针&#34;将使用并浏览单词
      2. 我首先检查一封信是否是一个元音

        2.1 它不是元音:音节数不会增加且指针向前移动

        2.2 元音不是&#34; E&#34; :音节数增加1,指针移动到下一个非元音字母

        2.3 元音是E :检查&#34; e&#34;是最后一个字母,或者如果它是前一个字母后跟一个&#34; d&#34;:在这种情况下,遵循规则2.1,否则,遵循规则2.2

      3. 将计数回报与1 进行比较:使用Math.max(count, 1),我确保至少返回1
      4. 代码是:

        private static int countWithLoop(String word) {
            // start counting
            int syllableCount = 0;
        
            // use a while loop
            int index = 0;
            while (index < word.length()) {
                char letter = word.charAt(index);
        
                // if vowel:
                if (isVowel(letter)) {
                    // specific case of "E"/"e"
                    if (letter == 'E' || letter == 'e') {
        
                        // 1. last "e" is ignored:
                        if (index == word.length() - 1) {
                            index++;
                        }
                        // 2. if "ed" finished the word, it is ignored
                        else if (index == word.length() - 2
                                && (word.charAt(word.length() - 1) == 'd' || word.charAt(word.length() - 1) == 'D')) {
                            index++;
                        }
                        // 3. this is neither a last "e" or last "ed". Count as a syllable
                        else {
                            // count one more syllable...
                            syllableCount++;
                            // ...and skip consecutive vowel
                            while (isVowel(letter) && index < word.length() - 1) {
                                index++;
                                letter = word.charAt(index);
                            }
                        }
                    } else {
                        // count one more syllable...
                        syllableCount++;
                        // ...and skip consecutive vowel
                        while (isVowel(letter) && index < word.length() - 1) {
                            index++;
                            letter = word.charAt(index);
                        }
                    }
                }
                // otherwise, keep going
                else {
                    index++;
                }
            }
        
            // return
            return Math.max(1, syllableCount);
        }
        

        使用正则表达式计数

        另一种解决方案,有点复杂,但也有点有趣,是使用正规快递,称为正则表达。它基本上需要一个模式,模式将针对String进行测试。如果找到模式,则返回匹配的字符,并针对剩余的字符测试模式,直到找不到任何内容。这将使用PatternMatcher

        代码看起来像

        private static int countWithRegex(String word) {
            String i = "(?i)[aiou][aeiou]*|e[aeiou]*(?!d?\\b)";
            Matcher m = Pattern.compile(i).matcher(word);
            int count = 0;
        
            while (m.find()) {
                count++;
            }
        
            // return at least 1
            return Math.max(count, 1);
        }
        

        关于i的一些解释:

        (?i)[aiou][aeiou]*|e[aeiou]*(?!d?\\b)   = complete regex
        (?i)                                    = case insensitivity: A=a, B=b and so on
            [aiou]                              = look for letter "a", "i", "o", "u", and their 
                                                   capital letter counterpart
                         *                      = look for the characters between the bracket 
                                                  with zero, one or more occurences
            [aiou][aeiou]*                      = look for non-E vowel followed a zero, one 
                                                  or more vowel. Like "a", or "Oa", or "ueu"
                          |                     = Or ...
                           e                    = simple look for letter "e" or "E"
                            [aeiou]*            = same as above: look for "e" followed by 
                                                  consecutive vowels
                                    (?!.....)   = but exclude "e"/"E" when followed by...
                                       d?\\b    = ...an optional "d"/"D" letter and \\b refer 
                                                  to the end of the String: it excludes final
                                                  "e" and final "ed"
        

        主要

        这是主要的:

        public static void main(String... aArgs) {
        
            List<String> words = new ArrayList<>();
            words.add("real");
            words.add("air");
            words.add("sound");
            words.add("tooth");
            words.add("soap");
            words.add("regal");
            words.add("continuous");
            words.add("queueing");
            words.add("committee");
            words.add("carefree");
            words.add("grrrr");
            words.add("she");
            words.add("fed");
            // Challenge the "ed" but not at the end of the word
            words.add("Medecine");
            // Challenge a final "e"
            words.add("Stone");
            // Challenge a final "ed"
            words.add("Stoned");
            // Challenge a double vowel
            words.add("Year");
            // Challenge case sensitivity
            words.add("BoAr");
            // Expected answer depends on the number of drink Andy has taken
            words.add("Vacuum");
        
            System.out.println("----Counting with Loop----");
            for (int i = 0; i < words.size(); i++) {
                System.out.println(i + " " + words.get(i) + " " + countWithLoop(words.get(i)));
            }
            System.out.println("----Counting with Regex----");
            for (int i = 0; i < words.size(); i++) {
                System.out.println(i + " " + words.get(i) + " " + countWithRegex(words.get(i)));
            }
        }
        

        随后输出:

        ----Counting with Loop----
        0 real 1
        1 air 1
        2 sound 1
        3 tooth 1
        4 soap 1
        5 regal 2
        6 continuous 3
        7 queueing 1
        8 committee 3
        9 carefree 3
        10 grrrr 1
        11 she 1
        12 fed 1
        13 Medecine 3
        14 Stone 1
        15 Stoned 1
        16 Year 1
        17 BoAr 1
        18 Vacuum 2
        ----Counting with Regex----
        0 real 1
        1 air 1
        2 sound 1
        3 tooth 1
        4 soap 1
        5 regal 2
        6 continuous 3
        7 queueing 1
        8 committee 3
        9 carefree 3
        10 grrrr 1
        11 she 1
        12 fed 1
        13 Medecine 3
        14 Stone 1
        15 Stoned 1
        16 Year 1
        17 BoAr 1
        18 Vacuum 2