2011-04-12 15 views
2

下面的代碼來自於我的教科書中的一個賦值,用於輸入用戶輸入名稱並大寫首字母和姓的第一個字母的簡單程序。該代碼正常工作,但我不明白爲什麼name.substring()正常工作。具體來說,我感興趣的是第24-29行的區塊是如何工作的。如果用戶輸入名稱「Johnny Johnson」,則i應該包含進入第29行的值7。如果i確實包含7,則不應該包含「Johnny J」,其應該使得第29行實際存儲「JohnnyJJohnson」在String name?但實際上它應該存儲「約翰尼約翰遜」。有關String.substring(int,int)如何工作的幫助

我的第二個問題來自這個代碼搞亂看到不同的結果。如果我改變線29的第一部分name = name.substring(0, i-1)我得到(使用Eclipse)的錯誤:在線程

異常「主」 java.lang.StringIndexOutOfBoundsException: 字符串索引超出範圍:在java的15 .lang.String.charAt(String.java:558) 在 RepairName.main(RepairName.java:17)

爲什麼在第17行,而不是第29行出現錯誤?其實,爲什麼我會得到一個錯誤,因爲i-1實際上並沒有改變i的值是否正確?我認爲它與循環有關,但由於i的值沒有改變,所以我不知道它爲什麼會這樣。

對不起,這是一個冗長的問題。我對Java很陌生,對編程也很新穎(顯然),但是我很欣賞你們所有人都能提供的見解。謝謝!

1 import javax.swing.*; 
2 
3 public class RepairName 
4 { 
5 public static void main(String[] args) 
6 { 
7  String name, saveOriginalName; 
8   int stringLength; 
9   int i; 
10   char c; 
11   name = JOptionPane.showInputDialog(null, "Please enter your first and last name"); 
12  
13   saveOriginalName = name; 
14   stringLength = name.length(); 
15   for (i = 0; i < stringLength; i++) 
16   { 
17     c = name.charAt(i); 
18     if (i == 0) 
19     { 
20       c = Character.toUpperCase(c); 
21       name = c + name.substring(1, stringLength); 
22     } 
23     else 
24      if(name.charAt(i) == ' ') 
25       { 
26        i++; 
27         c = name.charAt(i); 
28         c = Character.toUpperCase(c); 
29         name = name.substring(0, i) + c + name.substring(i+1, stringLength); 
30       } 
31   } 
32   JOptionPane.showMessageDialog(null, "Original name was " + saveOriginalName + "\nRepaired name is " + name); 
33 } 
34 
35 } 

回答

3

String.subString(int, int)的javadoc:

public String substring(int beginIndex, int endIndex) 

返回一個新字符串,它是此字符串的一個子 。子字符串 子字符串從指定的 beginIndex開始,並在索引endIndex - 1處擴展到 字符。因此 子字符串的長度爲 endIndex-beginIndex。

繼承人的鏈接:http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#substring(int,INT)

如有疑問看的javadoc:d

關於你的第二quesstion,再次的Javadoc(http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#charAt(int))爲charAt(int)爲您排憂解難:

拋出:IndexOutOfBoundsException - 如果 索引參數大於該STRI的長度負或不 更少NG。

如果你在你的子串由1每次找到一個' '時間遞減名的大小使用i-1。這意味着它將迭代15次,但在找到' '之後,name將只有14個字符長。

+0

非常感謝您的解釋!我甚至沒有想到循環的第一次迭代......我只是想着最後一個。我有很多東西需要學習。感謝您的鏈接 – knobcreekman 2011-04-12 21:55:28

+0

小調:我們現在有1.6(但是子串當然沒有改變)。 – 2011-04-12 21:56:14

+0

真的,大聲笑我剛剛搜索了Java字符串API,並得到了第一擊:D – Tnem 2011-04-12 21:57:22

1

引述substring的Javadoc,

的串開始在指定的beginIndex和延伸到字符索引endIndex - 1的

換句話說,endIndex是不包括在結果中。

至於你的第二個問題,它與你有關,減少循環內的name的長度。你的循環條件(i < stringLength)和你看看name.charAt(i)的事實假定name的長度保持不變(或最小不減少)。當你開始縮短字符串的時候,這會受到侵犯。

+0

非常感謝解釋! – knobcreekman 2011-04-12 21:56:06

1

這是正確的子工程是這樣的:

public String substring(int beginIndex, int endIndex) 

返回一個新字符串,它是此字符串的一個子 。子字符串 子字符串從指定的 beginIndex開始,並在索引endIndex - 1處擴展到 字符。因此 子字符串的長度爲 endIndex-beginIndex。

所以子(0,7),它需要0..6個字符的字符串從


注意,這是非常糟糕的做法,修改for循環(我++裏面換迭代的價值循環體)。如果在空間之後你沒有任何其他字符,你會遇到異常

+0

我感謝您的幫助! – knobcreekman 2011-04-12 21:56:52

1

嗨你得到的異常,因爲你遍歷字符串,但在for循環中,你實際上正在改變字符串length name = name.substring(0 ,i)+ c + name.substring(i + 1,stringLength); 所以,當你仍然在循環中,名稱的大小不再等於舊的stringLength。

米堡

1
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 15 at java.lang.String.charAt(String.java:558) at RepairName.main(RepairName.java:17) 

發生,因爲你是第21行和29改變name和保持的name相同的長度stringLength

1

廣告1)的javadoc,是一個很好的參考,下面的java .lang.String.substring(...):

public String substring(int beginIndex, int endIndex) 

返回一個新字符串,該字符串是此字符串的子字符串。子字符串 子字符串從指定的 beginIndex開始,並在索引endIndex - 1處擴展到 字符。因此 子字符串的長度爲 endIndex-beginIndex。

的好處,在排除年底的指數,是,你可以sequently遍歷值:

a [0] = x.substring (0, 5); 
a [1] = x.substring (5, 10); 
a [2] = x.substring (10, 15); 

// or 

a [i] = x.substring (i*5, (i+1)*5); 
+0

感謝您的幫助!第二部分有點超過我的頭雖然*尷尬* – knobcreekman 2011-04-12 21:59:14

+0

一個序列(5,10,...)的結尾可以是下一個序列的開始(...,5,10)。另一個好處是,您可以使用String.length作爲不帶-1的結束索引。不是很重要,只是方便。 – 2011-04-13 00:37:58

+0

好吧,我現在明白了。再次感謝 – knobcreekman 2011-04-13 01:04:18

1

廣告2)

你不改變我自己,但name在這裏被截斷:

name = name.substring(0,i-1)+ c + name.substring(i + 1,stringLength);

但外環沒有通知新的長度。

廣告3)(代碼審查):

還應當聲明並儘可能晚地初始化變量,並標記儘可能決賽。這告訴你,在初始化之後,你不必擔心它們。

鑑於此代碼:

import javax.swing.*; 

public class RepairName 
{ 
    public static void main(String[] args) 
    { 
     final String name = JOptionPane.showInputDialog(null, "Please enter your first and last name"); 
     final String saveOriginalName = name; 
     final int stringLength = name.length(); 
     System.out.println (name); 
     for (int i = 0; i < stringLength; i++) 
     { 
       final char c = name.charAt (i); 
       if (i == 0) 
       { 
         char upper = Character.toUpperCase (c); 
         name = upper + name.substring (1, stringLength); 
       } 
       else 
        if (c == ' ') 
         { 
          i++; 
           final char c2 = name.charAt (i); 
           final char upper = Character.toUpperCase (c2); 
           name = name.substring (0, i-1) + upper + name.substring (i+1, stringLength); 
         } 
     } 
     JOptionPane.showMessageDialog (null, "Original name was " + saveOriginalName + "\nRepaired name is " + name); 
    } 
} 

你會得到一個錯誤信息,對於名稱爲決賽。也許這會阻止你意外地與長度不同步。

修改,有一個可變的UPNAME,但遍歷名稱:

String upName = null; 
    for (int i = 0; i < stringLength; i++) 
    { 
      final char c = name.charAt (i); 
      if (i == 0) 
      { 
        char upper = Character.toUpperCase (c); 
        upName = upper + name.substring (1, stringLength); 
      } 
      else 
       if (c == ' ') 
        { 
         i++; 
          final char c2 = name.charAt (i); 
          final char upper = Character.toUpperCase (c2); 
          upName = upName.substring (0, i-1) + upper + name.substring (i+1, stringLength); 
        } 
    } 
    JOptionPane.showMessageDialog (null, "Original name was " + saveOriginalName + "\nRepaired name is " + upName); 

給你,輸入「HONKY tonky」輸出「HonkyTonky」,這將導致你的方式,子(從,到)的作品,也許。 :)