I am trying to implement a substring method using only charAt method of the String class
The problem occurs when I include the last character in the search term 'hat.' otherwise everything works perfectly.
Also when searching for example for 'hat' I see the charAt(j) trace prints all 'h' with index 0 for all characters and true occurrence.
Here is the complete code:
public class SubString {
public static void main(String[] args) {
String line = "The cat in the hat.";
String item = "hat.";
System.out.println("'" + item + "' is substring of '" + line + "' : " + isSubString(item, line));
}
private static boolean isSubString(String item, String line) {
int i = 0;
int j = 0;
int count = 0;
for (i = 0; i < line.length() - item.length(); i++) {
for (j = 0; j < item.length(); j++) {
if (item.charAt(j) != line.charAt(i + j)) {
break;
}
if (item.charAt(j) == line.charAt(i + j)) {
System.out.println(item.charAt(j) + ":" + j + " - " + line.charAt(i + j) + ":" + (i + j));
count++;
}
if (count == item.length())
return true;
}
}
return false;
}
}
Again the problem occurs when searching for 'hat.' < == the last word with dot.
and the 'hat' which although return true but trace shows wrong characters ( only h's compared) and indexes are always 0.
The first loop omits the last character of the string. i.e, line.length() - item.length()
Please replace it with below for loop condition.
for (i = 0; i < line.length() - item.length() + 1; i++) {
you should try
line.contains(item)
Related
The assignment was to write a method that returns the row and column of the string "needle" in a 2D array of strings, and that there would either be one or zero of these "needle" strings.
I did this but I'm getting an error at line 10 (return "row: " + i + ", column: " + j;) saying "class expected", have no idea why since it's a simple return statement? Any help would be greatly appreciated<3
public String needleInHaystack(String[][] haystack)
{
boolean isNeedle = false;
for (int i = 0; i < haystack.length; i++) {
for (int j = 0; j < haystack[].length; j++) {
if (haystack[i][j].equals("needle")) {
isNeedle = true;
return "row: " + i + ", column: " + j;
}
}
}
if (isNeedle == false) {
return "none";
}
}
I am writing a program to find substring in the string in Java without using any Java Library.
I had written a function subString(String str1, String str2) as shown below.
It is working for the following input:
str1="rahul"
str2="My name is rahul"
str1="rahul"
str2="rahul sah"
str3="rahul"
str2="sah rahul"
The problem occurs when I give input as:
str1="rahul"
str2="rararahul"
str1="rahul"
str2="My name is sunil"
It goes to infinite loop. Can anyone have a look into my code snippet and help me out.
public static boolean subString(String str1, String str2) {
boolean found = false;
int len1 = str1.length();
int len2 = str2.length();
int status = 0;
char[] arr1 = new char[len1];
char[] arr2 = new char[len2];
for (int ii = 0; ii < len1; ii++) {
arr1[ii] = str1.charAt(ii);
}
for (int jj = 0; jj < len2; jj++) {
arr2[jj] = str2.charAt(jj);
}
for (int ii = 0; ii < len1; ii++) {
for (int jj = 0; jj < len2; jj++) {
if (arr1[ii] == arr2[jj]) {
if (ii < len1 - 1) {
System.out.println("Found1::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = true;
ii++;
} else if (arr1[ii] == arr2[jj] && ii == len1 - 1) {
System.out.println("Found2::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = true;
break;
}
} else if (found == false && arr1[ii] != arr2[jj]) {
System.out.println("Found3::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = false;
} else if (found == true && arr1[ii] != arr2[jj]) {
System.out.println("Found4::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = false;
ii = 0;
}
}
}
return found;
}
}
Others have suggested using String.contains() - which is java.lang code, rather than a Java library. However, you obviously want to explore how you could do this yourself. One way to do that is to look at the OpenJDK 7 source code for String.contains(), which under the covers uses String.indexOf(). You can see the (fairly basic) algorithm they use there.
Problem with your code
Interestingly, your code works for "rahul" and "rararahul" when I paste it into my dev environment. The infinite loop on non matching exists, though. This will occur for any str2 that contains any of the characters of str1. This is because once you find a match of any character in str1 within str2, you reset your variables to start again. Your output is actually enough to debug that, if you look at the sequence that it goes through each string.
Possible fix
If you want to pursue your own approach and learn from that then consider stopping and doing a little design on paper with your own approach. You're looking for an occurence of str1 in str2. So you probably want to swap your loops around. Then you can be more efficient. You can go through the longer String (str2) character by character in the outer loop. Then you only really need to go into the inner loop if the first character of the shorter string (str1) matches the character you're dealing with in str2.
e.g. for the loop bit of your code
boolean retFound = false;
for (int jj = 0; jj < len2; jj++) {
if (arr1[0] == arr2[jj]) {
boolean tempFound = true;
int foundIndex = jj;
for (int ii = 0; ii < len1; ii++) {
if (arr1[ii] != arr2[jj+ii]) {
tempFound = false;
break;
}
}
if (tempFound) {
System.out.println("Found substring " + str1 + " in " + str2 + " at index " + foundIndex);
System.out.println("Carrying on to look for further matches...");
tempFound = false;
retFound = true;
}
}
}
return retFound;
Note, this won't be fast, but it should work. I've tested on all the string samples you provided. You get a bonus too - it will find multiple matches. If you don't want that (just want true false), break out when it says "Carrying on to look for..."
As others have said, if you want to continue with your original code, certainly don't try to change loop variables (i.e. ii) within the inner loop. That's bad practice, hard to read and prone to lots of bugs.
in the block startin with
} else if (found == true && arr1[ii] != arr2[jj]) {
you set ii back to zero. And thats why ii never will be bigger or equals len1
You need to put the outer loop for jj and inner loop for ii:
int ii=0;
for (int jj = 0; jj < len2; jj++) {
if (arr1[ii] == arr2[jj]) {
if (ii < len1 - 1) {
System.out.println("Found1::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = true;
ii++;
} else if (arr1[ii] == arr2[jj] && ii == len1 - 1) {
System.out.println("Found2::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = true;
break;
}
} else if (found == false && arr1[ii] != arr2[jj]) {
System.out.println("Found3::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = false;
} else if (found == true && arr1[ii] != arr2[jj]) {
System.out.println("Found4::" + "arr1::" + arr1[ii]
+ "and arr2::" + arr2[jj]);
found = false;
ii = 0;
}
}
EDIT:
You are also initializing the inner for loop for each character in the larger string. You don't need two loops at all. I have changed it appropriately. This should work.
You can use one loop and matching condition where the search will begin when the first char will be found in the full string. And then, the search will continue where where the matching will one by one from the list.Okay, here I am giving an example to explain.
public static boolean subString2(String smallString, String fullString)
{
int k = 0;
for (int i = 0; i < fullString.length(); i++)
{
System.out.println("fullStringCharArray[i]: " + fullString.charAt(i));
if (smallString.charAt(k) == fullString.charAt(i))
{
System.out.println("Found: " + smallString.charAt(k));
k++;
if (k == smallString.length())
return true;
}
else
{
k = 0;
}
}
return false;
}
Here, what is happening, we are going to search in fullString. if the first char of your smallString 'rahul' is 'r' then until it is found, the other part of the string ('ahul') will not be matched. so when the 'r' is matched then it will try to search for 'a' and then 'h' and more. So, if the count of search true(k) is equal of smallString length then the substring exists. I hope, I could explain properly. Sorry for my English.
Use This Code.
This will help you and very short and clear
public static boolean subString(String str1, String str2) {
int str1Len = str2 == null ? 0 : str1.length();
int str2Len = str2 == null ? 0 : str2.length();
for (int i = 0; i < str2Len; i++) {
if (str1.charAt(0) == str2.charAt(i)) {
int count = 0;
for (int j = 0; j < str1Len; j++) {
if (str1.charAt(j) == str2.charAt(i)) {
i++;
count++;
}
}
if (count == str1Len) {
return true;
}
}
}
return false;
}
public class Main {
public static void main(String args[]) {
Scanner sc=new Scanner(System.in);
System.out.println("Enter the string");
String str=sc.nextLine();
String Str1=" ";
System.out.println("Enter the numbers");
int start=sc.nextInt();
int end=sc.nextInt();
for (int i = start; i < end; i++)
Str1 += String.valueOf(str.charAt(i));
System.out.println(Str1);
}
}
This is an experiment. My friend is trying to get a grasp on java and writes text outputs like the following example. I wanted to test myself if I could provide a program that could generate them.
For a String, the program should count each character and save how often and at what index it occurred and then generate a for-clause with an if-clause for each character like the following:
I want to put in e.g. "1234123412341234"
and get something like
public class ClauseText {
public static void main(String[] args) {
for(int i = 0; i < 16; i++) {
if (i == 0 || i == 4 || i == 8 || i == 12) {
System.out.print("a");
}
if (i == 1 || i == 5 || i == 9 || i == 13) {
System.out.print("b");
}
if (i == 2 || i == 6 || i == 10 || i == 14) {
System.out.print("c");
}
if (i == 3 || i == 7 || i == 11 || i == 15) {
System.out.print("d");
}
}
}
}
What I've come up with is so far is the following. I convert the input String to a char array and iterate through the array. I maintain three array lists, one for the character, one for how often it occurred, and one saves an ArrayList of Integers containing the index position where the character occurred.
To make it simpler, I decided to make all ArrayLists the size 128 and put each character to the index equalling its respective ASCII value.
But it doesn't seem to work, it's a simple Indexoutofboundsexception, however, I don't know what is wrong. Here:
The output only goes this far and then it crashes:
public class ClauseText {
public static void main(String[] args) {
for(int i = 0; i < 6; i++) {
if (i == 0 || i == 3) {
System.out.print("a");
}
if (i == 1 || i == 4) {
System.out.print("b");
}
if (i == 2 || i == 5
The program is:
import java.util.ArrayList;
public class StringToProgram {
public static void main(String[] args) {
// define and create program
String className = "ClauseText";
String program = makeProgram("abcabc", className);
}
public static String makeProgram(String myWord, String className) {
String program = "public class " + className + " {\n";
program += " public static void main(String[] args) {\n";
program += " for(int i = 0; i < " + myWord.length()
+ "; i++) {\n";
char[] myWordChar = myWord.toCharArray();
// For each character, we have to save the index where it occurs and how
// often. We want to hash it into the ArrayLists by ASCII value.
ArrayList<Character> characters = new ArrayList<Character>();
ArrayList<ArrayList<Integer>> indices = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> amounts = new ArrayList<Integer>();
// Initialize three lists with the size of the ASCII table
for (int i = 0; i < 128; i++) {
characters.add(null);
indices.add(new ArrayList<Integer>());
amounts.add(0);
}
// Now we iterate through each occurrence. We use the ASCII code to hash
// and find specific letters.
for (int i = 0; i < myWordChar.length; i++) {
int index = (int) myWordChar[i]; // the hash value of the char
if (amounts.get(index).equals(0)) {
// create new entries and append them to the
// given index of the lists
characters.add(index, myWordChar[i]);
indices.add(index, new ArrayList<Integer>());
indices.get(index).add((Integer) i);
amounts.add(index, 1);
} else {
// there is already an entry. modify it.
amounts.add(index, amounts.get(index) + 1); // ++
indices.get(index).add((Integer) i);
}
}
// Now, we iterate through the occurrences list. First, we check for
// each index if an object is saved there.
for (int i = 0; i < amounts.size(); i++) {
if (amounts.get(i) > 0) {
// When this is the case, we append an if clause.
program += " if (i == ";
for (int j = 0; j < amounts.get(i); j++) {
// The amount of options in the if clause depends on how
// often the character occurred in the string.
program += indices.get(i).get(j);
if (j + 1 < amounts.get(i)) {
// we still have to append an option
program += " || i == ";
}
}
program += ") {\n";
program += " System.out.print(\""
+ characters.get(i) + "\");\n";
program += " }\n";
}
}
program += " }\n";
program += " }\n";
program += "}";
System.out.println(program);
return program;
}
}
The error is the following:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
at StringToProgram.makeProgram(StringToProgram.java:60)
at StringToProgram.main(StringToProgram.java:8)
Perhaps you should start simpler:
public class StringToProgram {
public static void main(String[] args) {
// define and create program
String className = "ClauseText";
String program = makeProgram("a\nbca\rbc", className);
}
public static String makeProgram(String myWord, String className) {
myWord = myWord.replace("\\", "\\\\");
myWord = myWord.replace("\t", "\\t");
myWord = myWord.replace("\b", "\\b");
myWord = myWord.replace("\n", "\\n");
myWord = myWord.replace("\r", "\\r");
myWord = myWord.replace("\f", "\\f");
myWord = myWord.replace("\'", "\\\'");
myWord = myWord.replace("\"", "\\\"");
myWord = myWord.replace("\t", "\\t");
String program = "public class " + className + " {";
program += " public static void main(String[] args) {";
program += " System.out.println(\"" + myWord + "\");";
program += " }";
program += "}";
System.out.println(program);
return program;
}
}
I didn't use org.apache.commons.lang.StringEscapeUtils for clarity.
You get this exception because in some cases list returned in this line does not contain elements.
You need following code:
List<Integer> numbers = indices.get(i);
for (Integer number : numbers) {
program += number;
program += " || i == ";
}
instead your code:
program += indices.get(i).get(j);
if (j + 1 < amounts.get(i)) {
// we still have to append an option
program += " || i == ";
}
OK, so I'm doing this project that requires that I have the first and last setters of a string appear with the number of letters in between them counted, and output. I've tried repurposing some reverse a string code I had handy, but I cannot get the output to appear in my IDE.
Can anyone look over my code, and make some suggestions?
public static void main(String[] args) {
String countWord;
countWord = JOptionPane.showInputDialog(null,
"Enter the string you wish to have formatted:");
}
static String countMe(String countWord) {
int count = 1;
char first = countWord.charAt (0);
char last = countWord.charAt(-1);
StringBuilder word = new StringBuilder();
for(int i = countWord.length() - 1; i >= 0; --i)
if (countWord.charAt(i) != first ) {
if (countWord.charAt(i) != last) {
count++;
}
}
return countWord + first + count + last;
}
}
Just build it using charAt():
return "" + str.charAt(0) + (str.length() - 2) + str.charAt(str.length() - 1);
The "" at the front causes the numeric values that follow to be concatenated as Strings (instead of added arithmetically).
A slightly more terse alternative is:
return countWord.replaceAll("(.).*(.)", "$1" + (str.length() - 2) + "$2")
Once you determined the first and last chars, it is no need for unnecessary conditions. Just try this:
static String countMe(String countWord) {
char first = countWord.charAt(0);
char last = countWord.charAt(countWord.length()-1);
int count=0;
for (int i = 1; i < countWord.length()-1; i++)
{
count++;
}
return first + String.valueOf(count) + last;
}
Or, if it is not mandatory to use for loop, you can make it simple as this
static String countMe(String countWord) {
char first = countWord.charAt(0);
char last = countWord.charAt(countWord.length()-1);
int count = countWord.substring(1, countWord.length()-1).length();
return first + String.valueOf(count) + last;
}
You could use the string.length() method to obtain the total length of the string. Your code would be something like:
int totalLength = countWord.length();
int betweenLength = totalLength - 2; // This gives the count of characters between first and last letters
char first = countWord.charAt(0);
char last = countWord.charAt(str.length() - 1);
String answer = first + betweenLength + last;
import javax.swing.JOptionPane;
public class Main{
public static void main(String[] args) {
String countWord;
countWord = JOptionPane.showInputDialog(null,
"Enter the word you wish to have formatted:");
JOptionPane.showMessageDialog(null, countMe(countWord));
}
static String countMe(String countWord) {
int count = 0;
String first = String.valueOf(countWord.charAt(0));
String last = String.valueOf(countWord.charAt(countWord.length() - 1));
for(int i = 1; i < countWord.length() - 1; i++) {
if (String.valueOf(countWord.charAt(i)) != first ) {
count++;
}
}
return first + count + last;
}
}
I'm making a cryptography/cryptanalysis program using java as a homework for my master. Anyway, i use a method to delete the uselless whitespaces and make the String i display to the JTextArea proper. This method is great for small texts but it gives me a StringIndexOutOfBoundsException when i use bigger texts (loaded from a .txt file). Can anyone help?
Thanks in advance.
This is the method:
public void Data(String s) {
System.out.print("Analysis" + "\n" + s);
jTextArea1.setText(s);
StringBuilder buf = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (!Character.isWhitespace(s.charAt(i))) {
buf.append(s.charAt(i));
} else if (Character.isWhitespace(s.charAt(i)) && !Character.isWhitespace(s.charAt(i + 1))) {
buf.append(s.charAt(i));
}
}
System.out.println(buf.toString() + "\n" + "from buf");
jTextArea1.setText(buf.toString());
}
You are going up to s.length() in the for loop but accessing s.charAt(i + 1) in the second if statement. Try to only go up to s.length() - 1:
for (int i = 0; i < s.length() - 1; i++) {
if (!Character.isWhitespace(s.charAt(i))) {
buf.append(s.charAt(i));
} else if (Character.isWhitespace(s.charAt(i)) && !Character.isWhitespace(s.charAt(i + 1))) {
buf.append(s.charAt(i));
}
}
And then check the last character afterwards.
s.charAt(i + 1) in !Character.isWhitespace(s.charAt(i + 1))
It fails when i == s.length() - 1
You might want to use s.replaceAll("\\s\\s+"," ") instead of reinventing the wheel.
You are using this statement
Character.isWhitespace(s.charAt(i + 1)
meaning you are accessing an character of your string length plus 1.
hi i hope you can use the below one, instead the above
//StringBuilder buf = new StringBuilder();
/* These lines are not needed
for (int i = 0; i < s.length(); i++) {
if (!Character.isWhitespace(s.charAt(i))) {
buf.append(s.charAt(i));
} else if (Character.isWhitespace(s.charAt(i)) && !Character.isWhitespace(s.charAt(i + 1))) {
buf.append(s.charAt(i));
}`enter code here`
}
*/
s = s.replaceAll("\\s+"," ");
// Whenever you print the object(reference) toString() method is called by default. so no need to call explicitly
// System.out.println(buf.toString() + "\n" + "from s");
System.out.println(s + "\n" + "from buf");
// jTextArea1.setText(s);
jTextArea1.setText(s);