StringBuilder and String Issues - java

Given the input...
Nathan E Long
Jay L Stevens
Edna J Jackson
Emma Watson
Alexa J Ness
Charles A Miller
I'm attempting to write code that reads it one line at a time, seperates the names into 3 tokens, and then rearrange those tokens to read...
Long, Nathan E
Stevens, Jay L
Jackson, Edna J
Ness, Alexa J
Miller, Charles A
Also if I get less than 3 tokens, I throw that name out completely such as Emma Watson. Code...
public class Hmwk {
public static void main(String[] args)throws FileNotFoundException {
Scanner names = new Scanner(new File("input.txt"));
int counter = 0;
while (names.hasNextLine())
{
String nameIn = names.next();
String delims = ("\t");
String[] tokens = nameIn.split(delims);
if (tokens.length != 3)
{
continue; //returns to while loop and gets next line
}
String first = tokens[0];
String middle = tokens[1];
String last = tokens[2];
StringBuilder finalName = builder(first,middle,last);
System.out.println(finalName);
}
}
public static StringBuilder builder(String f, String m, String l)
{
StringBuilder theBuilder = new StringBuilder();
theBuilder.append(l);
theBuilder.append(',');
theBuilder.append(' ');
theBuilder.append(f);
theBuilder.append(' ');
theBuilder.append(m);
return theBuilder;
}
}
All names in the file are separated by tabs. My code runs, but it doesn't print out... anything which has me completely confused. Where am I going wrong here?

First, Scanner#next() only returns the next token. With a default configuration, tokens are separated by whitespace characters. So the first call to
String nameIn = names.next();
would return
Nathan
which, when split, only returns an array with length 1.
Use Scanner#nextLine() to retrieve all input until a new line character is found.
Second, it doesn't seem like your tokens are separated by tab characters, \t. Use
String delims = ("\\s+");
to split by one or more whitespace characters.

Related

How do I change only letters in a string, leaving spaces, hyphens and apostrophes?

In my program, a random line (called ThingToGuess) is selected from a text file and is changed so that every letter after the third is replaced with an asterisk (this string of asterisks is called NumberOfBlanks), and the user has to guess what the original string was using the first three letters.
However, the spaces, apostrophes and hyphens must be left in the new string. For example, the string, Man in the mirror would be changed to Man ** *** ******
What I have only outputs Man *************.
String NumberOfBlanks = "";
for(int i=1; i<ThingToGuess.length(); i++){
NumberOfBlanks = NumberOfBlanks +"*";
}
String OutputCharacters = ThingToGuess.substring(0,3)+ NumberOfBlanks;
OutputCharacters = OutputCharacters.substring(0,secondIndex)+' '+OutputCharacters.substring(secondIndex+1);
System.out.println(OutputCharacters);
How do I change ThingToGuess to a string wherein only the letters are replaced with asterisks?
This should solve your problem.
String input = "Man in the mirror";
String output = input.substring(0,3) + input.substring(3,input.length()).replaceAll("[^ -\']","*");
System.out.println(output); // Prints "Man ** *** ******"
We are doing two things, taking first three characters as it is and for remaining characters, we are replacing all characters except SPACE, HYPHEN and APOSTROPHE with ASTERISK
Firstly, when you're iterating and appending to a string, its better to use a StringBuilder. As using the + operator in the loop increases the runtime of the program. More info here
Answering to your question:
String s = "Man in the mirror";
char[] charArr = s.toCharArray();
for(int i=0; i<charArr.length;i++)
{
if((charArr[i]!=' ' || charArr[i]!='\'' || charArr[i]!='-') && i>2){
charArr[i]='*';
}
}
s= new String(charArr);
System.out.println(s);
This method tackles the problem directly. It can also be solved by Regex as Hemang illustrated
You should probably use this method to check if a char is a letter or a number and convert the char to "*" only if they are.
Character.isDigit(yourchar) || Character.isLetter(yourchar)
If you are using Java 8 or 8+
public static String maskLettersAndDigits(String input) {
char[] chars = input.toCharArray();
return IntStream.range(0, chars.length).mapToObj(i -> i > 2 && Character.isLetterOrDigit(chars[i]) ? "*" : String.valueOf(chars[i])).collect(Collectors.joining());
}
Solution using regex:
public class Main {
public static void main(String[] args) {
String thingToGuess = "Man in the mirror";
String result = thingToGuess.substring(0, 3) + thingToGuess.substring(3).replaceAll("[^\\s'-]", "*");
System.out.println(result);
}
}
Output:
Man ** *** ******
The ^ inside the [] of the regex pattern specifies *None of the characters from this list of characters`.
Non-regex solution:
public class Main {
public static void main(String[] args) {
String thingToGuess = "Man in the mirror";
StringBuilder output = new StringBuilder();
output.append(thingToGuess.substring(0, 3));
for (int i = 3; i < thingToGuess.length(); i++) {
char ch = thingToGuess.charAt(i);
if (Character.isLetterOrDigit(ch)) {
output.append('*');
} else {
output.append(ch);
}
}
System.out.println(output);
}
}

Replace words in parenthesis

I have a question about replacing words. I have some strings, each of which looks like this:
String string = "today is a (happy) day, I would like to (explore) more about Java."
I need to replace the words that have parentheses. I want to replace "(happy)" with "good", and "(explore)" with "learn".
I have some ideas, but I don't know how.
for (int i = 0; i <= string.length(), i++) {
for (int j = 0; j <= string.length(), j++
if ((string.charAt(i)== '(') && (string.charAt(j) == ')')) {
String w1 = line.substring(i+1,j);
string.replace(w1, w2)
}
}
}
My problem is that I can only replace one word with one new word...
I am thinking of using a scanner to prompt me to give a new word and then replace it, how can I do this?
The appendReplacement and appendTail methods of Matcher are designed for this purpose. You can use a regex to scan for your pattern--a pair of parentheses with a word in the middle--then do whatever you need to do to determine the string to replace it with. See the javadoc.
An example, based on the example in the javadoc. I'm assuming you have two methods, replacement(word) that tells what you want to replace the word with (so that replacement("happy") will equal "good" in your example), and hasReplacement(word) that tells whether the word has a replacement or not.
Pattern p = Pattern.compile("\\((.*?)\\)");
Matcher m = p.matcher(source);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String word = m.group(1);
String newWord = hasReplacement(word) ? replacement(word) : m.group(0);
m.appendReplacement(sb, newWord); // appends the replacement, plus any not-yet-used text that comes before the match
}
m.appendTail(sb); // appends any text left over after the last match
String result = sb.toString();
Use below code for replacing the string.
String string = "today is a (happy) day, I would like to (explore) more about Java.";
string = string.replaceAll("\\(happy\\)", "good");
string = string.replaceAll("\\(explore\\)", "learn");
System.out.println(string);`
What you can do is run a loop from 0 to length-1 and if loop encounters a ( then assign its index to a temp1 variable. Now go on further as long as you encounter ).Assign its index to temp2 .Now you can replace that substring using string.replace(string.substring(temp1+1,temp2),"Your desired string")).
No need to use the nested loops. Better use one loop and store the index when you find opening parenthesis and also for close parenthesis and replace it with the word. Continue the same loop and store next index. As you are replacing the words in same string it changes the length of string you need to maintain copy of string and perform loop and replace on different,
Do not use nested for loop. Search for occurrences of ( and ). Get the substring between these two characters and then replace it with the user entered value. Do it till there are not more ( and ) combinations left.
import java.util.Scanner;
public class ReplaceWords {
public static String replaceWords(String s){
while(s.contains(""+"(") && s.contains(""+")")){
Scanner keyboard = new Scanner(System.in);
String toBeReplaced = s.substring(s.indexOf("("), s.indexOf(")")+1);
System.out.println("Enter the word with which you want to replace "+toBeReplaced+" : ");
String replaceWith = keyboard.nextLine();
s = s.replace(toBeReplaced, replaceWith);
}
return s;
}
public static void main(String[] args) {
String myString ="today is a (happy) day, I would like to (explore) more about Java.";
myString = replaceWords(myString);
System.out.println(myString);
}
}
This snippet works for me, just load the HashMap up with replacements and iterate through:
import java.util.*;
public class Test
{
public static void main(String[] args) {
String string = "today is a (happy) day, I would like to (explore) more about Java.";
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("\\(happy\\)", "good");
hm.put("\\(explore\\)", "learn");
for (Map.Entry<String, String> entry : hm.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
string = string.replaceAll(key, value);
}
System.out.println(string);
}
}
Remember, replaceAll takes a regex, so you want it to display "\(word\)", which means the slashes themselves must be escaped.

Convert String into Title Case

I am a beginner in Java trying to write a program to convert strings into title case. For example, if String s = "my name is milind", then the output should be "My Name Is Milind".
import java.util.*;
class TitleCase
{
public static void main(String args[])
{
Scanner in = new Scanner(System.in);
System.out.println("ent");
String s=in.nextLine();
String str ="";
char a ;
for(int i =0;i<s.length()-1;i++)
{
a = s.charAt(i);
if(a==' ')
{
str = str+(Character.toUpperCase(s.charAt(i+1)));
}
else
{
str =str+(Character.toLowerCase(a));
}
}
//for(int i =0; i<s.length();i++)
//{
System.out.println(str);
//}
}
}
You are trying to capitalize every word of the input.
So you have to do following steps:
get the words separated
capitalize each word
put it all together
print it out
Example Code:
public static void main(String args[]){
Scanner in = new Scanner(System.in);
System.out.println("ent");
String s=in.nextLine();
//now your input string is storred inside s.
//next we have to separate the words.
//here i am using the split method (split on each space);
String[] words = s.split(" ");
//next step is to do the capitalizing for each word
//so use a loop to itarate through the array
for(int i = 0; i< words.length; i++){
//we will save the capitalized word in the same place again
//first, geht the character on first position
//(words[i].charAt(0))
//next, convert it to upercase (Character.toUppercase())
//then add the rest of the word (words[i].substring(1))
//and store the output back in the array (words[i] = ...)
words[i] = Character.toUpperCase(words[i].charAt(0)) +
[i].substring(1);
}
//now we have to make a string out of the array, for that we have to
// seprate the words with a space again
//you can do this in the same loop, when you are capitalizing the
// words!
String out = "";
for(int i = 0; i<words.length; i++){
//append each word to out
//and append a space after each word
out += words[i] + " ";
}
//print the result
System.out.println(out);
}
Using Java 8 streams:
String titleCase = (new ArrayList<>(Arrays.asList(inputString.toLowerCase().split(" "))))
.stream()
.map(word -> Character.toTitleCase(word.charAt(0)) + word.substring(1))
.collect(Collectors.joining(" "));
The problem is with the way you're adding characters. Take a look at your if condition:
a = s.charAt(i);
if(a==' ')
{
// Here you are adding not the current character, but the NEXT character.
str = str+(Character.toUpperCase(s.charAt(i+1)));
}
else
{
// Here you are adding the current character.
str =str+(Character.toLowerCase(a));
}
As a result of this condition, you will skip a character if your input string contains a space, then repeat another character that you've already added.
Additionally, you're not looping through the whole string because your loop conditional goes to s.length()-1. Change that to just s.length(). However, if you do that, you may run into an exception if the input string ends with a space (since you'll try to check for a character at an out-of-bound index).
Here's what the fixed code would look like:
public static void main(String args[])
{
Scanner in = new Scanner(System.in);
System.out.println("ent");
String s=in.nextLine();
String str ="";
char a ;
for(int i =0;i<s.length();i++)
{
a = s.charAt(i);
if(a==' ')
{
str = str+Character.toLowerCase(a)+(Character.toUpperCase(s.charAt(i+1)));
i++; // "skip" the next element since it is now already processed
}
else
{
str =str+(Character.toLowerCase(a));
}
}
System.out.println(str);
}
NOTE: I only fixed the code that you supplied. However, I'm not sure it works the way you want it to - the first character of the string will still be whatever case it started in. Your conditional only uppercases letters that are preceded by a space.
You want to change the case of the first letter of each word of a String.
To do so, I would follow the following steps :
split the String in words : see String.split(separator)
retrieve the first letter of each word : see String.charAt(index)
retrieve its capitalized version : the Character.toUpperCase(char) you use is perfect
concatenate the capitalized letter with the rest of the word : concatenation operator (+) and String.substring
create a new String from the capitalized words : see String.join(separator)
Code Golf variation... I challenge anyone to make it any simpler than this:
public String titleCase(String str) {
return Arrays
.stream(str.split(" "))
.map(String::toLowerCase)
.map(StringUtils::capitalize)
.collect(Collectors.joining(" "));
}
By the way: Unicode distinguishes between three cases: lower case, upper case and title case. Although it does not matter for English, there are other languages where the title case of a character does not match the upper case version. So you should use
Character.toTitleCase(ch)
instead of Character.toUpperCase(ch) for the first letter.
There are three character cases in Unicode: upper, lower, and title. Uppercase and lowercase are familiar to most people. Titlecase distinguishes characters that are made up of multiple components and are written differently when used in titles, where the first letter in a word is traditionally capitalized. For example, in the string "ljepotica",[2] the first letter is the lowercase letter lj(\u01C9 , a letter in the Extended Latin character set that is used in writing Croatian digraphs). If the word appeared in a book title, and you wanted the first letter of each word to be in uppercase, the correct process would be to use toTitleCase on the first letter of each word, giving you "Ljepotica" (using Lj, which is \u01C8). If you incorrectly used toUpperCase, you would get the erroneous string "LJepotica" (using LJ, which is \u01C7).
[The Java™ Programming Language, Fourth Edition, by James Gosling, Ken Arnold, David Holmes (Prentice Hall). Copyright 2006 Sun Microsystems, Inc., 9780321349804]
WordUtils.capitalizeFully() worked for me like charm as it gives: WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
import java.util.Scanner;
public class TitleCase {
public static void main(String[] args) {
System.out.println("please enter the string");
Scanner sc1 = new Scanner(System.in);
String str = sc1.nextLine();
//whatever the format entered by user, converting it into lowercase
str = str.toLowerCase();
// converting string to char array for
//performing operation on individual elements
char ch[] = str.toCharArray();
System.out.println("===============");
System.out.println(str);
System.out.println("===============");
//First letter of senetence must be uppercase
System.out.print((char) (ch[0] - 32));
for (int i = 1; i < ch.length; i++) {
if (ch[i] == ' ') {
System.out.print(" " + (char) (ch[i + 1] - 32));
//considering next variable after space
i++;
continue;
}
System.out.print(ch[i]);
}
}
}
You can use lamda instead-
String titalName = Arrays.stream(names.split(" "))
.map(E -> String.valueOf(E.charAt(0))+E.substring(1))
.reduce(" ", String::concat);

How to find the last word in a String in Java?

How can I find the last word of a string? I am not trying to find a fixed word, in other words, I would not know what the last word is, however I want to retrieve it.
Here is my code:
myString = myString.trim();
String[] wordList = myString.split("\\s+");
System.out.println(wordList[wordList.length-1]);
Providing you consider words in a sentence to be delimited by whitespace and punctuation (particularly commas, spaces, new lines, brackets, and so on), which means punctuation can appear at the end of the sentence, and you want to include non-ASCII characters in the words, then the following will find you the last word in a string without the punctuation included:
static String lastWord(String sentence) {
Pattern p = Pattern.compile("([\\p{Alpha}]+)(?=\\p{Punct}*$)", Pattern.UNICODE_CHARACTER_CLASS);
Matcher m = p.matcher(sentence);
if (m.find()) {
return m.group();
}
return ""; // or null
}
The regular expression uses look-ahead to find zero-or-more punctuations at the end of the string and matches the alphabetical word before it.
If you want to also allow numbers in the word, change {Alpha} to {Alnum}.
Read the String API for various methods you might use.
For example you could:
Use the lastIndexOf(...) method to find where the start of the word is
Then use the substring(...) method to get the word
Use the StringTokenizer for this
StringTokenizer st = new StringTokenizer("this is a test");//Take any String
int count = st.countTokens();//it will count the number of token in that particular String
String[] myStringArray = new String[count];
for (int i = 0; i < count; i++) {
`myStringArray[i] = st.nextToken();`//insert the words/Tken in to the string array
}
`System.out.println("Last Word is--" + myStringArray[myStringArray.length - 1])`;//get the last words of the given String
System.out.println("enter the string");
Scanner input = new Scanner(System.in);
String instr = input.nextLine();
instr = instr.trim();
int index = instr.lastIndexOf(" ");
int l = instr.length();
System.out.println(l);
String lastStr = instr.substring(index+1,l);
System.out.println("last string .."+lastStr);

Remove repetitive string from sentence in java

I am working on java code in which I want to remove repetitive words. Following code works fine to remove them if I get space in any word for example:
1298 Anthony 1298 Anthony, it will make it like:
1298 Anthony
But for any other special character like:
1298 Anthony.ef 1298 Anthony.ef, it will show it like:
ef. 1298 Anthony.
My method is given below, I want to make it work for every special character, specially for : coma(,) , fullstop(.), dash(-), underscore(_). Please help me in this problem.
public static void removeString(){
String name1 = "1298 Anthony.ef 1298 Anthony.ef";
String[] strArr = name1.split(" ");
Set<String> set = new HashSet<String>(Arrays.asList(strArr));
String[] result = new String[set.size()];
set.toArray(result);
StringBuilder res = new StringBuilder();
for (int i = 0; i < result.length; i++) {
String string = result[i];
if(i==result.length-1){
res.append(string);
}
else{
res.append(string).append(" ");
}
}
System.out.println(res.toString());
String abc = res.toString();
}
You're splitting name1 around spaces. You can try to split name1 around any non-word character:
names.split("\\W+");
Method String.split accepts regex as argument. To quote from the docs:
Splits this string around matches of the given regular expression.
name1.split(" "); splits string around single space and returns array: [1298, Anthony.ef, 1298, Anthony.ef]
names.split("\\W+"); splits string around any non-word character (comma, dot, dash, etc.) and returns array: [1298, Anthony, ef, 1298, Anthony, ef]
As you can see in this case it was able to split Anthony.ef into separate strings.
UPDATE: If you want to preserve word's order in the original string you might want to use LinkedHashSet instead of HashSet. For example:
public static void removeString(){
String name1 = "1298 Anthony.ef 1298 Anthony.ef";
String[] strArr = name1.split("\\W+");
Set<String> set = new LinkedHashSet<String>(Arrays.asList(strArr));
String[] result = new String[set.size()];
set.toArray(result);
StringBuilder res = new StringBuilder();
for (int i = 0; i < result.length; i++) {
String string = result[i];
if(i==result.length-1){
res.append(string);
}
else{
res.append(string).append(" ");
}
}
System.out.println(res.toString());
String abc = res.toString();
}
Check out this question: Is there an insertion order preserving Set that also implements List?

Categories

Resources