#java #arrays #string
Вопрос:
Я пытаюсь переставить слова в любой заданной строке (20 слов или меньше). У меня возникла эта проблема, потому что я не могу вывести последнее слово в строке для печати. Я попытался изменить диапазон циклов, но не смог устранить проблему.
public class ListString {
String[] list = new String[20];
int n = 0;
public void read() {
Scanner in = new Scanner(System.in);
System.out.println("Please enter the sentence");
String s = in.nextLine();
String temp = "";
for (int i = 0; i < s.length(); i )
{
char ch = s.charAt(i);
if ((ch >= 'a' amp;amp; ch <= 'z') || (ch >= 'A' amp;amp; ch <= 'Z')) // range from a to z
temp = temp ch;
else
{
if (temp.length() > 0)
{
list[n] = temp;
n ;
temp = "";
}
}
}
}
public void print() {
System.out.print(list[0]);
for (int i = 0; i < n; i )
System.out.print(" " list[i]);
System.out.println(" ");
}
public void sort() {
for (int i = 0; i < n; i ) {
String key = list[i];
int j = i - 1;
while (j >= 0 amp;amp; (list[j].compareToIgnoreCase(key) > 0))
{
list[j 1] = list[j];
j = j - 1;
}
list[j 1] = key;
}
}
}
Ответ №1:
Это происходит, когда вы нажимаете конец строки, а temp не пуст. Чтобы исправить это, вы можете добавить тот же оператор if после цикла:
for(int i = 0; i < s.length(); i ) {
char ch = s.charAt(i);
if((ch >= 'a' amp;amp; ch <= 'z') || (ch >= 'A' amp;amp; ch <= 'Z')) {
temp = temp ch;
} else {
if(temp.length() > 0) {
list[n] = temp;
n ;
temp = "";
}
}
}
if(temp.length() > 0) {
list[n] = temp;
n ;
temp = "";
}
Кроме того, вам нужно будет исправить вывод, чтобы не печатать первое слово дважды:
public void print() {
for(int i = 0; i < n; i ) {
System.out.print(list[i] " ");
}
System.out.println();
}
Вывод перед исправлением:
a b c d e f g h i j k l m n o p q r s t
a a b c d e f g h i j k l m n o p q r s
Вывод после исправления:
a b c d e f g h i j k l m n o p q r s t
a b c d e f g h i j k l m n o p q r s t
Обновить:
Также вы можете решить свою проблему в одну строку, используя потоки
public void read() {
Scanner in = new Scanner(System.in);
System.out.println("Please enter the sentence");
String s = in.nextLine();
String[] list = Arrays.stream(s.split(" ")).limit(20).sorted().toArray(String[]::new);
}
Он разбивает входную строку на символы пробела, берет первые 20 слов, сортирует их и создает массив из них.
Выход:
t s r q p o n m l k j i h g f e d c b a z z z z z
a b c d e f g h i j k l m n o p q r s t
Комментарии:
1. В потоковой версии
read
переменной методаlist
отсутствует тип в ее объявлении.
Ответ №2:
Вам не нужно явно обрабатывать конец строки: используя целочисленные указатели на начало и конец слов, вы можете сделать это следующим образом:
int start = 0;
while (start < s.length()) {
// Increment a start pointer until it points to the end of the string or the start of a word.
while (start < s.length() amp;amp; !isLetter(s.charAt(start))) {
start ;
}
// Increment an end pointer until it points to the end of the string or a non-word character.
int end = start;
while (end < s.length() amp;amp; isLetter(s.charAt(end))) {
end ;
}
if (start == end) {
// You reached the end of the string.
break;
}
// Grab the portion of the string between start and end, this is a word.
list[n ] = s.substring(start, end);
// Set up the start pointer to point to the end of this word, for the next iteration.
start = end;
}
где isLetter(char)
находится метод, который проверяет, находится ли аргумент между A и Z (в любом случае).
Я видел вариант этого метода, который позволяет избежать внутренних циклов while: мне это не так нравится, так как я думаю, что это менее понятно для чтения; но в нем не так много повторяющихся проверок длины (я думаю, что этот код работает, не пробовал его).:
for (int start = 0, end = 0; start < s.length();) {
if (!isLetter(s.charAt(start))) {
start ;
end = start;
} else if (isLetter(s.charAt(end))) {
end ;
if (end >= s.length() || !isLetter(s.charAt(end))) {
list[n ] = s.substring(start, end);
start = end;
}
}
}