String formatter function in java - java

I m writing a function to format a string input. The function is to make the text output left indented, with a limit to the number of characters in a line.
if there are excess whitespaces,' ', between words; i skip the excess whitespace and only put one whitespace' '. if the word is too long and will go over the character per line limit, i insert whitespaces until the limit and start a new line with that word in the newline.
i am unable to create the padding section of the code. which is the part which checks whether the word will go over the limit and to start a newline with the word in the newline.
as part of the assignment requirements, i am only allowed to use charAt() and length methods on a String
void runApp(){
String text = " Knowing You Jesus " +
" Graham Kendrick " +
"All I once held dear, built my life upon " +
"All this world reveres, and wars to own " +
"All I once thought gain I have counted loss " +
"Spent and worthless now, compared to this " +
"Knowing you, Jesus " +
"Knowing you, there is no greater thing " +
"You're my all, you're the best " +
"You're my joy, my righteousness " +
"And I love you, Lord " +
"Now my heart's desire is to know you more " +
"To be found in you and known as yours " +
"To possess by faith what I could not earn " +
"All-surpassing gift of righteousness " +
"Oh, to know the power of your risen life " +
"And to know You in Your sufferings " +
"To become like you in your death, my Lord " +
"So with you to live and never die " +
"Source: Musixmatch " +
"Songwriters: Tim Hughes / Ben Cantelon ";
//limit = 60
System.out.println(" `123456789012345678901234567890123456789012345678901234567890");`
System.out.println(leftTextFormat(text, 60));
System.out.println();
}
// This prints out everything left indented, but does not pad.
String leftTextFormat(String text, int limit){
String formattedText = "";
int charCount = 0;
formattedText = formattedText+"[";
for (int i=0; i<text.length(); i++){
if (charCount%limit ==0){
if (text.charAt(i) == ' '){
continue;
}else if (text.charAt(i) != ' ' ){
formattedText = formattedText+text.charAt(i);
charCount++;
}
}else if (charCount%limit != 0){
if (text.charAt(i) == ' '){
if (text.charAt(i-1) != ' '){
formattedText = formattedText+text.charAt(i);
charCount++;
}else{
continue;
}
}else if (text.charAt(i) != ' '){
formattedText = formattedText+text.charAt(i);
charCount++;
}
}
if (charCount%limit ==0 && charCount!=0){
formattedText = formattedText+"]\n[";
}
}
return formattedText;
}
The expected output is this:
https://drive.google.com/file/d/1uYXtSBo37sFnpwJeBGtjF0MFYNngtZXv/view?usp=sharing
what i managed to do is this:
https://drive.google.com/file/d/102zNMe4JhaO2IUoOPCS5GSZ02Pq9aXwX/view?usp=sharing
123456789012345678901234567890123456789012345678901234567890
[Knowing You Jesus Graham Kendrick All I once held dear, buil]
[t my life upon All this world reveres, and wars to own All I]
[once thought gain I have counted loss Spent and worthless no]
[w, compared to this Knowing you, Jesus Knowing you, there is]
[no greater thing You're my all, you're the best You're my jo]
[y, my righteousness And I love you, Lord Now my heart's desi]
[re is to know you more To be found in you and known as yours]
[To possess by faith what I could not earn All-surpassing gif]
[t of righteousness Oh, to know the power of your risen life ]
[And to know You in Your sufferings To become like you in you]
[r death, my Lord So with you to live and never die Source: M]
[usixmatch Songwriters: Tim Hughes / Ben Cantelon

Ok attempt, but your problem is that you only adding characters and never actually establishing if those characters make up words and if those words, which you are adding, are going to go over your "limit". Hence you have no idea when a word will actually cause you to go over your imposed limit and subsequently you are make no attempt to pad your line when you are potentially going to go over that limit.
Essentially you need to work word for word and line by line. Each time you've established a word, check that the length of that word plus the length of your current line is not greater than your limit. If it's greater don't concatenate it to your current line, rather pad the line to your limit and start a new line.
public String formattedLine(String singleLine, int limit) {
int padding = limit - singleLine.length();
String pad ="";
for(int j = 0; j < padding; j ++) {
pad += " ";
}
return "[" + singleLine + pad + "]\n";
}
public String leftTextFormat(String text, int limit) {
String word = "";
String singleLine = "";
String formattedText = "";
for(int i=0; i<text.length(); i++) {
if (text.charAt(i) != ' ') {
word = word + text.charAt(i);
} else {
if(word.length() > 0) {
if(singleLine.length() + word.length() >= limit) {
formattedText = formattedText + formattedLine(singleLine, limit);
singleLine = "";
}
if(singleLine.length() == 0) {
singleLine = word;
} else {
singleLine = singleLine + " " + word;
}
word = "";
}
}
}
formattedText = formattedText + formattedLine(singleLine, limit);
return formattedText;
}

Related

Merge lines that share a word-link

so I'm having a small problem in java. I have something like
"Victor Fleming"
"Gone With"
"With The"
"The Wind."
So what the sentence should actually look like is
"Victor Fleming"
"Gone with the wind."
Therefore I'm looking to form a single sentence, by words that are adjacent and the same. If no adjacent same word is detected then the sentence will be separated as in "Victor Fleming" case where Fleming is not the same with Gone, so a new sentence is starting. What I've written so far:
List<String> separatedText = new ArrayList<>();
int i = 0;
while (i < mergedTextByHeightColor.size()) {
if ((i < (mergedTextByHeightColor.size() - 3)) && !(mergedTextByHeightColor.get(i + 1).equals(mergedTextByHeightColor.get(i + 2)))) {
separatedText.add(mergedTextByHeightColor.get(i) + " " + mergedTextByHeightColor.get(i + 1));
i = i + 2;
}
String concatStr = "";
while ((i < (mergedTextByHeightColor.size() - 3)) && (mergedTextByHeightColor.get(i + 1).equals(mergedTextByHeightColor.get(i + 2)))) {
if (concatStr.contains(mergedTextByHeightColor.get(i))) {
concatStr = mergedTextByHeightColor.get(i + 1) + " " + mergedTextByHeightColor.get(i + 3);
} else {
concatStr = mergedTextByHeightColor.get(i) + " " + mergedTextByHeightColor.get(i + 1) + " " + mergedTextByHeightColor.get(i + 3);
}
i = i + 3;
}
separatedText.add(concatStr);
}
We can store the sentences in a String array, then loop through each one.
Inside the loop, we check whether the last word of the last item (by splitting it into an array with .split(" "), then getting the last element) is equal to the first word of the current item. If it is, we first remove the first word of the current item, then append it to a StringBuilder.
If it isn't, then we append the StringBuilder's value to the list, append the current element, and move on.
String[] sentences = {"Victor Fleming", "Gone With", "With The", "The Wind."};
List<String> newsentences = new ArrayList<>();
StringBuilder str = new StringBuilder();
for(int i = 0; i < sentences.length; i++) {
String cur = sentences[i];
if(i != 0) {
String[] a = sentences[i-1].split(" ");
String[] b = cur.split(" ");
String last = a[a.length-1];
String first = b[0];
if(last.equalsIgnoreCase(first)) {
str.append(cur.substring(first.length()));
}else {
newsentences.add(str.toString());
str = new StringBuilder();
str.append(cur);
}
}else {
str.append(cur);
}
}
newsentences.add(str.toString());
System.out.println(Arrays.toString(newsentences.toArray()));
Output:
[Victor Fleming, Gone With The Wind.]

Fill in "secret word" letters

I am doing a hangman project.
I have got most of the code working.
The one part I can't get working is where the "secret word" has more than one letter which is the same. For example "hello" has 2 "l"'s.
This is the code for the part of the code where it replaces the "----" (hello) with the letter that was guessed if the guess was right:
int pos = $Input.indexOf($Guessed);
if (pos == -1)
{
System.out.print("Search string '" + $Guessed + "' not found");
}
else
{
System.out.println("\nSearch string found at " + (pos + 1));
pos = $Input.indexOf($Guessed);
String before = $Display.substring(0, pos);
String after = $Display.substring(pos + $Guessed.length());
System.out.println(before + $Guessed + after);
$Display = before + $Guessed + after;
System.out.println($Display);
$GuessAmt++;
}
I have looked at various answers on here but I cannot get one to work so far.
Obviously if someone guessed "l" then "-----" would change to "--ll-" for (hello).
I am not looking for someone to code this for me as I enjoy a challenge but a bit of a hint would be lovely!!
Obviously from looking at my code you may be able to guess we are not allowed to use arrays yet unfortunately. This is only an intro to Java class really.
Any help would be appreciated.
EDIT: Just to be clear, at the moment it ONLY does the first "l" not both the "l"'s of (hello).
EDIT: Changed to this. However, now it is repeating the "inside if" print statement over and over. Cant see how to fix this!
int pos = $Input.indexOf($Guessed);
if (pos == -1)
{
System.out.print("Search string '" + $Guessed + "' not found");
}
else
{
//System.out.println("\nSearch string found at " + (pos + 1));
for(int i=0;i<$StrLength;i++)
{
System.out.println(i);
if($Input.charAt(i) == $Guessed.charAt(0))
{
i = $Input.indexOf($Guessed);
String before = $Display.substring(0, i);
String after = $Display.substring(i + 1);
System.out.println("inside if" + before + $Guessed + after);
$Display = before + $Guessed + after;
}
}
System.out.println($Display);
$GuessAmt++;
}
If you still wanna use the indexOf you can use its overloaded version as well to insure that you have gone through all letter occurrences:
int index = str.indexOf('l');
while(index >= 0) {
// FILL THE BLANKS WITH THE LETTER
index = str.indexOf('l', index +1);
}
You can iterate over the String and check every character individually using word.charAt(i).
for (int i = 0; i < word.length; i++) {
if (word.charAt(i) == guessedChar) {
// do stuff
}
}

Searching a string arrays with an array

I am attempting to search a user input array of text with another user input array of search terms using nested loops and then output the search terms with the number of times they appear in the text along with the percentage of total text. I think I am on the right track and my issue is that the counter is not resetting each time the if statement is true. I am very new to programming -- so I could be completely wrong. Below is the entire program. If anyone could take a look and give me a hand at figuring out what my issue is I would be eternally grateful.
public class termFrequency {
public static void main(String[] args) {
String searchTextPeriod, searchTextComma, searchTextApostrophe, searchTextColon, searchTextExclamation,
searchTextQuestion, searchText, searchTerm;
int counter=0, total, searchIndex=0, termIndex=0;
double percentage=0.0;
String [] searchArray, termArray;
searchText = JOptionPane.showInputDialog("Enter a sentence that is at least 20 words long");
//removes some common punctuation from the searchable text
searchTextPeriod = searchText.replace(".", "");
searchTextComma = searchTextPeriod.replace(",", "");
searchTextApostrophe = searchTextComma.replace("'", " ");
searchTextColon = searchTextApostrophe.replace(":", " ");
searchTextExclamation = searchTextColon.replace("!", "");
searchTextQuestion = searchTextExclamation.replace("?", "");
searchArray = searchTextQuestion.split(" "); //splits the sentence and and puts it into an array
total=searchArray.length;
System.out.println("There are " +total +" words in your sentence");
searchTerm = JOptionPane.showInputDialog("Enter your search terms here seperated by a space");
termArray = searchTerm.split(" ");
DecimalFormat two = new DecimalFormat("#0.00");
boolean found = false;
for (termIndex=0; termIndex<termArray.length; termIndex++)
{
for (searchIndex=0; searchIndex<searchArray.length; searchIndex++)
if (termArray[termIndex].equalsIgnoreCase(searchArray[searchIndex]))
{
counter++;
found = true;
percentage= ((double) counter/(double)total) * 100;
}
if (found)
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is found " +counter +" times. That is "+ two.format(percentage)+"% of the statement." );
else
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is not found in the statement.");
}
}
}
}
You have to move the if/else on "found" from the inner loop to the end of the first loop.
You also need to reset the boolean and the counter in the first loop, like that you start the analysis of each new word in termArray with initial values.
for (termIndex=0; termIndex<termArray.length; termIndex++)
{
counter=0; //Reset the counter for each word in termArray
found=false; //Reset the "found" flag for each word in termArray
for (searchIndex=0; searchIndex<searchArray.length; searchIndex++)
if (termArray[termIndex].equalsIgnoreCase(searchArray[searchIndex]))
{
counter++;
percentage= ((double) counter/(double)total) * 100;
found=true
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is found " +counter +" times. That is "+ two.format(percentage)+"% of the statement." );
}
}
if (found)
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is found " +counter +" times. That is "+ two.format(percentage)+"% of the statement." );
else
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is not found in the statement.");
}
By the way you don't really need the "found" var, now if counter == 0 you know that the word has not been found in searchArray.
Move found = false inside of the first loop. that way it will be reset to false with each iteration. Right now if it is ever changed to true it stays true for the rest of the process.

Trying to instantiate objects within for loop and failing

Basically I am trying to create a new class as long as the continue variable equals "Y". The problem I am having is
DigitalMain.java:18: not a statement
DigitalPhoto[] class = new DigitalPhoto[9];
upon compile. I have looked at ArrayLists but I am not quite sure if they would instantiate classes the same way as what I am trying to achieve. In an ideal situation I would have objects with the name "class"+i, and different values for every object via their built in set methods.
// Import classes for class
import java.util.Arrays;
import java.util.List;
import javax.swing.*;
import java.awt.event.*;
import java.text.DecimalFormat;
public class DigitalMain
{
public static void main(String args[])
{
String cont = "Y";
String heightString,widthString,width,bitpsString;
double bitps,x,y,totesPrice,totesSize,totesSpeed;
DecimalFormat wholeDigits = new DecimalFormat("0");
DecimalFormat dec = new DecimalFormat("0.00");
DigitalPhoto[] picc = new DigitalPhoto[20];
for(int i=0; cont.equals("Y") ; i++)
{
picc[i] = new DigitalPhoto();
heightString = JOptionPane.showInputDialog("Please enter height");
picc[i].setHeight = Double.parseDouble(heightString);
heightString = JOptionPane.showInputDialog("Please enter width");
picc[i].setWidth = Double.parseDouble(widthString);
continueQuestion = JOptionPane.showInputDialog("Height: " + picc[i].getHeight + "\n Width: " + picc[i].getWidth + "\n Resolution: " + picc[i].getResolution + "\n Compression Ratio: " + picc[i].getCompression + "\n Required Storage: " + picc[i].calcStorage() + "\n Price of Scanned Photo: " + picc[i].getCost() + "Please enter 'Y' to try again or anything but 'Y' to accept values.");
};
do
{
bitpsString = JOptionPane.showInputDialog("Please enter your internet connection speed. Must be an integer between 1 and 99999999");
bitps = Double.parseDouble(bitpsString);
} while (bitps > 0 && bitps < 99999999);
picc0.setSpeed(bitps);
for(y = 0; y<picc.length; y++) {
totesPrice += picc+y.getCost();
totesSize += picc+y.calcStorage();
totesSpeed = picc0.getSpeed();
}
double seconds = transferTime(totesSize, totesSpeed);
double minutes = seconds / 60;
double realsec = seconds % 60;
JOptionPane.showMessageDialog(null, "You will be paying: " + totesPrice + "\nRequired Storage is: " + totesSize + "Required time for transfer is: " + wholeDigits.format(minutes) + " minutes, and " + wholeDigits.format(realsec) + " seconds.");
}
public static double transferTime(double totalStorage, double netSpeed) {
double bits, seconds;
bits = (totalStorage * 8);
seconds = (bits / netSpeed);
return seconds;
};
}
class is a keyword - you can't use it as a variable name.
Additionally, you have an odd construct here:
for(int i=0; cont.equals("Y") ; i++)
{
...
} while {continue.equalsIgnoreCase(Y)};
There's no such thing as a "for/while" loop - there's a normal for loop, a while loop, and a do/while loop.
So you've actually got a for loop followed by an invalid while loop here. It has no condition.
You need to work out which you want. (Possibly a for loop containing a do/while loop, although I'd extract the inner loop into a separate method. In general your code would greatly benefit from being broken out into multiple methods.
You do something similar later, although this time with do/while:
do
{
...
} while {bitps > 0 && bitps < 99999999};
The condition of a while loop goes in round brackets, not braces:
do
{
...
} while (bitps > 0 && bitps < 99999999);
Basically, you should read up on the syntax options available for loops.
The issue is most likely the name of your array. The word class is a keyword in the Java language and hence cannot be used to name variables. You can also use ArrayLists like so:
List<DigitalPhoto> photoes = new ArrayList<DigitalPhoto>();
do
{
DigitalPhoto photo = new DigitalPhoto();
heightString = JOptionPane.showInputDialog('Please enter height');
photo .setHeight = double.parseDouble(heightString);
heightString = JOptionPane.showInputDialog('Please enter width');
photo .setWidth = double.parseDouble(widthtString);
photos.add(photo)
continueQuestion = JOptionPane.showInputDialog('Height: ' + class[i].getHeight + '\n\lWidth: ' + class[i].getWidth + '\n\l Resolution: ' + class[i].getResolution + '\n\lCompression Ratio: ' + class[i].getCompression + '\n\lRequired Storage: ' + class[i].calcStorage() + '\n\lPrice of Scanned Photo: ' + class[i].getCost() + 'Please enter "Y" to try again or anything but "Y" to accept values.')
} while {cont.equals("Y")};
What kind of loop you are using.
for(...)
{
...
}while();
There is no for-while loop.
And also your for loop condition never going to become false. Set a proper condition to your for loop.
Also there is syntax error in your for-while loop. ie. last statement
continueQuestion = JOptionPane.showInputDialog('Height: ' + class[i].getHeight + '\n\lWidth: ' + class[i].getWidth + '\n\l Resolution: ' + class[i].getResolution + '\n\lCompression Ratio: ' + class[i].getCompression + '\n\lRequired Storage: ' + class[i].calcStorage() + '\n\lPrice of Scanned Photo: ' + class[i].getCost() + 'Please enter "Y" to try again or anything but "Y" to accept values.') // you miss the ;
there is some rules for naming of variables Variables
You cannot use any of the following(in list of keywords) as identifiers in your
programs.The keywords const and goto are reserved, even though they are not
currently used. true, false, and null might seem like keywords, but they
are actually literals; you cannot use them as identifiers in your programs.
List of keywords
for(int i=0; cont.equals("Y") ; i++)
{
class[i] = new DigitalPhoto();
heightString = JOptionPane.showInputDialog('Please enter height');
class[i].setHeight = double.parseDouble(heightString);
heightString = JOptionPane.showInputDialog('Please enter width');
class[i].setWidth = double.parseDouble(widthtString);
continueQuestion = JOptionPane.showInputDialog('Height: ' +
class[i].getHeight + '\n\lWidth: ' + class[i].getWidth + '\n\l Resolution: ' +
class[i].getResolution + '\n\lCompression Ratio: ' + class[i].getCompression +
'\n\lRequired Storage: ' + class[i].calcStorage() + '\n\lPrice of Scanned Photo: ' +
class[i].getCost() + 'Please enter "Y" to
try again or anything but "Y" to accept values.')
} while {continue.equalsIgnoreCase(Y)};
here i dont know any for-while loop..just check some basics..
Loops in java

removing comma from string array

I want to execute a query like
select ID from "xyz_DB"."test" where user in ('a','b')
so the corresponding code is like
String s="(";
for(String user:selUsers){
s+= " ' " + user + " ', ";
}
s+=")";
Select ID from test where userId in s;
The following code is forming the value of s as ('a','b',)
i want to remove the comma after the end of array how to do this ?
Here is one way to do this:
String s = "(";
boolean first = true;
for(String user : selUsers){
if (first) {
first = false;
} else {
s += ", ";
}
s += " ' " + user + " '";
}
s += ")";
But it is more efficient to use a StringBuilder to assemble a String if there is looping involved.
StringBuilder sb = new StringBuilder("(");
boolean first = true;
for(String user : selUsers){
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(" ' ").append(user).append(" '");
}
sb.append(")");
String s = sb.toString();
This does the trick.
String s = "";
for(String user : selUsers)
s += ", '" + user + "'";
if (selUsers.size() > 0)
s = s.substring(2);
s = "(" + s + ")";
But, a few pointers:
When concatenating strings like this, you are advised to work with StringBuilder and append.
If this is part of an SQL-query, you probably want to sanitize the user-names. See xkcd: Exploits of a Mom for an explanation.
For fun, a variation of Stephen C's answer:
StringBuilder sb = new StringBuilder("(");
boolean first = true;
for(String user : selUsers){
if (!first || (first = false))
sb.append(", ");
sb.append('\'').append(user).append('\'');
}
sb.append(')');
you could even do the loop it like this :-)
for(String user : selUsers)
sb.append(!first || (first=false) ? ", \'" : "\'").append(user).append('\'');
Use the 'old style' of loop where you have the index, then you add the comma on every username except the last:
String[] selUsers = {"a", "b", "c"};
String s="(";
for(int i = 0; i < selUsers.length; i++){
s+= " ' " + selUsers[i] + " ' ";
if(i < selUsers.length -1){
s +=" , ";
}
}
s+=")";
But as others already mentioned, use StringBuffer when concatenating strings:
String[] selUsers = {"a", "b", "c"};
StringBuffer s = new StringBuffer("(");
for(int i = 0; i < selUsers.length; i++){
s.append(" ' " + selUsers[i] + " ' ");
if(i < selUsers.length -1){
s.append(" , ");
}
}
s.append(")");
Use StringUtils.join from apache commons.
Prior to adding the trailing ')' I'd strip off the last character of the string if it's a comma, or perhaps just replace the trailing comma with a right parenthesis - in pseudo-code, something like
if s.last == ',' then
s = s.left(s.length() - 1);
end if;
s = s + ')';
or
if s.last == ',' then
s.last = ')';
else
s = s + ')';
end if;
Share and enjoy.
i would do s+= " ,'" + user + "'"; (place the comma before the value) and add a counter to the loop where i just do s = "'" + user + "'"; if the counter is 1 (or 0, depending on where you start to count).
(N.B. - I'm not a Java guy, so the syntax may be wrong here - apologies if it is).
If selUsers is an array, why not do:
selUsers.join(',');
This should do what you want.
EDIT:
Looks like I was wrong - I figured Java had this functionality built-in. Looks like the Apache project has something that does what I meant, though. Check out this SO answer: Java: function for arrays like PHP's join()?
I fully support Stephen C's answer - that's the one I wanted to suggest aswell: simply avoid adding the additional comma.
But in your special case, the following should work too:
s = s.replace(", \\)", ")");
It simply replaces the substring ", )" with a single bracket ")".
Java 1.4+
s = s.replaceFirst("\\, \\)$", ")");
Edited: I forgot last space before parethesis
StringBuilder has a perfectly good append(int) overload.
String [] array = {"1","2","3" ...};
StringBuilder builder = new StringBuilder();
builder.append(s + "( ")
for(String i : array)
{
if(builder.length() != 0)
builder.append(",");
builder.append(i);
}
builder.append(" )")
Answer shamelessly copied from here

Categories

Resources