程序中的 StringTokenizer 与 split()

StringTokenizer vs split() in a program

我必须将句子中每个单词的第一个字符大写。第一个单词的第一个字符是大写的,句子只能以句号或问号结束。然后我必须数出句子中每个单词的所有元音和辅音。

这是我的代码:

import java.io.*;
import java.util.*;
class ISC_Prac_2015
{
String s;
ISC_Prac_2015()
{
    s="";
}

void input()throws IOException
{
    System.out.println("Enter a sentence :");
    BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
    s=buf.readLine();
    if(!((s.charAt(s.length()-1)=='.'||s.charAt(s.length()-1)=='?')))
    {
        System.out.println("Invalid input.");
        System.exit(0);
    }
}

char changeToUpper(char c)
{
    return Character.toUpperCase(c);
}

boolean isVowel(char c)
{
    if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u'||c=='A'||c=='E'||c=='I'||c=='O'||c=='U')
        return true;
    else
        return false;
}

void main()throws IOException
{
    input();
    String s2=s.substring(0,s.length()-1);
    StringBuffer s3=new StringBuffer(s2);
    for(int x=0;x<s3.length()-1;x++)
        if(s3.charAt(x)==' ')
            s3.setCharAt(x+1,changeToUpper(s3.charAt(x+1)));
    String s4=s3.toString();
    System.out.println("\n"+s4);
    StringTokenizer st=new StringTokenizer(s4);
    String a[]=new String[st.countTokens()];
    for(int x=0;x<st.countTokens();x++)
    a[x]=st.nextToken();
    /*replace the 4 lines above with String a[]=s4.split(" ");
      and the program works, but why?*/
    System.out.println("Word\t\t"+"Vowels\t\t"+"Consonants");
    int vowel=0,consonant=0;
    for(int x=0;x<a.length;x++)
    {
        for(int y=0;y<a[x].length();y++)
            if(isVowel(a[x].charAt(y)))
                vowel++;
            else
                consonant++;
        if(a[x].length()<8)
            System.out.println(a[x]+"\t\t"+vowel+"\t\t"+consonant);
        else if(a[x].length()>=8&&a[x].length()<16)
            System.out.println(a[x]+"\t"+vowel+"\t\t"+consonant);
        else
            System.out.println(a[x]+vowel+"\t\t"+consonant);
    }
}
}

class 这个名字很特别,因为这是我计算机考试中的一道题。

该程序有些工作,但由于某种原因,我在 main() 的内部 for 循环中得到了一个 NullPointerException。但是,正如我在程序中评论的那样,如果我使用 split(" ") 函数,程序可以正常工作。

但是为什么呢? StringTokenizersplit(" ") 做的事情不一样吗?

要将每个单词大写,您可以使用 WordUtils.capitalize(str) from Apache Lang

元音和辅音计数技术可以在 SO 中的 this thread 中找到。

StringTokenizer 的 countTokens 方法的 API 文档说:

Calculates the number of times that this tokenizer's nextToken method can be called before it generates an exception. The current position is not advanced.

您在 for 循环中调用它,就好像您希望它保持不变一样,但每次您前进另一个标记时它都会减少 1。所以如果你的字符串有 4 个标记,你只会得到前两个。您的字符串数组中剩下空值。

您可以使用调试器或在代码中添加 printlns 来检查此类问题。

有几种解决方案。您可以修复代码以预先存储令牌计数,而不是继续调用该方法。更好的是,hasMoreTokens 方法正是针对这种情况,使用它。或者您可以遵循文档中的建议:

StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.

查看文档。当某些事情不像您假设的那样运行时,请仔细检查文档以查看您的假设是否真的有效。