回到同一个项目的另一个问题! 该项目是针对编程课程(Java)的第一学期入门,对于该项目,我们必须仅使用我们迄今为止学到的知识来计算一些示例文本的FRI。
我的问题是:如何使用for循环计算音节。到目前为止,我已经设置了通过每个字母,检查元音,当它看到元音时停止,然后检查下一个字母是否有另一个元音或其他字符。
如果我用元音计算单词中的音节并遵循我的前两条规则,它就有效。
但是,我不知道如何将单个单词中没有任何元音作为单个音节计数。
以下是我们必须遵循的音节计数规则:
- 单词中包含的音节数基于元音的出现次数,即字符a,e,i,o,u with 以下修改:
醇>一个。每组相邻的元音都算作一个音节。例如, “真实,空气,声音,牙齿,肥皂”都是单音节词 “豪华”有两个音节,“连续”有三个和“排队” 一。 '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
答案 0 :(得分:1)
以下是您发布的代码的一些评论:
字符串相等与字符串排序
word.compareTo("") != 0
有点奇怪。 compareTo
通常用于字母目的。也许您想使用!word.equals("")
多余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 == ' '
可能永远不会发生
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;必须被忽略
测试永远不会发生+最终&#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++;
}
如果nextLetter
为D or d
:它是D
,则nextLetter != 'd'
为真,否则nextLetter != 'D'
已经true
接下来的测试永远不会发生。另外,你不要忽视最后的&#34; ed&#34;这里是因为如果它是eD
,nextLetter != 'd'
是真的,如果它是ed
那么nextLetter != 'D'
就是真的
您似乎不会跳过连续的元音
我的建议是有两种专用方法,以便于阅读:
要检查的方法是字母是否是元音,显然是不区分大小写的:
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';
}
然后,计算给定单词的音节数的方法与你的相比有一些修改:
我首先检查一封信是否是一个元音:
2.1 它不是元音:音节数不会增加且指针向前移动
2.2 元音不是&#34; E&#34; :音节数增加1,指针移动到下一个非元音字母
2.3 元音是E :检查&#34; e&#34;是最后一个字母,或者如果它是前一个字母后跟一个&#34; d&#34;:在这种情况下,遵循规则2.1,否则,遵循规则2.2
Math.max(count, 1)
,我确保至少返回1
代码是:
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
进行测试。如果找到模式,则返回匹配的字符,并针对剩余的字符测试模式,直到找不到任何内容。这将使用Pattern
和Matcher
类
代码看起来像
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