【问题标题】:StringTokenizer vs split() in a program程序中的 StringTokenizer 与 split()
【发布时间】:2015-02-16 08:33:01
【问题描述】:

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

这是我的代码:

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);
    }
}
}

班级名称很奇怪,因为这是我的计算机考试中提出的问题。

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

但是为什么呢? StringTokenizer 不是和split(" ") 做同样的事情吗?

【问题讨论】:

  • 顺便说一句,由于缺少空格/大括号和糟糕的变量名(s1s2),您的代码很难阅读。具体是哪一行抛出NullPointerException

标签: java string stringtokenizer stringbuffer


【解决方案1】:

StringTokenizer 的 countTokens 方法的 API 文档说:

计算此分词器的 nextToken 方法的次数 可以在它产生异常之前调用。当前位置 不高级。

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

您可以通过使用调试器或将 printlns 添加到代码中来检查这种情况。

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

StringTokenizer 是为了兼容性而保留的遗留类 原因尽管在新代码中不鼓励使用它。推荐 任何寻求此功能的人都使用 String 的 split 方法 或 java.util.regex 包。

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

【讨论】:

  • 一种解决方案是将初始令牌数存储到一个变量中,然后在循环条件中使用该变量。 int numTokens = st.countTokens(); for(int x=0; x &lt; numTokens; x++) {//do stuff}
  • 或者使用 while(st.hasMoreTokens) 并增加你的计数器。但是对于手头的问题,tokenizer 做得很好,NPE 是由结果的使用引起的。 @D V - 请记住,默认标记器集确实不仅仅是空间作为其分隔符的一部分,仅供将来参考。
【解决方案2】:

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

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

【讨论】:

  • 但是为什么 StringTokenizer 返回的是空值呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多