Reputation: 15
I'm trying to rearrange words in any given string (20 words or less). I'm having this issue because I can not get the last word in the string to print. I tried modifying the loop range, but I am not able to fix the issue.
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' && ch <= 'z') || (ch >= 'A' && 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 && (list[j].compareToIgnoreCase(key) > 0))
{
list[j + 1] = list[j];
j = j - 1;
}
list[j + 1] = key;
}
}
}
Upvotes: 1
Views: 804
Reputation: 140319
You don't need to handle the end of the string explicitly: by using integer pointers to the start and end of words, you can do it as follows:
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() && !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() && 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;
}
where isLetter(char)
is a method that checks if the argument is between A and Z (in either case).
I have seen a variation on this method which avoids the inner while loops: I don't like this as much, as I think it's less clear to read; but it doesn't have quite so much repetitive checking of the length (I think this code works, not tried it):
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;
}
}
}
Upvotes: 0
Reputation: 2363
That happens, when you hit end of the string and temp is not empty. To fix it you can add same if statement after loop:
for(int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
temp = temp + ch;
} else {
if(temp.length() > 0) {
list[n] = temp;
n++;
temp = "";
}
}
}
if(temp.length() > 0) {
list[n] = temp;
n++;
temp = "";
}
Also you would need to fix your output to not print first word twice:
public void print() {
for(int i = 0; i < n; i++) {
System.out.print(list[i] + " ");
}
System.out.println();
}
Output before fix:
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
Output after fix:
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
Update:
Also you can solve your problem in one line, using streams
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);
}
It splits input string by space character, takes first 20 words, sorts them and creates an array of them.
Output:
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
Upvotes: 2