Java - Adding Asterisks between a user inputted string - java

I'm working on a class assignment with a few individual parts, which I have all done with the exception of this one. I need to get a string input from the user and create a loop (preferably a for loop) that inserts asterisks between each character. I'm completely stumped on this one so if someone could just give me some help to get started it would be appreciated.
Edit: I've come up with this so far
} else if (choice.equalsIgnoreCase("C")) {
System.out.print("Enter text here: ");
String orig = input.nextLine();
// To use for asterisk insertion
int x = 1;
int y = 2;
for (int length = orig.length(); length > 0;) {
orig = orig.substring(0,x) + "*" + orig.substring(y);
x = x + 2;
y = y + 2;
}
}
It compiles just fine but when I test it and enter some text it comes up with
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 5

You could use a for loop on the characters of the String (see below), but I would just do this:
str = str.replaceAll("(?<=.)(?=.)", "*");
The regex in the search parameter matches the point between any two characters, achieved by using a look-behind and a look-ahead, each asserting that there's a character there.
If you must use a loop, the simplest code is probably:
String result = input.isEmpty() ? "" : input.substring(0, 1);
for (int i = 1; i < input.length(); i++)
result += "*" + input.charAt(i);
The somewhat complicated first line caters for the edge case of the user entering a blank. The for loop already caters for blank input, because the terminating condition will always be false for blank, so it won't iterate at all.

Related

How to increment conditionally?

so im a complete beginner and I was wondering if it was possible to increment a counter conditionally. I am trying to count the letter “I” in a sentence and everytime i pass an “I”, i want counter to increment by 1 but if there is more than 1 of these together “III” it still only increments by 1 until there a character after it like “IIIaI” which would count as 2 instances.
Is this possible?
Sorry guys, here is my code:
public static int countTheIs(string sentence){
int iCounter = 0;
String iCount = "iI"; //both cases included
for (int j = 0; j < sentence.length(); j++){
char ch =sentence.charAt(j);
if (iCount.indexOf(ch) != -1){
iCounter++;
}
}
}
You are actually quite far already, all you need to do is to check the previous character. This can be done the following way:
String sentence = "Test i two II three iIi";
int iCounter = 0;
String iCount = "iI";
for (int j = 0; j < sentence.length(); j++){
char current = sentence.charAt(j);
char previous; //1
if (j==0) {
previous = 'Z'; //2
} else {
previous = sentence.charAt(j-1); //3
}
if (iCount.indexOf(current) != -1 && iCount.indexOf(previous) == -1 ){ //4
iCounter++;
}
}
Let me explain to you what I have done, according to my // tags
//1 We make a new char variable holding the previous character.
//2 Because the first index of the String has no previous characters, we will set it to a random, non-matching character to prevent errors at the start. I picked Z in this example.
//3 If there is a previous character, we get this by subtracting 1 from j
//4 We check in the if statement if the currenct character is in iCount, and the previous character is not in iCount. If this is the case, the counter will increase.
When the above code is ran, the result will output 3.
OK, I'm going to assume that you have a string input, you are counting by using a loop and then using charAt(x)(x is the number you use to increment the loop) and then comparing.
Simply check if charAt(x-1) is also I. If it is, then don't increment i. Also, you want to make sure x>0 otherwise it will throw an error.
Please run the below code:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CountI {
public static void main(String[] args) {
String input = "IIiaIii";
String regex = "([A-Za-z])\\1+";
Pattern pattern = Pattern.compile(regex , Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(input);
String output = matcher.replaceAll("$1");
int result = 0;
for(int i = 0; i < output.length(); i++){
if(output.charAt(i) == 73 || output.charAt(i) == 105){
result++;
}
}
System.out.println(result);
}
}
Output:
2
Process finished with exit code 0
You want Regular Expressions and the Java Pattern class (https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html).
In my sample below I used "w" instead of "l" because it's easier to distinguish. Using regular expressions, define a pattern that will capture one or more consecutive occurrences of the letter: w+, then use a matcher, count the number of times it matches.
String input = "wwowwee w w w";
Pattern p = Pattern.compile("w+");
Matcher matcher = p.matcher(input);
int count = 0;
while(matcher.find()) {
count++;
}
System.out.println("Count: " + count);
Or, simply split the string and count the number of splits:
String input = "wwowwee w w w";
Pattern p = Pattern.compile("w+");
String[] tokens = p.split(input);
System.out.println("token count: " + tokens.length);
Both give the correct results.
Edit: This doesn't answer the question about incrementing a counter conditionally, but it solves the problem that question was posed to address.

Maximum repeating sequence instead of longest repeating sequence

I am trying to get the most repeated sequence of characters in a string.
For example :
Input:
s = "abccbaabccba"
Output:
2
I have used dynamic programming to figure out the repeating sequence, but this returns the longest repeating character sequence. For example:
Input:
s = "abcabcabcabc"
Output:
2
2(abcabc,abcabc) instead of 4(abc,abc,abc,abc)
Here is the part of the code where I'm filling the DP table and extracting repeating sequence. Can anyone suggest how I can get the most repeating sequence?
//Run through the string and fill the DP table.
char[] chars = s.toCharArray();
for(int i = 1; i <= length; i++){
for(int j = 1; j <= length; j++){
if( chars[i-1] == chars[j-1] && Math.abs(i-j) > table[i-1][j-1]){
table[i][j] = table[i-1][j-1] + 1;
if(table[i][j] > max_length_sub){
max_length_sub = table[i][j];
array_index = Math.min(i, j);
}
}else{
table[i][j] = 0;
}
}
}
//Check if there was a repeating sequence and return the number of times it occurred.
if( max_length_sub > 0 ){
String temp = s;
String subSeq = "";
for(int i = (array_index - max_length_sub); i< max_length_sub; i++){
subSeq = subSeq + s.charAt(i);
}
System.out.println( subSeq );
Pattern pattern = Pattern.compile(subSeq);
Matcher matcher = pattern.matcher(s);
int count = 0;
while (matcher.find())
count++;
// To find left overs - doesn't seem to matter
String[] splits = temp.split(subSeq);
if (splits.length == 0){
return count;
}else{
return 0;
}
}
Simple and dump, the the smallest sequence to be considered is a pair of characters (*):
loop over the whole String an get every consecutive pair of characters, like using a for and substring to get the characters;
count the occurrence of that pair in the String, create a method countOccurrences() using indexof(String, int) or regular expressions; and
store the greatest count, use one variable maxCount outside the loop and an if to check if the actual count is greater (or Math.max())
(*) if "abc" occurs 5 times, than "ab" (and "bc") will occur at least 5 times too - so it is enough to search just for "ab" and "bc", not need to check "abc"
Edit without leftovers, see comments, summary:
check if the first character is repeated over the whole string, if not
check if the 2 initial characters are repeated all over, if not
check if the 3 ...
at least 2 counters/loops needed: one for the number of characters to test, second for the position being tested. Some arithmetic could be used to improve performance: the length of the string must be divisible by the number of repeated characters without remainder.

String.split replication: OutOfBoundsException

For my CompSci class, we're making a Would You Rather? function for our chatbot project. The String.split() method works well for this, but we get bonus points if we can do it without it. I decided to go about this by just creating a method that replicated String.split.
private String[] separate (String phrase, String omit1, String omit2)
{
int c = 0;
//gets rid of leading and trailing whitespace, replaces target characters
//with the # character
phrase = phrase.trim();
phrase = phrase.replace(omit1, "#");
phrase = phrase.replace(omit2, "#");
//detects the number of phrases to be included in the array
for (int i = 0; i < phrase.length(); i++)
if (phrase.charAt(i) == '#')
c++;
//creates array list based on number of phrases
String[] phraseList = new String[c];
c = 0;
//builds phrases from characters found between occurrences
//of the # character
for (int i = 0; i < phrase.length(); i++)
{
if (phrase.charAt(i) == '#')
c++;
else if (phrase.charAt(i) != '#')
phraseList[c] += phrase.charAt(i);
}
return phraseList;
}
Whenever I use this method with the phrase "Would you rather have tea, eat cookie, or push up?" (omit1 being "," and omit2 being "or") it throws this Exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at Magpie.separate(Magpie.java:306)
at Magpie.getResponse(Magpie.java:44)
at MagpieRunner.main(MagpieRunner.java:24)
I realize that this has something to do with the counter for the phraseList array, but my attempts to fix it have so far been to no avail.
Any Help?
because if you have even 1 # you will have 2 strings so you need to do c+1 while creating a new array
Like
//creates array list based on number of phrases
String[] phraseList = new String[c+1];
c = 0;
you should use replaceAll(omit1,"#") and not replace(omit1,"#") & replace(omit2,"#")
Can you give more information on where the null is coming ?
Edit:
Have you tried something like ?
phraseList[0]="";
for(int i = 0; i < phrase.length(); i++)
{
if(phrase.charAt(i) == '#')
{
c++;
phraseList[c]="";
}else if(phrase.charAt(i) != '#')
{
phraseList[c] += phrase.charAt(i);
}
}
Think of it like commas separating a list:
1 , 2 , 3 , 4 , 5 , 6
If you count the commas, you'll find there are five; but there are six entries in the list. That's because commas separate the entries, but you still have one on each end.
Or think in terms of fence posts and panels: five posts, four panels.
When you create your array to store the phrases, you need one more entry than you had split points, to make sure you have room for all the phrases.
But it would be easier to avoid this entirely and return a List<String> rather than a String[]. That way, you don't need to know the size in advance.
Since other answers showed you what's wrong with your code, here is a cleaner way of separating string that you might like and that behaves more like the actual split() method:
private String[] separate(String phrase, String delim) {
List<String> tokens = new ArrayList<String>();
// add delimiter to the end of the string
// so last token will be included properly
phrase += delim;
// start from index of first deliminator
// i is the index for the deliminator
// j is the index for the first char of the expression before deliminator
int i, j = 0;
// while there are deliminators
while( (i = phrase.indexOf(delim, j)) != -1) {
// obtain the current token from j to deliminator location
String token = phrase.substring(j, i);
// trim leading/trailing spaces of the token and make sure it has any chars
// if it does, add the token to list
if(token.trim().length() != 0) {
tokens.add(token);
}
// update j to the first character after the deliminator
j = i + delim.length();
}
return tokens.toArray(new String[0]);
}
why not use StringTokenizer? (Below is an example from Java doc)
The following is one example of the use of the tokenizer. The code:
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
prints the following output:
this
is
a
test
Arrays are indexed starting from 0, but the length of the array is determined with an initial value of 1.
So even though c gives you the number of phrases, its actually the number of indices in the array (since c starts from 0) and not the actual length. The actual length will be c + 1 (since length is calculated starting from 1)
Index 0 | 1 | 2 | 3 | 4
Length 1 | 2 | 3 | 4 | 5
For example, if c = 4 (Index = 4), your String[] will have length 4, when it should be 5. This is what throws that ArrayIndexOutOfBounds. Hope this helps :)

it works in c but not in java?

The following code to gets the vowel deleted from array, and the array rearranges itself.
public static void main(String[] args) {
int a = 0,k=0;
Scanner obj = new Scanner(System.in);
System.out.println("enter string");
String s= obj.nextLine();
char c[]=new char[s.length()];
c = s.toCharArray();
for(int i =0; i<s.length();i++){
if(c[i]=='a'|| c[i]=='i'|| c[i]=='o'||c[i]=='u'||c[i]=='e'){
for(int j=0;j<s.length();j++){
c[j]=c[j+1];
}
}
}
In the j for loop, you have this statement:
c[j]=c[j+1];
The ArrayIndexOutOfBoundsException comes when j is the last possible index, and you attempt to access the index element one too high.
You can stop when you get to s.length() - 1.
Additionally, you are shifting everything down, not just past where you found a vowel. Start your j for loop not at 0, but at i.
for(int j=i;j<s.length() - 1;j++){
You'll also have to decide what to do with the end of the array, which is not getting overwritten with anything here.
You can't change an array by pointing one location to the next: c[j]=c[j+1]; That line will only replace the character at c[j] but it won't remove that position entirely from the array. You'd need to create a new array with the vowels removed.
This also explains the out-of-bounds exception which happens when you're at the end of the array. You're trying to access the element at j + 1 but that is outside the array.
for(int j=0;j<s.length();j++){
c[j]=c[j+1];
}
Your problem is here. c[j+1] is referencing a location beyond the end of your array. When you assign c[j] a value from that location, you're trying to retrieve a location that does not exist. This causes an ArrayOutOfBoundsException.
You can achieve the same effect by transforming the string with a RegExp:
s.replaceAll("[aioue]","");
This works in C because the size of the string with strlen is one less than the actual size including the \0 at the end. When you copy all the characters down, you are moving the termination character as well. Java doesn't use termination characters and doesn't have a character which is beyond the end of the String.
In Java it is more natural to write a regular expression like this and work with Strings from the start.
System.out.println("enter string");
Scanner scan = new Scanner(System.in);
String line = scan.nextLine();
String noVowels = line.replaceAll("[AEIOUaeiou]", "");
System.out.println("Without vowels the line is '" + noVowels + "'");
Or you can use this regex
// (?i) mean case insensitive
String noVowels = line.replaceAll("(?i)[aeiou]", "");
you have the length of string is 4 and you put it on c[s.length] mean it start from 0-3 array indexing. in the second loop you swap the c[j+1] int c[j]. it cause array index out of bounds.
try this in the second loop
for (int j = 0; j < s.length()-1; j++)
{
System.out.println(c[j+1]);
c[j] = c[j + 1];
}

Why am I getting java.lang.StringIndexOutOfBoundsException?

I want to write a program that prints words incrementally until a complete sentence appears. For example : I need to write (input), and output:
I
I need
I need to
I need to write.
Here is my code:
public static void main(String[] args) {
String sentence = "I need to write.";
int len = sentence.length();
int numSpace=0;
System.out.println(sentence);
System.out.println(len);
for(int k=0; k<len; k++){
if(sentence.charAt(k)!='\t')
continue;
numSpace++;
}
System.out.println("Found "+numSpace +"\t in the string.");
int n=1;
for (int m = 1; m <=3; m++) {
n=sentence.indexOf('\t',n-1);
System.out.println("ligne"+m+sentence.substring(0, n));
}
}
and this is what I get:
I need to write.
16
Found 0 in the string.
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: -1 at
java.lang.String.substring(String.java:1937) at
split1.Split1.main(Split1.java:36) Java Result: 1 BUILD SUCCESSFUL
(total time: 0 seconds)
I don't understand why numSpace doesn't count the occurrences of spaces, nor why I don't get the correct output (even if I replace numSpace by 3 for example).
You don't have a \t character, so indexOf(..) returns -1
You try a substring from 0 to -1 - fails
The solution is to check:
if (n > -1) {
System.out.prinltn(...);
}
Your loop looking for numSpace is incorrect. You are looking for a \t which is a tab character, of which there are none in the string.
Further, when you loop in the bottom, you get an exception because you are trying to parse by that same\t, which will again return no results. The value of n in n=sentence.indexOf('\t',n-1); is going to return -1 which means "there is not last index of what you are looking for". Then you try to get an actual substring with the value of -1 which is an invalid substring, so you get an exception.
You are mistaken by the concept of \t which is an escape sequence for a horizontal tab and not for a whitespace character (space). Searching for ' ' would do the trick and find the whitespaces in your sentence.
This looks like homework, so my answer is a hint.
Hint: read the javadoc for String.indexOf paying attention to what it says about the value returned when the string / character is not found.
(In fact - even if this is not formal homework, you are clearly a Java beginner. And beginners need to learn that the javadocs are the first place to look when using an unfamiliar method.)
The easiest way to solve this I guess would be to split the String first by using the function String.split. Something like this:
static void sentence(String snt) {
String[] split = snt.split(" ");
for (int i = 0; i < split.length; i++) {
for (int j = 0; j <= i; j++) {
if (i == 1 && j == 0) System.out.print(split[j]);
else System.out.printf(" %s", split[j]);
}
}
}
As other people pointed out. You are counting every characters except tabs(\t) as a space. You need to check for spaces by
if (sentence.charAt(k) == ' ')
\t represents a tab. To look for a space, just use ' '.
.indexOf() returns -1 if it can't find a character in the string. So we keep looping until .indexOf() returns -1.
Use of continue wasn't really needed here. We increment numSpaces when we encounter a space.
System.out.format is useful when we want to mix literal strings and variables. No ugly +s needed.
String sentence = "I need to write.";
int len = sentence.length();
int numSpace = 0;
for (int k = 0; k < len; k++) {
if (sentence.charAt(k) == ' ') {
numSpace++;
}
}
System.out.format("Found %s in the string.\n", numSpace);
int index = sentence.indexOf(' ');
while(index > -1) {
System.out.println(sentence.substring(0, index));
index = sentence.indexOf(' ', index + 1);
}
System.out.println(sentence);
}
Try this, it should pretty much do what you want. I figure you have already finished this so I just made the code real fast. Read the comments for the reasons behind the code.
public static void main(String[] args) {
String sentence = "I need to write.";
int len = sentence.length();
String[] broken = sentence.split(" "); //Doing this instead of the counting of characters is just easier...
/*
* The split method makes it where it populates the array based on either side of a " "
* (blank space) so at the array index of 0 would be 'I' at 1 would be "need", etc.
*/
boolean done = false;
int n = 0;
while (!done) { // While done is false do the below
for (int i = 0; i <= n; i++) { //This prints out the below however many times the count of 'n' is.
/*
* The reason behind this is so that it will print just 'I' the first time when
* 'n' is 0 (because it only prints once starting at 0, which is 'I') but when 'n' is
* 1 it goes through twice making it print 2 times ('I' then 'need") and so on and so
* forth.
*/
System.out.print(broken[i] + " ");
}
System.out.println(); // Since the above method is a print this puts an '\n' (enter) moving the next prints on the next line
n++; //Makes 'n' go up so that it is larger for the next go around
if (n == broken.length) { //the '.length' portion says how many indexes there are in the array broken
/* If you don't have this then the 'while' will go on forever. basically when 'n' hits
* the same number as the amount of words in the array it stops printing.
*/
done = true;
}
}
}

Categories

Resources