eclipse 帮助 String.substring(int, int) 如何工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5641980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 16:09:11  来源:igfitidea点击:

help with how String.substring(int, int) works

javaeclipse

提问by knobcreekman

the code below is from an assignment in my text book for a simple program that takes a user's entered name and capitalizes the first letter of the first and last name. The code works properly, but I do not understand why the name.substring()works correctly. Specifically, I am interested in how the block from lines 24 - 29 works. If the user enters the name "Johnny Johnson", then ishould contain the value 7 going into line 29. If idoes contain 7, then shouldn't name = name.substring(0, i)contain "Johnny J" which should make line 29 actually store "Johnny JJohnson" in String name? But instead it actually stores "Johnny Johnson" as it should.

下面的代码来自我教科书中的一个简单程序的作业,该程序采用用户输入的姓名并将名字和姓氏的第一个字母大写。代码工作正常,但我不明白为什么name.substring()工作正常。具体来说,我对第 24 - 29 行的块如何工作感兴趣。如果用户输入名称“Johnny Johnson”,i则应包含进入第 29 行的值 7。如果i确实包含 7,则不应name = name.substring(0, i)包含“Johnny J”,这将使第 29 行实际存储“Johnny JJohnson” String name?但实际上它应该存储“Johnny Johnson”。

My second question comes from messing around with this code to see different results. If I change the first part of line 29 to name = name.substring(0, i-1)I get the error (using Eclipse):

我的第二个问题来自弄乱这段代码以查看不同的结果。如果我将第 29 行的第一部分更改为name = name.substring(0, i-1)出现错误(使用 Eclipse):

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)

线程“main”中的异常 java.lang.StringIndexOutOfBoundsException: String index out of range: 15 at java.lang.String.charAt(String.java:558) at RepairName.main(RepairName.java:17)

Why does the error appear on line 17 instead of line 29? Actually, why do I get an error at all because i-1isn't actually changing the value of icorrect? I assumed it had something to do with the loop but since the value of iwasn't changed I didn't know why it would.

为什么错误出现在第 17 行而不是第 29 行?实际上,为什么我会收到错误消息,因为i-1实际上并没有改变i正确的值?我认为它与循环有关,但由于 的值i没有改变,我不知道为什么会改变。

Sorry if this was a long-winded question. I'm new to Java and pretty new to programming (obviously), but I appreciate any insight you all can give. Thanks!

对不起,如果这是一个冗长的问题。我是 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 }

回答by Tnem

From the String.subString(int, int)javadoc:

String.subString(int, int)javadoc:

public String substring(int beginIndex, int endIndex)

Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

返回一个新字符串,它是此字符串的子字符串。子字符串从指定的 beginIndex 开始,并延伸到索引 endIndex - 1 处的字符。因此子字符串的长度是 endIndex-beginIndex。

Heres the link: http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#substring(int, int)

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

If in doubt look at the javadocs :D

如果有疑问,请查看 javadocs :D

As for your second quesstion, again the javadocs ( http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#charAt(int) ) for charAt(int)help you out:

至于你的第二个问题,javadocs(http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#charAt(int ))再次charAt(int)帮助你:

Throws: IndexOutOfBoundsException - if the index argument is negative or not less than the length of this string.

抛出: IndexOutOfBoundsException - 如果索引参数为负或不小于此字符串的长度。

If you use i-1in substring you are decreasing the size of name by 1 each time it finds a ' '. This means it will iterate 15 times, but the namewill only be 14 characters long after the ' 'is found.

如果您i-1在子字符串中使用,则每次找到一个' '. 这意味着它将迭代 15 次,但在找到name后将只有 14 个字符长' '

回答by NPE

To quote the substringJavadoc,

引用substringJavadoc,

The substring begins at the specified beginIndex and extends to the character at index endIndex - 1.

子字符串从指定的 beginIndex 开始,并扩展到索引 endIndex - 1 处的字符。

In other words, endIndexis not included in the result.

换句话说,endIndex不包括在结果中。

As to your second question, it has to do with you reducing the length of nameinside the loop. Your loop condition (i < stringLength) and the fact that you look at name.charAt(i)assume that the length of nameremains constant (or least does not decrease). This gets violated the moment you start shortening the string.

至于你的第二个问题,它与你减少name循环内部的长度有关。您的循环条件 ( i < stringLength) 以及您查看的事实name.charAt(i)假定 的长度name保持不变(或至少不会减少)。当您开始缩短字符串时,这会被违反。

回答by lukastymo

that's correct substring works in this way:

这是正确的子字符串以这种方式工作:

public String substring(int beginIndex, int endIndex)

Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

返回一个新字符串,它是此字符串的子字符串。子字符串从指定的 beginIndex 开始,并延伸到索引 endIndex - 1 处的字符。因此子字符串的长度是 endIndex-beginIndex。

so for substring(0, 7) it takes 0..6 chars from string

所以对于 substring(0, 7) 它从 string 中取出 0..6 个字符



Notice that this is really bad practice to modify iterate's value in for-loop (i++ inside for-loop-body). If after space you haven't any other chars, you'll encounter exception

请注意,在 for 循环(for 循环体中的 i++)中修改 iterate 的值是非常糟糕的做法。如果在空格之后你没有任何其他字符,你会遇到异常

回答by Boro

Hi You get the Exception because you iteratate over the string but in the for loop you are actually changing the strings length name = name.substring(0, i) + c + name.substring(i+1, stringLength); So while you are still in the loop the size of the name is no longer equal to the old stringLength.

嗨,您得到异常是因为您遍历字符串,但在 for 循环中您实际上是在更改字符串长度 name = name.substring(0, i) + c + name.substring(i+1, stringLength); 因此,当您仍在循环中时,名称的大小不再等于旧的 stringLength。

Boro

博罗

回答by pjwilliams

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)

Occurs because you are altering nameon line 21 and 29 and keeping the length of namethe same in stringLength

发生是因为您name在第 21 行和第 29 行更改并保持name相同的长度stringLength

回答by user unknown

ad 1) The javadocs are a very good reference, here java.lang.String.substring (...):

广告 1)javadocs 是一个很好的参考,这里是 java.lang.String.substring (...):

substring

public String substring(int beginIndex, int endIndex)

Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

子串

public String substring(int beginIndex, int endIndex)

返回一个新字符串,它是此字符串的子字符串。子字符串从指定的 beginIndex 开始,并延伸到索引 endIndex - 1 处的字符。因此子字符串的长度是 endIndex-beginIndex。

The benefit, in excluding the index of the end, is, that you can sequently iterate over values:

不包括结尾的索引的好处是,您可以连续迭代值:

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

回答by user unknown

ad 2)

广告 2)

You don't change i itself, but namegets truncated here:

您不会更改 i 本身,但name会在此处被截断:

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

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

but the outer loop isn't informed about the new length.

但外环不知道新的长度。

ad 3) (Code-review):

广告 3)(代码):

You should declare and initialize your variables as late as possible, and mark as much as possible final. This tells you, that you don't have to worry about them, after they're initialized.

您应该尽可能晚地声明和初始化您的变量,并尽可能将其标记为 final。这告诉您,在它们初始化之后,您不必担心它们。

Given this code:

鉴于此代码:

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

you would have get an error message, for name being final. Maybe this would have prevented you to accidentially get out of sync with the length.

您会收到一条错误消息,因为 name 是最终的。也许这会防止您意外地与长度不同步。

modified, to have a mutable upName, but iterating over 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);

gives you, for input "honky tonky" the output "HonkyTonky", which would have led you to the way, substring (from, to) works, maybe. :)

为您提供输入“honky tonky”的输出“HonkyTonky”,这可能会引导您找到子字符串(从,到)工作的方式。:)