Compare a char to an array of chars? - java

package loopPractice;
import java.util.Scanner;
public class replaceVowels {
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
System.out.print("Enter a string: ");
String s = sc.nextLine();
String originalString = s;
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c.equals(vowels[i])){
String front = s.substring(0, i);
String back = s.substring(i + 1);
s = front + "" + back;
}
}
System.out.println(originalString);
System.out.println(s);
}
}
The job is to replace all vowels in a word, How can i replace every vowel using an array of vowels?
The question is: Write a method that returns a String that is a copy of a String parameter, but without any vowels

Well, in the spirit of your question, you could write a new function that checks if an array contains a character:
public static void main(String[] args) {
System.out.print("Enter a string: ");
String s = sc.nextLine();
String originalString = s;
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (contains(c, vowels)) {
String front = s.substring(0, i);
String back = s.substring(i + 1);
s = front + "" + back;
}
}
System.out.println(originalString);
System.out.println(s);
}
private static boolean contains(char c, char[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == c) {
return true;
}
}
return false;
}

There are three big problems with this code.
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c.equals(vowels[i])){
String front = s.substring(0, i);
String back = s.substring(i + 1);
s = front + "" + back;
}
}
First, you can't use equals on a char, since char is a primitive type. Use ==.
Second, you're not checking for vowels properly. The above code compares the 0'th character of 's' to the 0'th character in the vowels array; that is, it compares it to 'a' but not to any other vowel. Similarly, it compares the character at index 1 to 'e', but not any other vowel, the character as 2 to 'i', etc.; when you get up to index 5, the program will throw an exception because vowels isn't that big.
The solution is that you need a double loop (or nested loop). For each character in s, you will need to check it against every character in the vowels array (or at least until you hit a match). So you'll need something like
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
boolean isAVowel = false;
for (int j = 0; j < vowels.length; j++) {
if (c == vowels[j]) {
isAVowel = true;
break; // will leave the inner loop but not the outer loop
}
// I'll let you finish the rest
As #cptcactus demonstrated in his answer, moving the inner loop to a new method is a good way to implement this kind of solution.
The third problem is more subtle. When you're looping through indexes in an array or string, and the loop removes elements from the array or string, you have to be very careful because the indexes will shift. Suppose your code did approximately this:
for (int i = 0; i < s.length(); i++) {
if [[[ s.charAt(i) is a vowel ]]] {
[[[ remove the i'th character from s; ]]]
}
}
Say s is "air". First i is set to 0, and s.charAt(i) is 'a'. This is a vowel, so we remove it. This means s is now "ir". Then we loop back and set i to 1. Now s.charAt(i) is 'r' since it uses the new value of s, and it never looks at the vowel 'i'.
A couple ways to work around that problem are:
make sure i is not incremented if you remove a character from it (you could use i-- which will cancel out the i++);
go backwards through the indexes (i.e. start with s.length()-1 and decrement) instead of forwards.
(There are other ways to solve this, by using the replaceAll method or a Set<Character>, but I'm assuming that this is a class and your purpose is to learn the basics of loops and such.)

String.replaceAll("[aeiou](?!\\b)", "");
Reads: Match all vowels ([aeiou]) that are not followed ((?!...)) by an "end of word" (\b). For more information read the Javadoc on java.util.regex.Pattern;
even simpler would be this (equivalent but simpler) regex:
String.replaceAll("[aeiou]\\B", "");

Related

What is the best way to replace a letter with the letter following it in the alphabet in Java?

I'm a programming newbie and I am doing a coderbyte exercise that says "
Replace every letter in the string with the letter following it in the alphabet (ie. c becomes d, z becomes a)"
i'm thinking of the following methods:
declare a string called "abcdefghijklmnopqrstuvxyz" and compare each string's char index position with the alphabet's index position, and then just bring the alphabet char that is located at the i+1 index location. But I don't know how it would work from z to a.
I've seen some techniques using ASCII values for every char but I've never done that before and not sure how it works
convert the given string into a char[] array, but then I'm not sure how I would tell the system to get me the next alphabet char
What would be the easiest way to do this?
EDIT
this is my code so far, but it doesn't work.
import java.util.*;
import java.io.*;
class Main {
public static String LetterChanges(String str) {
// code goes here
String alphabet = "abcdefghijklmnopqrstuvwxyz";
String newWord = "";
for (int i = 0; i < str.length(); i++){
for (int j = 0; j < alphabet.length(); i++){
if (str[i] == alphabet[i]){
if (alphabet[i+1].isVowel()){
newWord = newWord + toUpperCase(alphabet[i+1]);
}
else{
newWord = newWord + alphabet[i+1];
}
}
}
}
return str;
}
public static void main (String[] args) {
// keep this function call here
Scanner s = new Scanner(System.in);
System.out.print(LetterChanges(s.nextLine()));
}
}
Can't I ask for the index position of a Char that is a part of a String? in C I could do that.
Other than that not sure why it doesn't work.
I would definitely go with method 1.
I believe what you're looking for is the indexOf method on a String.
First of, I would create a method that given a character finds the next letter in the alphabet and return that. This could be done by finding the letter in your alphabet string and then fetch the letter at index+1. As you also pointed out you would need to take care of the edge case to turn 'z' into 'a', could by done with an if-statement or by having an extra letter 'a' at the end of your alphabet string.
Now all that remains to do is create a loop that runs over all characters in the message and calls the previously made method on that character and constuct a new string with the output.
Hope this helps you figure out a solution.
Assuming that there would be only lower case English letters in the given String the most performant way would be to add +1 to every character, and use either if-statement checking whethe the initial character was z or use the modulo operator % as #sp00m has pointed out in the comment.
Performing a search in the alphabetic string (option 1 in your list) is redundant, as well extracting array char[] from the given string (option 3).
Checking the edge case:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = str.charAt(i);
if (next == 'z') result.append('a'); // checking the edge case
else result.append((char) (next + 1));
}
return result.toString();
}
Applying modulo operator:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = (char) ((str.charAt(i) - 'a' + 1) % 26 + 'a');
result.append(next);
}
return result.toString();
}
main()
public static void main(String[] args) {
System.out.println(shiftLetters("abc"));
System.out.println(shiftLetters("wxyz"));
}
Output:
bcd // "abc"
xyza // "wxyz"

Incorrect output in small program. Why is this String variable not doing what I want it to?

This program should take a String, check if each letter is a vowel and change the vowels into underscores. For example, if I enter some it should output s_m_. This is a simple programming exercise that I feel like I should be able to do. However I am genuinely stumped and can't tell what I'm doing wrong.
I have declared an array to keep the vowels, a newStr variable which will contain the updated string ,and I'm looping through the string, comparing each letter using charAt() to check if it's in the vowels array. If it is, I add _ to the updated String, and I keep the original letter if it's not. The final output is wrong, what am I doing wrong?
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
String newStr = "";
for (int x = 0; x < str.length(); x++) {
char letter = str.charAt(x);
for (int j = 0; j < vowels.length; j++) {
if (letter == vowels[j]) {
newStr = newStr + '_';
break;
} else {
newStr = newStr + letter;
break;
}
}
}
out.println(newStr);
In your code the issue is within your nested "for-loop". I say this in quotes because it never actually loops. The first iteration j=0 immediately breaks the loop since either your letter is equal to a with (letter == vowels[0]) or not. In either case you do a break; and append the character. This means your loop can be reduced to a simple if-else that checks if the letter is an a and replaces it with _ or keeps it.
To fix this issue you need to use a different approach. You can create a String of vowels such as "aeiouAEIOU" and use indexOf to test whether the selected character is a vowel.
public static String omitVowels(String input) {
StringBuilder out = new StringBuilder(input.length());
String vowels = "aeiouAEIOU";
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (vowels.indexOf(c) >= 0) // is vowel if index not negative
out.append('_');
else
out.append(c);
}
return out.toString();
}
indexOf(char) will return -1 if the provided character is not part of the string, else it will return the specific index. We can use this property to test whether the character is a vowel or not.
Examples
omitVowels("hello world") -> "h_ll_ w_rld"
omitVowels("aeiou") -> "_____"
omitVowels("TESTing") -> "T_ST_ng"
This is pretty simple. Just iterate over each character of the given string and replace with _ in case of it is vowel.
Use StringBuilder
Be ware of using String. This is immutable in java, therefore to build final string, you should use StringBuilder.
public static String replaceVowel(String str) {
final IntPredicate isVowel = ch -> ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
StringBuilder buf = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
boolean vowel = isVowel.test(Character.toLowerCase(ch));
buf.append(vowel ? '_' : ch);
}
return buf.toString();
}
Use RegularExpression
As alternative, you can use Regular Expression with replaceAll() method of the String class.
private static final Pattern VOWEL = Pattern.compile("[aeiou]");
public static String replaceVowel(String str) {
return VOWEL.matcher(str).replaceAll("_");
}
This is also correct, because in the background, replaceAll() uses StringBUilder.
for (int x = 0; x < str.length(); x++) {
char letter = str.charAt(x);
boolean toReplace = false;
for (int j = 0; j < vowels.length; j++) {
if (letter == vowels[j]) {
toReplace = true;
break;
}
}
if (toReplace) {
newStr = newStr + "_";
} else {
newStr = newStr + letter;
}
}

Replace vowel with next does not work

I have a string input and want to replace every vowel in that string with its next vowel.
However, it does not seem to work correct. I have tried various input like:
venky -> vinky // Correct
ui -> uo // Incorrect, expected ao
ai -> ao // Incorrect, expected eo
The vowel order is
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
My code is:
package test;
import java.util.Scanner;
public class Problem1 {
public static void main(String args[]) {
Scanner r = new Scanner(System.in);
String str, res;
char ch;
int i, j;
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
System.out.println("Enter a string");
str = r.nextLine();
res = str;
for (i = 0; i < str.length(); i++) {
ch = str.charAt(i);
for (j = 0; j < 4; j++) {
if (ch == 'u') {
res = str.replace(ch, 'a');
break;
} else if (ch == vowels[j]) {
res = str.replace(ch, vowels[j+1]);
break;
}
}
}
System.out.println("String after replacing the vowels with next vowel : "
+ res);
}
}
Your problem is here:
res = str.replace(ch, vowels[j+1]);
Consider the input ai. The 1st time you pass here you change the value of res to ei, the second time you replace the i in the initial string ai, not in the modified one. So res gets the new value ao.
Anyway, even if you fix this particular case you may hit some other issue with longs words containing many wovels as you replace the first occurence (imagine the case of ae you would get ie). You should build the result one char at a time, with either the unmodified letter or the next wovel.
You are replacing the vowel in your str variable and saving it to res then you break and continue on your str which has the previous vowel not replaced.
You would need put your response together char by char
Your problem is String.replace will replace all occurrence of a char in your String.
Since you traverse over your String, one original character might be replaced multiple times, for example:
acac -> ecec -> ecic
You will receive ecic instead of ecec.
So I think you can create another String based on the current Strin to avoid the sideeffect of String.replace:
char[] output = new char[str.length()];
for(i = 0; i < str.length(); i++) {
ch = str.charAt(i);
for (j = 0; j < 4; j++) {
if (ch == 'u') {
output[i] = 'a';
} else if(ch == vowels[j]) {
output[i] = vowels[j+1];
} else {
output[i] = ch;
}
}
}
String res = new String(output);
res = str.replace(ch, vowels[j+1]);
will replace the string value and put in res variable but on the next time it will not use the old res variable for further modification thats why it is giving wrong answer try changing.
str = str.replace(ch, 'a');
str = str.replace(ch, vowels[j+1]);
and print str instead of len

How can i replace a char in a String using chars from another string (Caesar Cypher)(JAVA)

I'm doing a caesar-cypher. Trying to replace all characters from a string to a certain character from the shifted alphabet.
Here is my code so far
public static String caesarify(String str, int key){
String alphabetNormal = shiftAlphabet(0);
String alphabetShifted = shiftAlphabet(key);
for (int i =0; i < str.length();i++){
for (int c =0; c < alphabetNormal.length(); c++) {
if (str.charAt(i) == alphabetNormal.charAt(c)) {
char replacement = alphabetShifted.charAt(c);
str.replace(str.charAt(i), replacement);
}
}
}
return str;
}
public static String shiftAlphabet(int shift) {
int start =0;
if (shift < 0) {
start = (int) 'Z' + shift + 1;
} else {
start = 'A' + shift;
}
String result = "";
char currChar = (char) start;
for(; currChar <= 'Z'; ++currChar) {
result = result + currChar;
}
if(result.length() < 26) {
for(currChar = 'A'; result.length() < 26; ++currChar) {
result = result + currChar;
}
}
return result;
}
I don't know why the string for example "ILIKEDONUTS" doesn't change to "JMJLFEPOVUT" when it's caesarified.
Don't use replace(), or any replace method, to replace a character at a given index in a String. It doesn't work. You're hoping that
str.replace(str.charAt(i), replacement);
will replace the i'th character of str. As pointed out in the other (now deleted) answer, str.replace doesn't change str itself, so you'd need to write
str = str.replace(str.charAt(i), replacement);
But that doesn't work. The replace() method doesn't know what your index i is. It only knows what character to replace. And, as the javadoc for replace() says, it replaces all characters in the string. So suppose that str.charAt(i) is 'a', and you want to replace it with 'd'. This code would replace all a characters with d, including (1) those that you already replaced with a earlier in the loop, so that this will defeat the work you've already done; and (2) a characters that come after this one, which you want to replace with d, but this will fail because later in the loop you will see d and replace it with g.
So you can't use replace(). There are a number of ways to replace the i'th character of a string, including using substring():
str = str.substring(0, i) + replacement + str.substring(i + 1);
But there are better ways, if you are going to replace every character. One is to create a StringBuilder from str, use StringBuilder's setCharAt method to change characters at specified indexes, and then convert the StringBuilder back to a String at the end. You should be able to look at the javadoc to find out what methods to use.
More: After looking into this more, I see why it was returning all A's. This inner loop has an error:
for (int c =0; c < alphabetNormal.length(); c++) {
if (str.charAt(i) == alphabetNormal.charAt(c)) {
char replacement = alphabetShifted.charAt(c);
str.replace(str.charAt(i), replacement);
}
}
Suppose key is 1, and the current character is 'C'. Your inner loop will eventually find C in alphabetNormal; it finds the corresponding character in alphabetShifted, which is D, and replaces C with D.
But then it loops back. Since the next character in alphabetNormal is D, it now matches the new str.char(i), which is now D, and therefore changes it again, to E. Then it loops back, and ... you get the picture.
replace below line
str.replace(str.charAt(i), replacement);
With
str= str.replace(str.charAt(i), replacement);
or you can make a String arr and then replace character in that. in the end create a new string from that array and return.
a better version of caesarify():
public static String caesarify(String str, int key){
String alphabetNormal = shiftAlphabet(0);
String alphabetShifted = shiftAlphabet(key);
//create a char array
char[] arr=str.toCharArray();
//always try to create variable outside of loop
char replacement
for (int i =0; i < arr.length();i++){
for (int c =0; c < alphabetNormal.length(); c++) {
if (arr[i] == alphabetNormal.charAt(c)) {
replacement = alphabetShifted.charAt(c);
//replace char on specific position in the array
arr[i]= replacement;
}
}
}
//return arrray as String
return new String(arr);
}

Can't seem to clone char in a string

I have this assignment in school to check input string (through BufferedReader), if that string contains any vowels (like, in my language, a, ā, e, ē etc) and if they are there, you have to put character 'p' after that vowel and even after that 'p' char you have to put that vowel, after which that 'p' was inserted.
Sounds like this: dog => dopog; snails => snapaipils and so on.
The thing is - I made it working so that this char 'p' is in the right spot, but I can't put that vowel after char 'p'. For now I am getting like, dog => dopg.
In my code here:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Ld2151rdb255 {
static char[] patskani = { 'a', 'ā', 'e', 'ē', 'i', 'ī', 'u', 'ū', 'o' };
static char character;
static StringBuilder input;
public static void main(String[] args) {
char charAtPosition;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
String valueEntered = br.readLine();
valueEntered = valueEntered.toLowerCase();
input = new StringBuilder(valueEntered);
// should use "String.contain"
for (int i = 0; i < input.length(); i++) {
for (int j = 0; j < patskani.length; j++) {
charAtPosition = input.charAt(i);
if (charAtPosition == patskani[j]) {
input.insert(i + 1, 'p');
// input.insert(i + 2, charAtPosition);
}
}
}
} catch (IOException e) {
System.out.println("input-output error");
}
// Rezultātu izvade
String result = input.toString();
System.out.println(result);
}
}
I tried to put input.insert(i + 2, charAtPosition);, but yea - it smells like IndexOutOfBoundary exception. It really is, no matter, how I changed the index and what method I approached to do the task.
Don't worry much about object 'patskani'. Just a 'vowels' in my language.
Any help would be appreciated, because I am kinda stuck there and don't know if there's a way of doing it just by continuing or I have to rewrite the logic.
Thanks in advance!
I would suggest that you build the output step by step, that will be easier.
So get the char, add it to the output, check if it's a patskani and if so append a p:
input = new StringBuilder(); // should be named output most likely
for (int i = 0; i < valueEntered.length(); i++) {
// get the i-th char
charAtPosition = valueEntered.charAt(i);
// append this char to "output"
input.append(charAtPosition);
// check if the char is in "patskani"
for (int j = 0; j < patskani.length; j++) {
if (charAtPosition == patskani[j]) {
// if so, append a "p" and no need to continue checking
input.append('p');
break;
}
}
}
Something like that (demo here). As a side note, note that there is something called enhanced for loop that can be handy.

Categories

Resources