Copying numbers from an addition series into an array - java

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.

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

My loop is populating my array with the number seven, 6 times, why?

Im writing a program to read in a file and store the strings in arraylist and ints in an array. The file contains strings and ints in the format: String int
I have already got the string section to work, I'm looking to know why the following code is populating my array with the number 7, six times rather than the correct numbers.
Correct output would be:
12, 14, 16, 31, 42, 7
But it gives:
7, 7, 7, 7, 7, 7
Code:
BufferedReader buffy = new BufferedReader(new FileReader(fileName));
while((str = buffy.readLine()) != null) {
for(int i = 0; i <= arrayInt.length - 1; i++) {
for(int k = 0; k <= str.length()-1; k++) {
if(str.substring(k, k + 1).equals(" ")) {
String nums = str.substring(k+1);
arrayInt[i] = Integer.parseInt(nums);
}
}
}
}
buffy.close();
This happens because for each line in file you fill whole array.
Try this:
int i = 0;
BufferedReader buffy = new BufferedReader(new FileReader(fileName));
while((str = buffy.readLine()) != null) {
if(i < arrayInt.length) {
for(int k = 0; k <= str.length()-1; k++) {
if(str.substring(k, k + 1).equals(" ")) {
String nums = str.substring(k+1);
arrayInt[i] = Integer.parseInt(nums);
break;
}
}
i++;
}
}
buffy.close();
Also you can use indexOf
int i = 0;
BufferedReader buffy = new BufferedReader(new FileReader(fileName));
while((str = buffy.readLine()) != null) {
if(i < arrayInt.length) {
int k = str.indexOf(" ");
if(k!=-1) {
String nums = str.substring(k+1);
arrayInt[i] = Integer.parseInt(nums);
}
i++;
}
}
buffy.close();
File read are typically batch/ETL kind of job and if this code is going to production and would be used multiple times instead of only once then I would like to stress on Performance and Ease of Maintenance:
Only read least characters to identify the space index
#talex added a very good line of code i.e. break; inside the loop that way you won't need to read till the end of line but this would only work if the string has no spaces. If the string can contain spaces than you would need lastIndexOf space (" ") or no break; at all.
I prefer using framework method lastIndexOf assuming you are using java because:
it would start reading from right instead of left and assuming the numbers would be always less length than the string it would find index of space faster in most of the cases than reading from start.
2nd benefit is that there are lots of scenarios framework/utilities method already handled so why to reinvent the wheel
int k = str.lastIndexOf(" ");
last but not the least if someone else is going to maintain this code it would be easier for him/her as there would be enough documentation available.
Only read required lines from files
Seems like you only need certain number of lines to read arrayInt.length if that's the case then you should 'break;' the while loop once the counter i is more than array length.
I/O operations are costly and though you will get right output you would end-up scanning whole file even if it's not required.
Dont forget try-catch-finally
The code assumes that there will not be any issue and it would be able to close the file after done but there could be n number of combinations that can result in error resulting the application to crash and locking the file.
See the below example:
private Integer[] readNumbers(String fileName) throws Exception {
Integer[] arrayInt = new Integer[7];
String str = null;
BufferedReader buffy = new BufferedReader(new FileReader(fileName));
try {
int i=0;
while ((str = buffy.readLine()) != null) {
if(i> arrayInt.length){
break;
}
//get last index of " "
int k = str.lastIndexOf(" ");
if(k > -1){
String nums = str.substring(k+1);
arrayInt[i] = Integer.parseInt(nums);
}
//increment the line counter
i++;
}
} catch (Exception ex) {
//handle exception
} finally {
buffy.close();
}
return arrayInt;
}

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
}

Java: Accumulate output pattern in string variable?

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).

Categories