2015-02-16 2 views
3

Мне нужно загладить первый символ каждого слова в предложении. Первый символ первого слова находится в верхнем регистре, и предложение должно быть прекращено только с полной остановкой или вопросительным знаком. Затем я должен считать все гласные и согласные в каждом слове приговора.StringTokenizer vs split() в программе

Вот мой код:

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

Имя класса свойственен, потому что это был вопрос, заданный в моем компьютерном экзамене.

Программа несколько работает, но я получаю NullPointerException по какой-то причине на внутренней петле for в main(). Но когда, как я прокомментировал в программе, если я использую функцию split(" "), программа работает правильно.

Но почему? Не StringTokenizer делать то же, что split(" ")?

+1

Просто в сторону, ваш код трудно читать из-за отсутствия интервалов/фигурных скобок и слабых имен переменных ('s1',' s2'). И в частности, какая линия бросает «NullPointerException»? – ryanyuyu

ответ

4

Документация API для метода countTokens StringTokenizer говорит:

Вычисляет число раз, что метод nextToken этого Tokenizer в можно назвать, прежде чем он генерирует исключение. Текущая позиция не продвинута.

Вы вызываете его в цикле for так, как если бы вы ожидали, что он будет оставаться постоянным, но он уменьшается на 1 каждый раз, когда вы продвигаетесь другим токеном. Поэтому, если ваша строка имеет 4 жетона, вы получаете только первые два. Вы остаетесь с нулями в своем массиве строк.

Вы можете проверить это, используя отладчик или добавить printlns в свой код.

Существует несколько решений. Вы можете исправить код, чтобы сохранить счетчик токенов, а не продолжать вызов метода. Лучше, метод hasMoreTokens существует именно для этой ситуации, используйте его. Или вы могли бы следовать советам в документации:

StringTokenizer является наследием класс, который сохраняется для совместимости причины, хотя его использование не рекомендуется в новом коде. Рекомендуется , что любой, кто ищет эту функцию, использует метод split String или пакет java.util.regex.

Ознакомьтесь с документацией. Когда что-то не ведет себя так, как вы предполагаете, следует тщательно изучить документацию, чтобы убедиться, что ваши предположения действительно действительны.

+0

Решение состоит в том, чтобы сохранить начальное число токенов в переменной, а затем использовать эту переменную в состоянии цикла. 'int numTokens = st.countTokens(); for (int x = 0; x ryanyuyu

+1

Или используйте while (st.hasMoreTokens) и увеличивайте счетчик. Но в вопросе под рукой токенизатор выполнил свою работу должным образом, NPE был вызван использованием результата. @D V - Имейте в виду, что набор tokenizer по умолчанию имеет больше, чем просто пространство, как часть его разделителей только для использования в будущем. – Michael

-1

Чтобы извлечь выгоду из каждого слова, вы можете использовать WordUtils.capitalize(str) от Apache Lang.

Гласные и согласные методы подсчета могут быть найдены в this thread в SO.

+1

Но почему именно StringTokenizer возвращает нулевые значения? –

Смежные вопросы