Making a substring out of a line read from file - java

So I am trying to read through a .txt file and find all instances of html tags, push opening tags to a stack, and then pop it when I find a closing tag. Right now I am getting String out of bounds exception for the following line:
if(scan.next().startsWith("</", 1))
{
toCompare = scan.next().substring(scan.next().indexOf('<'+2), scan.next().indexOf('>'));
tempString = htmlTag.pop();
if(!tempString.equals(toCompare))
{
isBalanced = false;
}
}
else if(scan.next().startsWith("<"))
{
tempString = scan.next().substring(scan.next().indexOf('<'+1), scan.next().indexOf('>'));
htmlTag.push(tempString);
}
It is telling me that the index of the last letter is -1. The problem I can think of is that all of the scan.next() calls are moving onto the next string. If this is the case, do I need to just write
toCompare = scan.next()
and then so my comparisons?

You have two major problems in your code:
you're calling scan.next() way too much and as you expect, this will move the scanner to the next token. Therefore, the last one will be lost and gone.
.indexOf('<'+2) doesn't return the index of '<' and adds 2 to that position, it will return the index of '>', because you're adding 2 to the int value of char < (60; > has 62). Your problem with index -1 ("It is telling me that the index of the last letter is -1.") comes from this call: .indexOf('<'+1) this looks for char '=' and if your string doesn't contain that, then it will return -1. A call for #substring(int, int) will fail if you pass -1 as the starting position.
I suggest the following two methods to extract the value between '<' and '>':
public String extract(final String str) {
if (str.startsWith("</")) {
return extract(str, 2);
} else if (str.startsWith("<")) {
return extract(str, 1);
}
return str;
}
private String extract(final String str, final int offset) {
return str.substring(str.indexOf('<') + offset, str.lastIndexOf('>'));
}
As you can see, the first method evaluates the correct offset for the second method to cut off either "offset. Mind that I wrote str.indexOf('<') + offset which behaves differently, than your str.indexOf('<' + offset).
To fix your first problem, store the result of scan.next() and replace all occurrences with that temporary string:
final String token = scan.next();
if (token.startsWith("</")) { // removed the second argument
final String currentTag = extract(token); // renamed variable
final String lastTag = htmlTag.pop(); // introduced a new temporary variable
if (!lastTag.equals(currentTag)) {
isBalanced = false;
}
}
else if (token.startsWith("<")) {
htmlTag.push(extract(token)); // no need for a variable here
}
I guess this should help you to fix your problems. You can also improve that code a little bit more, for example try to avoid calling #startsWith("</") and #startsWith("<") twice.

Related

How can I prevent the user from entering the same letter in Hangman JAVA?

I am writing a hangman program and one of the requirements to a hangman game is preventing the user from entering the same letter twice.
I have written the code for that, but the problem is every time I enter a letter it says it is already entered. I need to only say it when it is entered the second time. You guys have any suggestions? I've been trying to fix this for the past few hours, I figured I could ask on here to find some help. I already looked at another Stackoverflow question regarding something similar to this but all those solutions have the same result.
In Java, how can I determine if a char array contains a particular character?
I've tried something like this but it won't work either:
boolean contains = false;
for (char c : store) {
if (c == character) {
System.out.println("Already Entered");
contains = true;
break;
}
}
if (contains) {
// loop to top
continue;
}
SECOND CLASS-
public void hangman(String word, int life) {
KeyboardReader reader = new KeyboardReader();
char[] letter = new char[word.length()];
char[] store = new char[word.length()];
String guess;
int i = 0, tries = 0, incorrect = 0, count = 1, v = 0;
while (i < word.length()) {
letter[i] = '-';
I would just use the String.contains() method:
String aString = "abc";
char aChar = 'a';
return aString.contains(aChar + "");
To keep track of guessed letters you can use a StringBuffer, appending them using a StringBuffer.append() to append new letters (maintaining state) and use the StringBuffer.toString() method to get the String representation when you need to do the comparison above.
Since Java 1.5 the class String contains the method contains(). My idea is to collect all entered letters into a string variable and using above method:
// My code line
String letterAlreadyEntered = "";
// Your code line
char character = reader.readLine().charAt(0);
// My code line
if (letterAlreadyEntered.contains("" + character) == true) {
//Put code here what ever you want to do with existing letter
} else {
letterAlreadyEntered += character;
}
In my opinion, this is an easier way to check for occurrences than in arrays, where you have to write your own check method.

Why is this code not executing properly? Longest substring problem

So I'm trying to solve the Longest Substring Without Repeating Character problem in a webpage and when I'm trying to upload it it will show me this bug:
class Solution {
public int lengthOfLongestSubstring(String s) {
HashSet<Character> hash = new HashSet<>();
int count = 0, finalCount = 1;
char prevChar = s.charAt(0);
hash.add(prevChar);
for (int i = 1; i < s.length(); i++)
{
char character = s.charAt(i);
if (!hash.contains(character)){
hash.add(character);
count++;
if (count > finalCount) finalCount = count;
}
else{
hash.clear();
hash.add(character);
count = 1;
}
prevChar = character;
}
return finalCount;
} }
Is there anything wrong with it?
If not, do you think my algorithm was efficient? I can't compare its performance since the webpage won't let me upload it.
You call s.charAt(0) in line 5. I imagine they pass in the empty string as a test case and you are getting an out of bounds exception. Prior to line 5 add a check to see if the string length is 0 and if it is return 0.
According to the error description it's doing a dummy-spit at line 5 of the Solution class.
Based on the picture that's:
char prevChar = s.charAt(0);
The error is ArrayIndexOutOfBounds which generally indicates you tried to get more out of something than was actually there (e.g. running over the end of an array).
Here I'd suggest maybe putting in some System.out.println lines at line 3 to sanity check the method parameter, e.g.:
(a) if the input String s is null
or
(b) if the input String s is empty (e.g. "")
charAt(0) will get the first character, but if there are zero characters then trying to get the 1th character is an error, no?
NB: something like this:
System.out.println("Input was :" + s + ":");
Will show both of those conditions, as either:
Input was ::
for an empty String
Input was :null:
for a null String

Determine if a string has all unique characters

This is from cracking the Coding Interview Book
The Questions Implement an algorithm to determine if a string has all unique characters. What if
you can not use additional data structures?
I am wondering what is happening in the if statement below? can anyone explain it to me ?
I have left my understanding of the code in the comments.Please correct me if i am wrong
public class Uniquechar2 {
public static boolean isUniqueChars2(String str) {
// Create a new boolean array of 256 characters to account for basic a cii and extended ascii characters
boolean[] charSet = new boolean[256];
//iterate through the array
for (int i = 0; i < str.length(); i++) {
// Assign the value of current value of the iterator i to int variable val.So if we are looping through "hello" at i = 0 the int value of 'h' will be assigned to val.Is that correct?
int val = str.charAt(i);
// Continuing from the example of loping throughout the string "hello" the if statement will see if 'h' is in charSet and since it will be there it will return false /is that what is happening?
if (charSet[val]) {
return false;
}
// Is this the else statement? true will be assigned to charSet[h] in this case
charSet[val] = true;
}
// I dont understand why we are returning true at the end ?
return true;
}
public static boolean isUniqueChars2(String str) {
// Create a new boolean array of 256 characters to account for basic ascii and extended ascii characters
boolean[] char_set = new boolean[256];
// Iterate through the string we are testing
for (int i = 0; i < str.length(); i++) {
// Get the numerical (ascii) value of the character in the `str` at position `i`.
int val = str.charAt(i);
// If char_set[val] has been set, that means that this character was already present in the string. (so in string 'hello' this would be true for the second 'l')
if (char_set[val]) {
return false;
}
// If the character hasn't been encountered yet (otherwise we would have returned false above), then mark this particular character as present in the string
char_set[val] = true;
}
// If the function hasn't returned false after going through the entire string that means that each character is unique - thus returning true
return true;
}
Is this the else statement
No, otherwise there would be an else in the code. But in this case, else is unnecessary since, if char_set[val] is true, the execution of the method stops immediately, due to the return false; instruction.
I dont understand why we are returning true at the end ?
Because since no duplicate has been found, the method must return true to indicate that the string is composed of unique characters. If a duplicate had been found, the method would have returned already in
if (char_set[val]) {
return false;
}
I would just use regex, which requires only one line of code:
public static boolean isUniqueChars(String str) {
return str.matches("((.)(?!.*?\\2))*");
}
Breaking down the regex:
(.) captures every character
(?!.*?\\2) is a negative look ahead for a back reference to the captured group
Together, these mean "a character that does not reappear after itself"
(...)* around the above means 0-n of them
Altogether, it means "comprised of characters that do do reappear later in the string", ie unique characters.
One-line solution without any extra data structure:
str.chars().distinct().count() == (int)str.length();

return the first word in any string (Java)

I have to be able to input any two words as a string. Invoke a method that takes that string and returns the first word. Lastly display that word.
The method has to be a for loop method. I kind of know how to use substring, and I know how to return the first word by just using .substring(0,x) x being how long the first word is.
How can I make it so that no matter what phrase I use for the string, it will always return the first word? And please explain what you do, because this is my first year in a CS class. Thank you!
I have to be able to input any two words as a string
The zero, one, infinity design rule says there is no such thing as two. Lets design it to work with any number of words.
String words = "One two many lots"; // This will be our input
and then invoke and display the first word returned from the method,
So we need a method that takes a String and returns a String.
// Method that returns the first word
public static String firstWord(String input) {
return input.split(" ")[0]; // Create array of words and return the 0th word
}
static lets us call it from main without needing to create instances of anything. public lets us call it from another class if we want.
.split(" ") creates an array of Strings delimited at every space.
[0] indexes into that array and gives the first word since arrays in java are zero indexed (they start counting at 0).
and the method has to be a for loop method
Ah crap, then we have to do it the hard way.
// Method that returns the first word
public static String firstWord(String input) {
String result = ""; // Return empty string if no space found
for(int i = 0; i < input.length(); i++)
{
if(input.charAt(i) == ' ')
{
result = input.substring(0, i);
break; // because we're done
}
}
return result;
}
I kind of know how to use substring, and I know how to return the first word by just using .substring(0,x) x being how long the first word is.
There it is, using those methods you mentioned and the for loop. What more could you want?
But how can I make it so that no matter what phrase I use for the string, it will always return the first word?
Man you're picky :) OK fine:
// Method that returns the first word
public static String firstWord(String input) {
String result = input; // if no space found later, input is the first word
for(int i = 0; i < input.length(); i++)
{
if(input.charAt(i) == ' ')
{
result = input.substring(0, i);
break;
}
}
return result;
}
Put it all together it looks like this:
public class FirstWord {
public static void main(String[] args) throws Exception
{
String words = "One two many lots"; // This will be our input
System.out.println(firstWord(words));
}
// Method that returns the first word
public static String firstWord(String input) {
for(int i = 0; i < input.length(); i++)
{
if(input.charAt(i) == ' ')
{
return input.substring(0, i);
}
}
return input;
}
}
And it prints this:
One
Hey wait, you changed the firstWord method there.
Yeah I did. This style avoids the need for a result string. Multiple returns are frowned on by old programmers that never got used to garbage collected languages or using finally. They want one place to clean up their resources but this is java so we don't care. Which style you should use depends on your instructor.
And please explain what you do, because this is my first year in a CS class. Thank you!
What do I do? I post awesome! :)
Hope it helps.
String line = "Hello my name is...";
int spaceIndex = line.indexOf(" ");
String firstWord = line.subString(0, spaceIndex);
So, you can think of line as an array of chars. Therefore, line.indexOf(" ") gets the index of the space in the line variable. Then, the substring part uses that information to get all of the characters leading up to spaceIndex. So, if space index is 5, it will the substring method will return the indexes of 0,1,2,3,4. This is therefore going to return your first word.
The first word is probably the substring that comes before the first space. So write:
int x = input.indexOf(" ");
But what if there is no space? x will be equal to -1, so you'll need to adjust it to the very end of the input:
if (x==-1) { x = input.length(); }
Then use that in your substring method, just as you were planning. Now you just have to handle the case where input is the blank string "", since there is no first word in that case.
Since you did not specify the order and what you consider as a word, I'll assume that you want to check in given sentence, until the first space.
Simply do
int indexOfSpace = sentence.indexOf(" ");
firstWord = indexOfSpace == -1 ? sentence : sentence.substring(0, indexOfSpace);
Note that this will give an IndexOutOfBoundException if there is no space in the sentence.
An alternative would be
String sentences[] = sentence.split(" ");
String firstWord = sentence[0];
Of if you really need a loop,
String firstWord = sentence;
for(int i = 0; i < sentence.length(); i++)
{
if(sentence.charAt(i) == ' ')
{
sentence = firstWord.substring(0, i);
break;
}
}
You may get the position of the 'space' character in the input string using String.indexOf(String str) which returns the index of the first occurrence of the string in passed to the method.
E.g.:
int spaceIndex = input.indexOf(" ");
String firstWord = input.substring(0, spaceIndex);
Maybe this can help you figure out the solution to your problem. Most users on this site don't like doing homework for students, before you ask a question, make sure to go over your ISC book examples. They're really helpful.
String Str = new String("Welcome to Stackoverflow");
System.out.print("Return Value :" );
System.out.println(Str.substring(5) );
System.out.print("Return Value :" );
System.out.println(Str.substring(5, 10) );

Finding Palindromes in a word list

I'm working on a program for Java on how to find a list of palindromes that are embedded in a word list file. I'm in an intro to Java class so any sort of help or guidance will be greatly appreciated!
Here is the code I have so far:
import java.util.Scanner;
import java.io.File;
class Palindromes {
public static void main(String[] args) throws Exception {
String pathname = "/users/abrick/resources/american-english-insane";
File dictionary = new File(pathname);
Scanner reader = new Scanner(dictionary);
while (reader.hasNext()) {
String word = reader.nextLine();
for (int i = 0; i > word.length(); i++) {
if (word.charAt(word.indexOf(i) == word.charAt(word.indexOf(i)) - 1) {
System.out.println(word);
}
}
}
}
}
There are 3 words that are 7 letters or longer in the list that I am importing.
You have a few ways to solve this problem.
A word is considered a palindrome if:
It can be read the same way backwards as forwards.
The first element is the same as the last element, up until we reach the middle.
Half of the word is the same as the other half, reversed.
A word of length 1 is trivially a palindrome.
Ultimately, your method isn't doing much of that. In fact, you're not doing any validation at all - you're only printing the word if the first and last character match.
Here's a proposal: Let's read each end of the String, and see if it's a palindrome. We have to take into account the case that it could potentially be empty, or be of length 1. We also want to get rid of any white space in the string, as that can cause errors on validation - we use replaceAll("\\s", "") to solve that.
public boolean isPalindrome(String theString) {
if(theString.length() == 0) {
throw new IllegalStateException("I wouldn't expect a word to be zero-length");
}
if(theString.length() == 1) {
return true;
} else {
char[] wordArr = theString.replaceAll("\\s", "").toLowerCase().toCharArray();
for(int i = 0, j = wordArr.length - 1; i < wordArr.length / 2; i++, j--) {
if(wordArr[i] != wordArr[j]) {
return false;
}
}
return true;
}
}
I'm assuming that you're reading in strings. Use string.toCharArray() to convert each string to a char[]. Iterate through the character array using a for loop as follows: on iteration 1, if the first character is equal to the last character, then proceed to the next iteration, else return false. On iteration 2, if the second character is equal to the second-to-last character then proceed to the next iteration, else return false. And so on, until you reach the middle of the string, at which point you return true. Be careful of off-by-one errors; some strings will have an even length, some will have an odd length.
If your palindrome checker is case insensitive, then use string.toLowerCase().toCharArray() to preprocess the character array.
You can use string.charAt(i) instead of string.toCharArray() in the for loop; in this case, if the palindrome checker is case insensitive then preprocess the string with string = string.toLowerCase()
Let's break the problem down: In the end, you are checking if the reverse of the word is equal to the word. I'm going to assume you have all of the words stored in an array called wordArray[].
I have some code for getting the reverse of the word (copied from here):
public String reverse(String str) {
if ((null == str) || (str.length() <= 1)) {
return str;
}
return new StringBuffer(str).reverse().toString();
}
So, now we just need to call that on every word. So:
for(int count = 0; count<wordArray.length;count++) {
String currentWord = wordArray[count];
if(currentWord.equals(reverse(currentWord)) {
//it's a palendrome, do something
}
}
Since this is homework, i'll not supply you with code.
When i code, the first thing i do is take a step back and ask myself,
"what am i trying to get the computer to do that i would do myself?"
Ok, so you've got this huuuuge string. Probably something like this: "lkasjdfkajsdf adda aksdjfkasdjf ghhg kajsdfkajsdf oopoo"
etc..
A string's length will either be odd or even. So, first, check that.
The odd/even will be used to figure out how many letters to read in.
If the word is odd, read in ((length-1)/2) characters.
if even (length/2) characters.
Then, compare those characters to the last characters. Notice that you'll need to skip the middle character for an odd-lengthed string.
Instead of what you have above, which checks the 1st and 2nd, then 2nd and 3rd, then 3rd and fourth characters, check from the front and back inwards, like so.
while (reader.hasNext()) {
String word = reader.nextLine();
boolean checker = true;
for (int i = 0; i < word.length(); i++) {
if(word.length()<2){return;}
if (word.charAt(i) != word.charAt(word.length()-i) {
checker = false;
}
}
if(checker == true)
{System.out.println(word);}
}

Categories

Resources