Count lexemes - string out of bounds exception - java

I have a small program that is suppose to count lexemes. What I get is an erorr. I am fairly new to Java. Here is the error:
c:\programming>java LexemesTokenizer
input string: a = ++b; c = d - /* -e */ --f;
Input string= a
Delimeter= .
Total number of delimeters= 2 Exception in thread "main" java.lang.StringIndexOu
tOfBoundsException: String index out of range: 2
at java.lang.String.charAt(Unknown Source)
at LexemesTokenizer.main(LexemesTokenizer.java:41)
Here is the code
import java.util.Scanner;
public class LexemesTokenizer {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("input string: ");
String s = scanner.next();
char delimiter = ' ';
// calculate number of delimiter characters
int cntDelimeters = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != delimiter) {
cntDelimeters++;
}
}
System.out.println("Input string= " + s);
System.out.printf("Delimeter= %c.", delimiter);
System.out.printf("\nTotal number of delimeters= %d ", cntDelimeters);
String[] lexemes = new String[cntDelimeters + 1];
// parse cntDelimeters+1 lexemes and store in an array
int right = 0;
int left = 0;
for (int i = 0; i < cntDelimeters; i++) {
while (s.charAt(right) != delimiter) {
right++;
}
lexemes[i] = s.substring(left, right);
right++;
left = right;
}
lexemes[cntDelimeters] = s.substring(right, s.length());
// print results for testing
for (int i = 0; i < lexemes.length; i++) {
System.out.printf("\n%d : %s", i, lexemes[i]);
}
}
}
line 41 is:while (s.charAt(right) != delimiter) {
Some reason string s is only an a
any help is much appreciated.

Well, your string (s) doesn't contain a space (the value you assigned to delimiter) and then you do this:
while (s.charAt(right) != delimiter) {
right++;
}
Thus flying right off the end of your string.
while (s.charAt(right) != delimiter && s.length > right)
Will take care of that.
Edit: To help with the input string
You're calling
String s = scanner.next();
Scanner is an input parser. This is going to return the first word of your input ("a") because the default delimiter is whitespace.
If you want the entire line of input you use:
String s = scanner.nextLine();

Related

Put a space every 5 characters without using regex or StringBuilder

I want a user to put in a sentence with the scanner class.
Make sure to filter out all the spaces (for example the sentence: this is a test becomes thisisatest)
And then print out that sentence with a for loop with a space every 5 characters
(for example thisi sates t).
This is what i have so far
import java.util.Scanner;
public class BlockText {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Give your sentence: ");
String sentence = s.nextLine();
String nospace = sentence.replace(" ", "");
String out = "";
for (int i = 5; i < nospace.length(); i+=5) {
out += nospace.replaceAll( nospace.substring(i) , " ");
}
System.out.println("Sentence without spaces: " + nospace);
System.out.println("This gives: " + out);
}
}
but I have the issue that he repeats certain characters and removes others.
Like you can see underneath after "this gives:"
run:
Give your sentence:
this is a test
Sentence without spaces: thisisatest
This gives: thisi hisisa es
BUILD SUCCESSFUL (total time: 8 seconds)
Can someone help me out? Like I said in the titel, I want to accomplish this with a for loop and without using regex or StringBuilder.
You should really use a StringBuilder here, because appending strings with += in a loop is very inefficient.
Without a string builder, you can do something like this:
private static String addSpacesEvery5(String s) {
String out = "";
for (int i = 0 ; i < s.length() ; i++) {
if (i % 5 == 0 && i != 0) {
out += " "; // this will run once every five iterations, except the first one
}
out += s.charAt(i);
}
return out;
}
Or more efficiently without +=:
private static String addSpacesEvery5(String s) {
// s.length() / 5 is how many spaces we will add
char[] charArray = new char[s.length() + s.length() / 5];
int currentPos = 0;
for (int i = 0 ; i < s.length() ; i++) {
if (i % 5 == 0 && i != 0) {
charArray[currentPos] = ' ';
currentPos++;
}
charArray[currentPos] = s.charAt(i);
currentPos++;
}
return new String(charArray);
}
And then you can use it in your main method like this:
Scanner s = new Scanner(System.in);
System.out.println("Give your sentence: ");
String sentence = s.nextLine();
String nospace = sentence.replace(" ", "");
String out = addSpacesEvery5(nospace);
System.out.println("Sentence without spaces: " + nospace);
System.out.println("This gives: " + out);
With a string builder, the addSpacesEvery5 could be rewritten as:
private static String addSpacesEvery5(String s) {
StringBuilder out = new StringBuilder();
for (int i = 0 ; i < s.length() ; i++) {
if (i % 5 == 0 && i != 0) {
out.append(" ");
}
out.append(s.charAt(i));
}
return out.toString();
}
Here is one relatively simple and faster:
String tmp = new String();
int len = str.length();
int remOdds = len % 5;
int i = 0;
while (i < len - remOdds)
{
tmp = tmp.concat(str.substring(i, i + 5));
i += 5;
if (i < len)
{
tmp += " ";
}
}
while (i < len)
{
tmp += str.charAt(i);
i++;
}
str = tmp;

New to programming, getting a run time error don't know why

Basically summarized in the title. https://ideone.com/E2BMS8 <-- that's a link to the code. I understand if you don't want to click it though so I'll paste it here as well. will just be disorganized. The code is supposed to flip the letters but keep words in the same position. I would like to figure that part out on my own though. Just need help with the run time error.
import java.util.*;
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
Scanner input = new Scanner(System.in);
String sent, accum = "";
char check, get;
int len, count = 0;
System.out.print("Please enter the sentance you want reversed: ");
sent = input.nextLine();
len = sent.length();
for (int i = 0; i < len; i++) {
check = sent.charAt(len - i);
count += 1;
if (check == ' ') {
for (int p = 0; p < count; p++) {
while (p < count) {
get = sent.charAt(len - p);
accum += (get + ' ');
}
}
}
}
System.out.println("Reversed: " + accum);
}
}
The error String index out of range is cause because of the len is one more than the index range. Remove one on the index such I did below:
import java.util.*;
public class Ideone {
public static void main (String[] args) throws java.lang.Exception {
Scanner input = new Scanner(System.in);
String sent, accum = "";
char check, get;
int len, count = 0;
System.out.print("Please enter the sentance you want reversed: ");
sent = input.nextLine();
len = sent.length();
for (int i = 0; i < len; i++) {
check = sent.charAt(len - i - 1);
count += 1;
if (check == ' ') {
for (int p = 0; p < count; p++) {
get = sent.charAt(len - p - 1);
accum += (get + ' ');
}
}
}
System.out.println("Reversed: " + accum);
}
}
This is a classical "off by one" error -- something you will run into a lot as you find your programming feet. The issue in this case is the 0-based indexing. That is, the first character of a string is at index 0, and the last is at index "string length - 1". If we use sent = "Test"; as an example, then:
sent.charAt(0) == 'T'
sent.charAt(1) == 'e'
sent.charAt(2) == 's'
sent.charAt(3) == 't'
sent.charAt(4) == ??? // "That's an error, Jim!"
Note that index 4 -- which perhaps confusingly is also the length of the string -- is out of bounds. So, what happens during the first iteration of the loop, when i == 0:
check = sent.charAt(len - i); // ERROR! Because ...
==> = sent.charAt((4) - (0));
==> = sent.charAt( 4 ); // Doh!
I leave it to you to figure out how you might fix it.

How to replace characters in a string in Java without using .replace?

The goal of this program is to prompt the user for a single character and a phrase, and then replace any instances of that character within that phrase with a '$'. My program below does just that, but when I showed it to my professor I was told that I cannot use .replace in the methods I built, so I have to figure out a way to not use that. I have worked at it for a while, and thus far I know that I can replace it with a for loop, but after several frustrating iterations, I can't seem to get it right. Excuse me if my code looks funky, I am still an introductory java student so I'm still learning the basics. I have provided a proposed solution at the end of my code snippet below.
public static char getKeyCharacter(String userInput) {
char keyCharacter;
Scanner inputStream = new Scanner(System.in);
while(userInput.length() > 1)
{
System.out.println("Please enter a SINGLE character to use as key: ");
userInput = inputStream.nextLine();
}
keyCharacter = userInput.charAt(0);
return keyCharacter;
}
public static String getString(String userResponse) {
Scanner inputStream = new Scanner(System.in);
String theString;
while(userResponse.length() > 500) {
System.out.println("Please enter a phrase or sentence >= 4 and <=500 characters: ");
userResponse = inputStream.nextLine();
}
while(userResponse.length() < 4) {
System.out.println("Please enter a phrase or sentence >= 4 and <=500 characters: ");
userResponse = inputStream.nextLine();
}
theString = userResponse;
return theString;
}
public static String maskCharacter(String theString, char keyCharacter){
String maskedString = "";
final char mask = '$';
maskedString = maskedString + theString.replace(keyCharacter, mask);
System.out.println("String with " + keyCharacter + " masked: ");
return maskedString;
}
public static String removeCharacter(String theString, char keyCharacter) {
String modifiedString = " ";
final char replaceChar = ' ';
modifiedString = modifiedString + theString.replace(keyCharacter, replaceChar);
System.out.println("String with " + keyCharacter + " removed:");
return modifiedString;
}
public static int countKey(String theString, char keyCharacter) {
int charCount = 0;
for (int c = 0; c < theString.length(); c++) {
if (theString.charAt(c) == keyCharacter) {
charCount++;
}
}
System.out.println("Occurences of " + keyCharacter + " in string:");
return charCount;
}
}
I believe the solution is will look something like this, but thus far I've been unsuccesful -
public static String maskCharacter(String theString, char keyCharacter){
String maskedString = "";
final char mask = '$';
for (int k = 0; k < theString.length(); k++) {
if (theString.charAt(k) == keyCharacter) {
keyCharacter = mask;
}
System.out.println("String with " + keyCharacter + " masked: ");
return maskedString;
}
My issue lies in making the maskedString = theString with all the keyCharacters replaced by mask. For the record, I have yet to learn anything about those fancy arrays, so if there is a way to do this using a simple for loop I would greatly appreciate it. Thank you for the assistance in advance!
I would use a StringBuilder and String#toCharArray() with a simple for-each loop. Like,
public static String maskCharacter(String theString, char keyCharacter){
StringBuilder sb = new StringBuilder();
for (char ch : theString.toCharArray()) {
if (ch == keyCharacter) {
sb.append('$'); // <-- mask keyCharacter(s).
} else {
sb.append(ch); // <-- it isn't the character to mask
}
}
return sb.toString();
}
I wouldn't use a StringBuilder: just use the result of toCharArray() directly:
char[] cs = theString.toCharArray();
for (int i = 0; i < cs.length; ++i) {
if (cs[i] == keyCharacter) cs[i] = '$';
}
return new String(cs);
Not only is it more concise, but:
It will run faster, because it's cheaper to access an array element than to invoke a method; and because it doesn't require StringBuilder's internal buffer to resize (although you could just pre-size that);
It will use less memory, because it doesn't require storage for the copy inside StringBuilder.
public static String maskCharacter(String theString, char keyCharacter){
String masked = "";
for (int i = 0 ; i < theString.length() ; i++) {
if (theString.charAt(i) == keyCharacter) {
masked += "$";
}
else {
masked+=theString.charAt(i)+"";
}
}
return masked;
}
An answer that only uses string concatenation and basic character access.
You seem to know that you can concatenate something to a string and get a different string.
maskedString = maskedString + ...;
You also know you can build a for-loop that gets each individual character using .charAt()
for (int k = 0; k < theString.length(); k++) {
char nch = theString.charAt(k);
}
You can check equality between chars
if (nch == keyCharacter)
... assuming you know about else-branches, isn't it clear you just need to put them together?
if (nch == keyCharacter) {
// append '$' to maskedString
}
else {
// append nch to maskedString
}
Of course this creates a new string on every loop iteration so it is not terribly efficient. But I don't think that's the point of the exercise.

Java - make new string based on old one and lag

I need to get a new string based on an old one and a lag. Basically, I have a string with the alphabet (s = "abc...xyz") and based on a lag (i.e. 3), the new string should replace the characters in a string I type with the character placed some positions forward (lag). If, let's say, I type "cde" as my string, the output should be "fgh". If any other character is added in the string (apart from space - " "), it should be removed. Here is what I tried, but it doesn't work :
String code = "abcdefghijklmnopqrstuvwxyzabcd"; //my lag is 4 and I added the first 4 characters to
char old; //avoid OutOfRange issues
char nou;
for (int i = 0; i < code.length() - lag; ++i)
{
old = code.charAt(i);
//System.out.print(old + " ");
nou = code.charAt(i + lag);
//System.out.println(nou + " ");
// if (s.indexOf(old) != 0)
// {
s = s.replace(old, nou);
// }
}
I commented the outputs for old and nou (new, but is reserved word) because I have used them only to test if the code from position i to i + lag is working (and it is), but if I uncomment the if statement, it doesn't do anything and I leave it like this, it keeps executing the instructions inside the for statmement for code.length() times, but my string doesn't need to be so long. I have also tried to make the for statement like below, but I got lost.
for (int i = 0; i < s.length(); ++i)
{
....
}
Could you help me with this? Or maybe some advices about how I should think the algorithm?
Thanks!
It doesn't work because, as the javadoc of replace() says:
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
(emphasis mine)
So, the first time you meet an 'a' in the string, you replace all the 'a's by 'd'. But then you go to the next char, and if it's a 'd' that was an 'a' before, you replace it once again, etc. etc.
You shouldn't use replace() at all. Instead, you should simply build a new string, using a StringBuilder, by appending each shifted character of the original string:
String dictionary = "abcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder(input.length());
for (int i = 0; i < input.length(); i++) {
char oldChar = input.charAt(i);
int oldCharPositionInDictionary = dictionary.indexOf(oldChar);
if (oldCharPositionInDictionary >= 0) {
int newCharPositionInDictionary =
(oldCharPositionInDictionary + lag) % dictionary.length();
sb.append(dictionary.charAt(newCharPositionInDictionary));
}
else if (oldChar == ' ') {
sb.append(' ');
}
}
String result = sb.toString();
Try this:
Convert the string to char array.
iterate over each char array and change the char by adding lag
create new String just once (instead of loop) with new String passing char array.
String code = "abcdefghijklmnopqrstuvwxyzabcd";
String s = "abcdef";
char[] ch = s.toCharArray();
char[] codes = code.toCharArray();
for (int i = 0; i < ch.length; ++i)
{
ch[i] = codes[ch[i] - 'a' + 3];
}
String str = new String(ch);
System.out.println(str);
}
My answer is something like this.
It returns one more index to every character.
It reverses every String.
Have a good day!
package org.owls.sof;
import java.util.Scanner;
public class Main {
private static final String CODE = "abcdefghijklmnopqrstuvwxyz"; //my lag is 4 and I added the first 4 characters to
#SuppressWarnings("resource")
public static void main(String[] args) {
System.out.print("insert alphabet >> ");
Scanner scanner = new Scanner(System.in);
String s = scanner.next();
char[] char_arr = s.toCharArray();
for(int i = 0; i < char_arr.length; i++){
int order = CODE.indexOf(char_arr[i]) + 1;
if(order%CODE.length() == 0){
char_arr[i] = CODE.charAt(0);
}else{
char_arr[i] = CODE.charAt(order);
}
}
System.out.println(new String(char_arr));
//reverse
System.out.println(reverse(new String(char_arr)));
}
private static String reverse (String str) {
char[] char_arr = str.toCharArray();
for(int i = 0; i < char_arr.length/2; i++){
char tmp = char_arr[i];
char_arr[i] = char_arr[char_arr.length - i - 1];
char_arr[char_arr.length - i - 1] = tmp;
}
return new String(char_arr);
}
}
String alpha = "abcdefghijklmnopqrstuvwxyzabcd"; // alphabet
int N = alpha.length();
int lag = 3; // shift value
String s = "cde"; // input
StringBuilder sb = new StringBuilder();
for (int i = 0, index; i < s.length(); i++) {
index = s.charAt(i) - 'a';
sb.append(alpha.charAt((index + lag) % N));
}
String op = sb.toString(); // output

Reversing characters in each word in a sentence - Stack Implementation

This code is inside the main function:
Scanner input = new Scanner(System.in);
System.out.println("Type a sentence");
String sentence = input.next();
Stack<Character> stk = new Stack<Character>();
int i = 0;
while (i < sentence.length())
{
while (sentence.charAt(i) != ' ' && i < sentence.length() - 1)
{
stk.push(sentence.charAt(i));
i++;
}
stk.empty();
i++;
}
And this is the empty() function:
public void empty()
{
while (this.first != null)
System.out.print(this.pop());
}
It doesn't work properly, as by typing example sentence I am getting this output: lpmaxe. The first letter is missing and the loop stops instead of counting past the space to the next part of the sentence.
I am trying to achieve this:
This is a sentence ---> sihT si a ecnetnes
Per modifications to the original post, where the OP is now indicating that his goal is to reverse the letter order of the words within a sentence, but to leave the words in their initial positions.
The simplest way to do this, I think, is to make use of the String split function, iterate through the words, and reverse their orders.
String[] words = sentence.split(" "); // splits on the space between words
for (int i = 0; i < words.length; i++) {
String word = words[i];
System.out.print(reverseWord(word));
if (i < words.length-1) {
System.out.print(" "); // space after all words but the last
}
}
Where the method reverseWord is defined as:
public String reverseWord(String word) {
for( int i = 0; i < word.length(); i++) {
stk.push(word.charAt(i));
}
return stk.empty();
}
And where the empty method has been changed to:
public String empty() {
String stackWord = "";
while (this.first != null)
stackWord += this.pop();
return stackWord;
}
Original response
The original question indicated that the OP wanted to completely reverse the sentence.
You've got a double-looping construct where you don't really need it.
Consider this logic:
Read each character from the input string and push that character to the stack
When the input string is empty, pop each character from the stack and print it to screen.
So:
for( int i = 0; i < sentence.length(); i++) {
stk.push(sentence.charAt(i));
}
stk.empty();
I assume that what you want your code to do is to reverse each word in turn, not the entire string. So, given the input example sentence you want it to output elpmaxe ecnetnes not ecnetnes elpmaxe.
The reason that you see lpmaxe instead of elpmaxe is because your inner while-loop doesn't process the last character of the string since you have i < sentence.length() - 1 instead of i < sentence.length(). The reason that you only see a single word is because your sentence variable consists only of the first token of the input. This is what the method Scanner.next() does; it reads the next (by default) space-delimited token.
If you want to input a whole sentence, wrap up System.in as follows:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
and call reader.readLine().
Hope this helps.
Assuming you've already got your input in sentence and the Stack object is called stk, here's an idea:
char[] tokens = sentence.toCharArray();
for (char c : tokens) {
if (c == ' ') {
stk.empty();
System.out.print(c);
} else {
stk.add(c);
}
}
Thus, it will scan through one character at a time. If we hit a space character, we'll assume we've hit the end of a word, spit out that word in reverse, print that space character, then continue. Otherwise, we'll add the character to the stack and continue building the current word. (If you want to also allow punctuation like periods, commas, and the like, change if (c == ' ') { to something like if (c == ' ' || c == '.' || c == ',') { and so on.)
As for why you're only getting one word, darrenp already pointed it out. (Personally, I'd use a Scanner instead of a BufferedReader unless speed is an issue, but that's just my opinion.)
import java.util.StringTokenizer;
public class stringWork {
public static void main(String[] args) {
String s1 = "Hello World";
s1 = reverseSentence(s1);
System.out.println(s1);
s1 = reverseWord(s1);
System.out.println(s1);
}
private static String reverseSentence(String s1){
String s2 = "";
for(int i=s1.length()-1;i>=0;i--){
s2 += s1.charAt(i);
}
return s2;
}
private static String reverseWord(String s1){
String s2 = "";
StringTokenizer st = new StringTokenizer(s1);
while (st.hasMoreTokens()) {
s2 += reverseSentence(st.nextToken());
s2 += " ";
}
return s2;
}
}
public class ReverseofeachWordinaSentance {
/**
* #param args
*/
public static void main(String[] args) {
String source = "Welcome to the word reversing program";
for (String str : source.split(" ")) {
System.out.print(new StringBuilder(str).reverse().toString());
System.out.print(" ");
}
System.out.println("");
System.out.println("------------------------------------ ");
String original = "Welcome to the word reversing program";
wordReverse(original);
System.out.println("Orginal Sentence :::: "+original);
System.out.println("Reverse Sentence :::: "+wordReverse(original));
}
public static String wordReverse(String original){
StringTokenizer string = new StringTokenizer(original);
Stack<Character> charStack = new Stack<Character>();
while (string.hasMoreTokens()){
String temp = string.nextToken();
for (int i = 0; i < temp.length(); i ++){
charStack.push(temp.charAt(i));
}
charStack.push(' ');
}
StringBuilder result = new StringBuilder();
while(!charStack.empty()){
result.append(charStack.pop());
}
return result.toString();
}
}
public class reverseStr {
public static void main(String[] args) {
String testsa[] = { "", " ", " ", "a ", " a", " aa bd cs " };
for (String tests : testsa) {
System.out.println(tests + "|" + reverseWords2(tests) + "|");
}
}
public static String reverseWords2(String s) {
String[] sa;
String out = "";
sa = s.split(" ");
for (int i = 0; i < sa.length; i++) {
String word = sa[sa.length - 1 - i];
// exclude "" in splited array
if (!word.equals("")) {
//add space between two words
out += word + " ";
}
}
//exclude the last space and return when string is void
int n = out.length();
if (n > 0) {
return out.substring(0, out.length() - 1);
} else {
return "";
}
}
}
This can pass in leetcode

Categories

Resources