помогите с тем, как работает String.substring (int, int) - PullRequest
2 голосов
/ 13 апреля 2011

код, приведенный ниже, взят из задания в моем учебнике для простой программы, которая берет введенное пользователем имя и заглавная буква имени и фамилии.Код работает правильно, но я не понимаю, почему name.substring() работает правильно.В частности, меня интересует, как работает блок из строк 24 - 29.Если пользователь вводит имя «Джонни Джонсон», то i должно содержать значение 7, входящее в строку 29. Если i содержит 7, то name = name.substring(0, i) не должно содержать «Джонни J», что должно составлять строку 29на самом деле хранить "Джонни Джонсона" в String name?Но вместо этого он хранит «Джонни Джонсон», как и должно быть.

Мой второй вопрос связан с тем, что я возился с этим кодом, чтобы увидеть разные результаты.Если я изменяю первую часть строки 29 на name = name.substring(0, i-1), я получаю сообщение об ошибке (используя Eclipse):

Исключение в потоке "main" java.lang.StringIndexOutOfBoundsException: индекс строки вне диапазона: 15на java.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 }

Ответы [ 7 ]

3 голосов
/ 13 апреля 2011

Из 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)

Если сомневаетесь, посмотрите на javadocs: D

Что касается вашего второго вопроса, снова вам помогут Javadocs (http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#charAt(int)) для charAt(int):

Броски: IndexOutOfBoundsException - если аргумент индекса отрицательный или нет меньше длины этой строки.

Если вы используете i-1 в подстроке, вы уменьшаете размер имени на 1 каждый раз, когда он находит ' '. Это означает, что он будет повторяться 15 раз, но name будет только 14 символов после того, как найден ' '.

1 голос
/ 13 апреля 2011

ad 2)

Вы сами не меняете i, но name усекается здесь:

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

, но внешний цикл не информируется о новой длине.

ad 3) (Проверка кода):

Вы должны объявить и инициализировать ваши переменные как можно позже и отметить как можно больше final.Это говорит о том, что вам не нужно беспокоиться о них после их инициализации.

Учитывая этот код:

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", который привел бы вас кКстати, подстрока (от, до) работает, может быть.:)

1 голос
/ 13 апреля 2011

ad 1) Javadocs - очень хорошая ссылка, здесь java.lang.String.substring (...):

подстрока

public String substring(int beginIndex, int endIndex)

Возвращает новыйстрока, которая является подстрокой этой строки.Подстрока начинается с указанного beginIndex и продолжается до символа с индексом endIndex - 1. Таким образом, длина подстроки равна endIndex-beginIndex.

Преимущество в исключении индекса конца состоит в том, что, что вы можете последовательно перебирать значения:

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);
1 голос
/ 13 апреля 2011
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)

Происходит, потому что вы изменяете name в строках 21 и 29 и сохраняете длину name одинаковой в stringLength

1 голос
/ 13 апреля 2011

Привет. Вы получаете Исключение, потому что вы перебираете строку, но в цикле for вы фактически меняете длину строки name = name.substring (0, i) + c + name.substring (i + 1, stringLength); Поэтому, пока вы все еще находитесь в цикле, размер имени больше не равен старому stringLength.

Boro

1 голос
/ 13 апреля 2011

правильная подстрока работает следующим образом:

public String substring(int beginIndex, int endIndex)

Возвращает новую строку, которая является подстрокой этой строки.Подстрока начинается в указанном beginIndex и продолжается до символа с индексом endIndex - 1. Таким образом, длина подстроки равна endIndex-beginIndex.

, поэтому для подстроки (0, 7) требуется 0..6 символов из строки


Обратите внимание, что это действительно плохая практика для изменения значения итерации в цикле for (i ++ внутри for-loop-body).Если после пробела у вас нет других символов, вы встретите исключение

1 голос
/ 13 апреля 2011

В кавычках substring Javadoc,

Подстрока начинается в указанном beginIndex и продолжается до символа в индексе endIndex - 1.

Другими словами, endIndex не входит в результат.

Что касается вашего второго вопроса, это связано с тем, что вы уменьшаете длину name внутри цикла.Ваше условие цикла (i < stringLength) и тот факт, что вы смотрите на name.charAt(i), предполагают, что длина name остается постоянной (или, по меньшей мере, не уменьшается).Это нарушается в тот момент, когда вы начинаете сокращать строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...