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

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.

Related

Put even characters in uppercase, but skipping spaces

I'm trying to convert some text so that every even character becomes uppercase. This works, but if there's a space between words, the code takes the space as a character too. So for example, if the input text is "this is a test", the output is "tHiS Is a tEsT". I want it to ignore the spaces and give "tHiS iS a TeSt" as output.
I now have the following code:
private String result;
private String letter;
private void generateText() {
result = "";
String input = editTextInput.getText().toString();
String lowerCase = input.toLowerCase();
char[] charArray = lowerCase.toCharArray();
for(int i=0;i<charArray.length;i++){
if(String.valueOf(charArray[i]).equals(" ")){
//I don't know what to put here
letter = String.valueOf(charArray[i]);
}else{
if(i%2 == 0){
letter = String.valueOf(charArray[i]);
}else if(i%2 == 1){
letter = String.valueOf(charArray[i]).toUpperCase();
}
}
result += letter ;
}
Log.d("result", result);
}
What do I have to do to skip the spaces?
If it's possible, I would like to skip punctuation marks too, or in general, every character which is not a letter.
Thanks in advance!
(For those who are wondering, I'm making a Spongebob meme text generator app)
If you want to do alternate logic in a loop, you could normally use i % 2 == 0, or (i & 1) == 1, but since the alternation is conditional, you need a variable to store the "state". With simple alternation, a boolean variable is the obvious choice.
Also, continuously converting each char to a String is bad for performance. Just update the char[].
private static String upperEven(String input) {
char[] buf = input.toLowerCase().toCharArray();
boolean upper = false;
for (int i = 0; i < buf.length; i++) {
if (Character.isLetter(buf[i])) {
if (upper)
buf[i] = Character.toUpperCase(buf[i]);
upper = ! upper;
}
}
return new String(buf);
}
Test
System.out.println(upperEven("this IS a TEST"));
Output
tHiS iS a TeSt
Code can be compressed/obscured to this: ;-)
private static String upperEven(String s) {
char[] c = s.toCharArray();
boolean t = false;
for (int i = 0; i < c.length; i++)
if (Character.isLetter(c[i]))
c[i] = ((t = ! t) ? Character.toLowerCase(c[i]) : Character.toUpperCase(c[i]));
return new String(c);
}
This is my solution.
private static void generateText() {
String result = "";
String input = "i am a engineer and student of nit.";
String lowerCase = input.toLowerCase();
Boolean isLower = false;
char[] charArray = lowerCase.toCharArray();
for (int i = 0; i < lowerCase.length(); i++) {
String letter = String.valueOf(charArray[i]);
if (!Character.isLetter(charArray[i])) {
result += letter;
} else {
if(isLower)
letter = letter.toUpperCase();
result += letter;
isLower = !isLower;
}
}
System.out.println(result);
}

Counting words in a string using methods

I have a project to make a program that takes a string as input and then prints the number of words in the string as output. We are supposed to use 3 methods in this, one to read input, one to print the output, and one to count the words.
I know I am missing something basic but I have spent hours on this and cannot figure out why the program wont run as it should. I need to keep the program pretty simple so I dont want to edit it too much, just find the issue and fix it so it will run correctly.
Example: Enter a string of text: The quick brown fox jumped over the lazy dog. 9 words
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter text: ");
String words = wordInput(in);
int count = wordCount(words);
System.out.println(words);
System.out.println(count);
printLine(count);
}
private static String wordInput(Scanner in)
{
String words = in.nextLine();
return words;
}
private static int wordCount(String words)
{
int length = words.length();
int ctr = 0;
int spot = 0;
int stop = 1;
char space = ' ';
char end = '.';
char com = ',';
char yes = '!';
char question = '?';
while (length > 0 && stop > 0)
{
if (words.charAt(spot) == space)
{
ctr++;
spot++;
}
else if (words.charAt(spot) == com)
{
spot++;
}
else if (words.charAt(spot) == yes || words.charAt(spot) == end || words.charAt(spot) == question)
{
stop = -1;
}
else if (spot > length)
{
stop = -1;
}
else
spot++;
}
return ctr + 1;
}
private static void printLine(int ctr)
{
System.out.println(ctr + " words");
}
Here is a rewritten wordCount that does as you request, minimal changes to the code. However, I am not sure it produces the answers you expect.
private static int wordCount(String words)
{
int length = words.length();
int ctr = 0;
int spot = 0;
char space = ' ';
char end = '.';
char com = ',';
char yes = '!';
char question = '?';
while (spot < length)
{
if (words.charAt(spot) == space)
{
ctr++;
spot++;
}
else if (words.charAt(spot) == com)
{
spot++;
}
else if (words.charAt(spot) == yes || words.charAt(spot) == end || words.charAt(spot) == question)
{
break;
}
else
spot++;
}
return ctr + 1;
}
However, fundamentally you are trying to count words in a string, and that is a known art. A few options and further reading:
http://www.quickprogrammingtips.com/java/find-number-of-words-in-a-string-in-java.html
Count words in a string method?
Which leads to a simpler result of:
private static int wordCount(String words) {
return words.split("\\s+").length;
}
Going on the assumption that whoever enters the string is not going to make a grammar error, try split the string at all spaces and set it equal to a string[]. Here is an example:
String temp = JOptionPane.showInputDialog(null, "Enter some text here");
String[] words = temp.split(" ");
JOptionPane.showMessage(null, String.format("Words used %d", words.length));

Replace two strings without overriding the other value

I have an assignment for school due at midnight today. I have finished almost all the assignment except for one question. I need to swap "r" and "q" with each other as values. So, if you enter "r" in the compiler you should get "q" if you enter "q" you get "r"(Using JOptionPane). For example, if your name is Quart, the compiler should print Ruaqt. I tried using the replace.All method, but once I can only swap "r" or "q" not both. I know I need a temporary variable, but do not know anything else...
We had to replace vowels with the letter after them so I did this:
String firstName = JOptionPane
.showInputDialog("What is your first name?");
String lastName = JOptionPane
.showInputDialog("What is your last name?");
String fullname = firstname + lastname;
String lowername = fullName.toLowerCase();
String encryptedname = lowername.replaceAll("a", "b")
.replaceAll("e", "f").replaceAll("i", "j").replaceAll("o", "p")
.replaceAll("u", "v");
Thanks
Dunno why the 2 answers using StringBuilder are both making the thing more complicated than needed.
Here is the way you can use StringBuilder to do that single character swap:
public static String swapChar(String string, char c1, char c2) {
StringBuilder sb = new StringBuilder(string);
for (int i = 0; i < sb.length(); ++i) {
if (sb.charAt(i) == c1) {
sb.setCharAt(i, c2);
} else if (sb.charAt(i) == c2) {
sb.setCharAt(i, c1);
}
}
return sb.toString();
}
Update :
Just found that what you are looking for is actually doing a bunch of replace of character at the same time. That can be cleanly done by providing a Map as parameter:
public static String replaceChars(String string, Map<Character,Character> cmap) {
StringBuilder sb = new StringBuilder(string);
for (int i = 0; i < sb.length(); ++i) {
if (cmap.containsKey(sb.charAt(i)) {
sb.setCharAt(i, cmap.get(sb.charAt(i));
}
}
return sb.toString();
}
to use it:
// or make a util method to make these even easier to create
Map<Character,Character> cmap = new HashMap<Character,Character>();
cmap.put('r','q');
cmap.put('q','r');
cmap.put('a','b');
cmap.put('e','f');
cmap.put('i','j');
cmap.put('o','p');
cmap.put('u','v');
and simply do a replace:
String result = replaceChars(inputString, cmap);
or even simpler, by making use of Apache Commons Lang:
String result = StringUtils.replaceChars(inputString, "rqaeiou", "qrbfjpv");
You can try this.
private static final char Q_STR = 'q';
private static final char R_STR = 'r';
public static String replaceString(String original, int position, char strToReplace) {
StringBuilder strBuilder = new StringBuilder(original);
if (strToReplace == Q_STR) {
strBuilder.setCharAt(position, R_STR);
} else if (strToReplace == R_STR){
strBuilder.setCharAt(position, Q_STR);
}
return strBuilder.toString();
}
public static void main(String[] args) {
String firstname = "Quart";
String lastname = " QuartLastName";
String fullname = firstname + lastname;
String lowername = fullname.toLowerCase();
//get all chars in String
char[] array = lowername.toCharArray();
//list to keep original position of Q char
List<Integer> allQPosition = new ArrayList<Integer>();
//list to keep original position of R char
List<Integer> allRPosition = new ArrayList<Integer>();
for (int i = 0; i < array.length; i++) {
if(array[i] == 'q') {
allQPosition.add(i);
} else if(array[i] == 'r') {
allRPosition.add(i);
}
}
//replace q
for (Integer integer : allQPosition) {
lowername = replaceString(lowername, integer, Q_STR);
}
//replace r
for (Integer integer : allRPosition) {
lowername = replaceString(lowername, integer, R_STR);
}
//replace others
String encryptedname = lowername.replace("a", "b")
.replace("e", "f")
.replace("i", "j")
.replace("o", "p")
.replace("u", "v");
System.out.println("Result: " + encryptedname);
}
My solution is:
Keep all position of 'q' and 'r' from original String.
Replace each of them
Replace the rest of other chars
Hope this help
public static void main(String[] args) {
String origin = "r and q";
System.out.println(newReplacement(origin, 'r', 'q'));
}
private static String newReplacement(String origin, char firstChar, char secondChar) {
StringBuffer stringBuffer = new StringBuffer(origin);
for(int i = 0; i < origin.length(); i++) {
if(origin.charAt(i) == firstChar) {
stringBuffer.replace(i, i+1, secondChar + "");
continue;
}
if(origin.charAt(i) == secondChar) {
stringBuffer.replace(i, i+1, firstChar + "");
}
}
return stringBuffer.toString();
}
Rewrite replace method with simple one.

Java Case Converter, most of the program is done, having trouble with case options?

My program worked fine before I tried implementing the conversion options. All I am trying to do is implement a U/u or L/l input option for either convert the string to Uppercase or Lowercase. Help please?
import java.util.Scanner;
public class CaseManipulation {
public static void main(String[] args) {
boolean up, low;
char up[] = {'U', 'u'};
char low[] = {'L', 'l'};
Scanner scanner = new Scanner(System.in);
System.out.print("Enter an input String: ");
String inputString = scanner.nextLine();
System.out.print("Case Conversion Option(U/u for uppercase, L/l for lowercase):");
char caseoption = scanner.nextLine();
if (caseoption == up[]) {
System.out.println("Upper Case: " + toUpperCase(inputString));
} else if (caseoption == low[]) {
System.out.println("Lower Case: " + toLowerCase(inputString));
}
//is_uppercase();
//System.out.println("Upper Case: " + toUpperCase(inputString));
//System.out.println("Lower Case: " + toLowerCase(inputString));
}
//public static boolean is_uppercase(char caseoption) {
// if (char caseoption == ) {
// }
//}
public static String toUpperCase(String inputString) {
String result = "";
for (int i = 0; i < inputString.length(); i++) {
char currentChar = inputString.charAt(i);
char currentCharToUpperCase = Character.toUpperCase(currentChar);
result = result + currentCharToUpperCase;
}
return result;
}
public static String toLowerCase(String inputString) {
String result = "";
for (int i = 0; i < inputString.length(); i++) {
char currentChar = inputString.charAt(i);
char currentCharToLowerCase = Character.toLowerCase(currentChar);
result = result + currentCharToLowerCase;
}
return result;
}
}
Basically, your if condition is comparing the object/memory references of the two objects, not their values...
if (caseoption == up[]) {...
caseoption is never likely to be equal to up...
Instead, you should be comparing their contents...
if (caseoption == up[0] || caseoption == up[1]) {...
A simpler solution might be to convert the caseoption into a single use case, for example...
if (Character.toUpperCase(caseoption) == 'U') {...

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