Java: Accumulate output pattern in string variable? - java

There is probably a question that covers this, but I haven't found it in searching. The idea is to display a pattern given user input for the character and number of lines like this:
x
xx
xxx
xxxx
xxxx
xxx
xx
x
But I need to use JOptionPane to do this. Here is what I have:
import javax.swing.JOptionPane;
public class loopPattern {
public static void main(String[] args) {
String in, num, output1 = null, output2 = "";
int lines = 0;
int i, n = 1;
in = JOptionPane.showInputDialog("Please enter the character for the pattern:");
num = JOptionPane.showInputDialog("Please enter the number of lines in the pattern:");
lines = Integer.parseInt(num);
for (i=1; i<=lines; i++) {
for (n=1; n<=lines; n++) {
output1 = (n +"\n");
}
}
for (i=lines; i>=1; i--){
for (n=lines; n>=1; n--){
output2 = (n +"\n");
}
}
JOptionPane.showMessageDialog(null, output1 +output2);
}
}
I have to then make it repeat this pattern each time the user hits "Ok" and quit when they hit "Cancel". I think I can do that if I could just figure out the accumulating in a string variable thing. Thanks so much for the help.

Accumulating in a string variable is called a StringBuilder. It allows you to quickly append things into the StringBuilder from which you can call toString() to transform it back to a String.
StringBuilder sb = new StringBuilder();
for (i=1; i<=lines; i++) {
for (n=1; n<=lines; n++) {
sb.append(n +"\n");
}
}
if you can not use a StringBuilder, then use a String variable and assign it the value of itself with another string using the "+" operator. This can be shorthanded with "+="
String string = new String();
string = string + "stuff to go on the string";
// or as a shorthand equivalent
string += "stuff to go on the string";
/// loop example
String myoutput = new String();
for (i=1; i<=lines; i++) {
for (n=1; n<=lines; n++) {
myoutput += n +"\n";
}
}

As a high level approach, you could try this. Create two StringBuilder instances. Loop up until the desired lines is hit. For each iteration, append an X into the first StringBuilder and then append to entire contents of that StringBuilder into the other one (via toString) with a \n for the newline. After that loop finishes, append in 2 empty lines for the separators. Then, loop until the first StringBuilder is empty, removing the last char for each iteration (via deleteCharAt(sb.length()-1)) and appending the entire content into the other StringBuilder again via toString plus \n. When done, the second StringBuilder should have the patten you desire.
int lines = 4;
StringBuilder sb = new StringBuilder();
StringBuilder pattern = new StringBuilder();
for(int i = 0; i < lines; i++){
sb.append("X");
pattern.append(sb.toString() + "\n");
}
pattern.append("\n\n");
pattern.append(sb.toString() + "\n");
while(sb.length() > 0){
sb.deleteCharAt(sb.length() - 1);
pattern.append(sb.toString() + "\n");
}
System.out.println(pattern.toString());

If using a StringBuilder is too advanced you can get the same effect simply using a string:
String output1 = "";
for (i=1; i<=lines; i++) {
for (n=1; n<=lines; n++) {
output1 = output1.concat(n +"\n");
// note the below commented out code should also work:
//output1 = output1 + n + "\n";
}
}
This is much less efficient then using a StringBuilder though since a new string will be created and assigned to output1 for each iteration of the inner loop.

Your loop shuold look more like:
for (i=1; i<=lines; i++) {
for (n=0; n<i; n++) {
output1 += in;
}
output += "\n";
}
assuming you can't use StringBuilder (which, per other posts, is a better option).

Related

How do I get rid of the comma at the end? (Java)

I'm working on an assignment and the code is working perfectly, except for one small little problem.
For example at the end it's supposed to say, "t,e,s,t" but instead it prints out "t,e,s,t,".
import javax.swing.JOptionPane;
public class program {
public static int divide(String input) {
int length=0;
String output = "";
for (int i=0; i<input.length(); i++) {
length++;
output += input.charAt(i);
output += ",";
}
JOptionPane.showMessageDialog(null, "Eingabe: " +input+ "\nAnzahl der Zeichen: " +length+ "\nZeichen: \n" +output);
return length;
}
}
I'd just like to say for those who are planning on giving tips, please note that this is an assignment so I'm not really allowed to make any MAJOR changes to it. This program HAS to be:
Solved using a for loop
The output HAS to be in JOptionPane
It has to be in a method (for I'll have to write an inputDialog later in the main-method, but that's unimportant right now).
My only problem with it, for example the output would have to say (I'll translate the output in english, since I'm at an austrian school) if the string was "hello", the program would say "letters: h, e, l, l, o" but instead it says "h, e, l, l, o," with a comma at the end, how do I get rid of it?
(Also sorry if I messed up any variables, I renamed them all from German to English for this post so I hope I didn't mess any of them up)
One of the possibilities is to print comma not after each character, but before every character except the first one.
You only want to add a comma if there is more data to come after. So you can do it in two ways:
add the comma before the text if there's already something in the string:
String output = "";
for (int i=0; i<input.length(); i++) {
length++;
if (output.length() > 0) output += ",";
output += input.charAt(i);
}
add the comma after unless it's the last element:
String output = "";
for (int i=0; i<input.length(); i++) {
length++;
output += input.charAt(i);
if (i < input.length() - 1) output += ",";
}
Personally I like the first way.
Hello I used an if statement to check if we are at the first letter and if we are then we don't write a comma, here is the code:
{
int length = 0;
String output = "";
int i = 0;
for ( i = 0; i < input.length(); i++)
{
if(i == 0)
{
length++;
output += input.charAt(i);
}
else
{
output += ",";
output += input.charAt(i);
length++;
}
}
Console.WriteLine(output);
}
You only need to check whether you are at the last character, and if you are, then break out from the loop.
for (int i=0; i<input.length(); i++) {
length++; //you do not seem to need this
output += input.charAt(i);
if (i==(input.length()-1)) break; //checking whether we are at the last character
output += ",";
}
Two additional notes:
Please follow the Java Naming Conventions and use PascalCase for your class names, this is very important;
It would make your code much more efficient if you'd use StringBuilder instead of String, to concatenate characters and dynamically build your string. String is immutable and per each concatenation, you're actually creating a new instance of it, which is expensive.
I would use a StringJoiner
StringJoiner output = new StringJoiner(",");
for (int i = 0; i < input.length(); i++) {
length++;
output.add(input.substring(i, i + 1));
}
JOptionPane.showMessageDialog(… + output.toString());
so You are not allowed to use StringJoiner
String output = "";
String comma = "";
for (int i = 0; i < input.length(); i++) {
length++;
output += comma;
output += input.charAt(i);
comma = ",";
}
Your loop iterates through every character, appending both the character and a comma. This includes the final character. You need to find a way to avoid adding a comma after the final iteration;
Using String and appending characters one by one is very inefficient. This is what StringBuilder is designed for;
What is the purpose of the length variable? It can be replaced with input.length() - 1;
String.format() makes your code easier to read rather than chaining together string concatenations;
Don't be afraid to use a healthy amount of spacing throughout your code. It is much harder to read otherwise.
Something like this should work well:
public static int divide(String input) {
int length = input.length() - 1;
String output;
if (input.length() == 0) output = input;
else {
StringBuilder outputBuilder = new StringBuilder(input.charAt(0));
for (int i = 1; i < input.length(); i++) {
outputBuilder.append(',').append(input.charAt(i));
}
output = outputBuilder.toString();
}
JOptionPane.showMessageDialog(null, String.format("Eingabe: %s\nAnzahl der Zeichen: %d\nZeichen: \n%s", input, length, output);
return length;
}
Once you learn, use a StringJoiner or similar modern device. My favourite link is at the bottom. There will also be a time when you learn to use a StringBuilder or StringBuffer for assembling a string.
In the meantime, I still like what I learned in my first year of programming: when one iteration through a loop needs to be different, take it out of the loop. In my experience this often gives the clearest code. In your case:
String input = "Wort";
String output = "" + input.charAt(0);
for (int i = 1; i < input.length(); i++) {
output += ",";
output += input.charAt(i);
}
System.out.println("Zeichen: " + output);
Output:
Zeichen: W,o,r,t
In this case I have taken the first character outside the loop and add it to the output (without comma) already in the declaration of output. The loop starts from index 1 (not 0). Inside the loop I have to add the comma before adding the next char. In other cases one may put the last item outside the loop instead, the result will be the same.
Links
Answer by Lii to a similar question demonstrating all of String.join(), Collectors.joining() and StringJoiner.
StringBuilder vs String concatenation in toString() in Java

Copying numbers from an addition series into an array

I'm trying to copy only the numbers from an addition series say 45+45+45
The code works just fine until the moment it encounters the last 45 and all I get displayed are two 45's where I wanted all the three of them.I'd like suggestions for what I haven't done which would give me the exact output.Here's my code
InputStreamReader read = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(read);
String str = "", st;
System.out.println("Enter Number");
st = in.readLine();
int l = st.length();
int c = 0;
String arr[] = new String[20];
for(int i = 0; i < l; i++)
{
char chr = st.charAt(i);
if(chr == '+')
{
arr[c++] = str;
str = "";
}
else
{
str += chr;
}
}
for(int i = 0; i < c; i++)
{
System.out.println(arr[i]);
}
}
Take a look in your code. You are only adding the content into the array after you read an +. As the last '45' number has no remaining + left, it is not added into your array.
If this is not a homework, the best solutions is to use split() as suggested in the comments. In other case, I would recommend you to store the last content of the str when the loop is over. It contains the remaining characters left.
It is an easy code and I am sure that you can figure it out.

Java find difference between characters in StringBuffer

I'm working on an Anagram program and I'm currently working on a method called diff which should return a StringBuffer containing the chars that are in the first StringBuffer but not in the second one. So for example if the StringBuffers are abba and acca, then my diff method should return bb. So far I currently have loop with an if statement but it's not working. Any help would be appreciated. Thanks
public StringBuffer diff(){
StringBuffer diffVal = null;
for (int i =0; i < sBuffer1.length(); i++){
String let1 = String.valueOf(sBuffer1);
if (sBuffer2.indexOf(let1) == -1 ){
}
}
return diffVal;
I think you are trying to use a loop to examine one character by one character in sBuffer1. But String let1 = String.valueOf(sBuffer1); gives you the entire string of sBuffer1.
What you need is String let1 = sBuffer1.substring(i, i + 1) to take a single character from sBuffer1 to check if it exists in sBuffer2.
For example:
public static StringBuffer diff(StringBuffer sBuffer1, StringBuffer sBuffer2) {
StringBuffer diffVal = new StringBuffer();
for (int i = 0; i < sBuffer1.length(); i++) {
String let1 = sBuffer1.substring(i, i + 1); // get the character from sBuffer1
if (sBuffer2.indexOf(let1) == -1) {
diffVal.append(let1); // append the character to the diff
}
}
return diffVal;
}
ok this might work, your logic was a little bit wrong, this code is straight forward. search for the character if it doesn't exist in the second string buffer add it to the result SF.
public StringBuffer diff(){
StringBuffer diffVal = new StringBuffer();//initialize before you use it.
for (int i =0; i < sBuffer1.length(); i++){
String let1 = String.valueOf(sBuffer1.charAt(i))//get the character at the ith position.
if (sBuffer2.indexOf(let1) == -1 ){
diffVal.append(let1);
}
}
return diffVal;
}
Try this.
StringBuilder diffVal= new StringBuilder();
StringBuffer sBuffer1 = new StringBuffer("abbad");//input 1
StringBuffer sBuffer2 = new StringBuffer("acca");//input 2, you can ignore if you have already passed/defined these
for (int i =0; i < sBuffer1.length(); i++){
if(i >= sBuffer2.length()){//handles difference in input string length
diffVal.append(sBuffer1.substring(i, sBuffer1.length()));
break;
}
if (sBuffer1.charAt(i) != sBuffer2.charAt(i)) {
diffVal.append(sBuffer1.charAt(i));
}
}
System.out.println(diffVal);// I am printing it here
the out put is : bbd
One recommendation here is use StringBuilder if you the strings you are using here are not required to be synchronized

Reversing A String. Every other word reversing

So i've got a for loop that's reversing every other word in a string. I can't determine which condition is causing this.
for (int i = 0; i < words.length; i++)
{
stringBuilder.append(words[(words.length-1)-i]);
stringBuilder.reverse()
}
newMessage = stringBuilder.toString();
return Message
stringBuilder.reverse() reverse the whole string that you are currently building at each iteration.
Try:
for (int i = 0 ; i < words.length ; i++) {
String word = words[(words.length-1)-i];
String reverse = new StringBuilder(word).reverse().toString();
stringBuilder.append(reverse).append(" ");
}
Or even simpler, reversing at the end:
for (int i = 0 ; i < words.length ; i++) {
stringBuilder.append(words[(words.length-1)-i]).append(" ");
}
newMessage = stringBuilder.reverse().toString();
Edit based on comments:
for (String w : words) {
String reverse = new StringBuilder(w).reverse().toString();
stringBuilder.append(reverse).append(" ");
}
newMessage = stringBuilder.toString();
stringBuilder.reverse(); is reversing the whole word comment that line and your code wont reverse your new message
var string = "hello world";
function reverseWords(string) {
var words = string.split(' '),
finals = [];
words.forEach(function(word) {
finals.push(word.split('').reverse().join(''););
});
return finals.join(' ');
}
reverseWords(string); // "olleh dlrow"
First of all, your loop is more complex then it needs to be. If you want to reverse words starting from the end, you should just use the loop index to do that, you don't need the (words.length-1)-i calculation.
Another thing, when you call reverse() on a StringBuilder you are reversing the whole string not just the appended portion. What you can do is use a temp StringBuilder to perform the reversal and a temp String variable to separate reversal from appending.
Something like this:
StringBuilder reversedBuilder = new StringBuilder();
for (int i = words.length - 1; i >= 0; i --)
{
String reversed = reversedBuilder.append(words[i]).reverse().toString(); // reverse the word
stringBuilder.append(reversed).append(" ");
reversedBuilder.setLength(0); // clear the reversed
}
If you want, you can do this in a single line of code (added with comments for clarification):
for (int i = words.length - 1; i >= 0; i --)
{
stringBuilder.append(new StringBuilder() // create a temp string builder
.append(words[i]) // add the current word to temp string builder
.reverse() // reverse the current word in the temp string builder
.toString()) // add the reversed word to stringBuilder
.append(" "); // add the space to stringBuilder
}

How can I append a word in between an array of strings?

I want to append the word AND between each string in an array, but I don't want it at the end of my string. Here is what I'm trying:
Assuming I want to pass First, Second, Third
public void addString(String... myString) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < myString.length -1;) {
sb.append("(" + myString[i] + " AND " + myString[i+1] + ")");
i++;
}
System.out.println(sb);
}
My output is (First AND Second)(Second AND Third)
But I want (First AND Second AND Third)
What am I doing wrong?
Append the "(" before your for loop so it prints only once. Similarly, append the ")" after your for loop so it prints only once. Finally, you can loop through your entire myString array, appending only that element, instead of two elements at a time, and only appending " AND " if needed.
Tweak your answer like this:
public void addString(String... myString) {
StringBuilder sb = new StringBuilder("(");
for(int i = 0; i < myString.length -1; i++) {
sb.append(myString[i] + " AND ");
}
if(myString.length == 0)
sb.append(")");
else
sb.append(myString[myString.length - 1]);
System.out.println(sb);
}
The only changes are:
Create the StringBuilder containing the starting (
Add all the elements except the last one, and append "AND" after it
Add the final element and the closing )
The repetitive part of your algorithm is the one that places the inner elements. This also covers the case where myString has length 1. In case of having no elements, the last addition is skipped and the closing ")" is added.
You should seperate the parts that you want just once from you for loop like this. So you want ( and ) once and there is only one word for wich you dont need AND in front of it.
public void addString(String[] myString)
{
StringBuilder sb = new StringBuilder();
sb.append("("+myString[0]);
for(int i = 1; i < myString.length;i++)
{
sb.append(" AND " + myString[i]);
}
sb.append(")")
System.out.println(sb);
}
To do what you want I'd probably use the join method in StringUtils.
StringUtils.join Docs
From the docs:
public static String join(Object[] array,
String separator)
Joins the elements of the provided array into a single String containing the provided list of elements.
No delimiter is added before or after the list. A null separator is the same as an empty String (""). Null objects or empty strings within the array are represented by empty strings.
StringUtils.join(null, *) = null
StringUtils.join([], *) = ""
StringUtils.join([null], *) = ""
StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
StringUtils.join(["a", "b", "c"], null) = "abc"
StringUtils.join(["a", "b", "c"], "") = "abc"
StringUtils.join([null, "", "a"], ',') = ",,a"
Parameters:
array - the array of values to join together, may be null
separator - the separator character to use, null treated as ""
Returns:
the joined String, null if null array input
You can do the following -
Arrays.asList(myString).toString().replaceAll(",", " AND").replace("[", "(").replace("]", ")")
Arrays.asList(myString) converts the array to a List.
toString() converts it to a string which is like [ele1, ele2, ele
3].
Then using the replaceAll and replace method gives the
appropriate output.
The second option is to use the join method provided by StringUtils.
The approach used most often when you want separators between elements is to add the separator first, then the string. Only skipping the separator before the first element.
public void addString(String... myString) {
String separator = " AND ";
StringBuilder sb = new StringBuilder();
sb.append('(');
boolean needSeparator = false;
for(String string : myString) {
if (needSeparator) {
sb.append(separator);
} else {
needSeparator = true;
}
sb.append(string);
}
sb.append(')');
System.out.println(sb);
}
If you call addString("First", "Second", "Third") you'd get
(First AND Second AND Third)
This works perfectly fine with just 1 input addString("First")
(First)
Or even empty input addString() which would crash most other solutions I've seen here
()
It is possible to move printing the first element out of the loop so the loop does not have to check if it needs to omit the separator (minimal performance gain) but that results IMO in less readable code. E.g.:
if (myString.length > 0) {
// append first element without separator
sb.append(myString[0]);
// implicitly checks that length > 1
for (int i = 1; i < myString.length; i++) {
// append separator unconditionally
sb.append(separator);
sb.append(myString[i]);
}
}
Get the Apache CommonsLang package http://commons.apache.org/proper/commons-lang/
then use its StringUtils join() method as described here: http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html
System.out.println(StringUtils.join(myString, ' AND '));
Append the parenthesis before and after the For Loop.
Append only one element in the String at a time.
Remove the final "AND " at the end of the String after the For Loop.
public void addString(String... myString) {
StringBuilder sb = new StringBuilder();
sb.append("(");
for(int i = 0; i < myString.length;) {
sb.append(myString[i] + " AND ");
i++;
}
sb = sb.substring(0, sb.length() - 5);
sb.append(")");
System.out.println(sb);
}
Try this:
public void addString(string[] myString) {
StringBuilder sb = new StringBuilder();
sb.Append("(");
for(int i = 0; i < myString.length; i++) {
sb.Append(myString[i] + " AND ");
}
string result = sb.ToString().Substring(0, sb.ToString().LastIndexOf("AND"));
result += ")";
System.out.println(result);
}
Corrected code:
public void addString(String... myString) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < myString.length; i++) {
if(i = 0){
sb.append("(" + myString[i])
}else if (i = myString.length-1){
sb.append(myString[i] + ")");
}else{
sb.append(myString[i])
}
sb.append("(" + myString[i] + " AND " + myString[i+1] + ")");
}
System.out.println(sb);
}
EDIT: Here is a better version based off of one of the answers above:
public void addString(String[] myString)
{
StringBuilder sb = new StringBuilder();
sb.append("(");
for(int i = 0; i < myString.length; i++){
sb.append(myString[i] + " AND ");
}
sb.append(")")
System.out.println(sb);
}

Categories