Getting the last integer from a string - java

Say I have a string 3 + 4 = 7 or 23 - 4 = 19. I'm wondering how I would go about getting the last integer from the string so that it can be compared to another int.
Ive used this code:
int first = Integer.parseInt(str.substring(0, str.indexOf(" ")));
int second = Integer.parseInt(result.substring(result.indexOf('+')+1 , result.indexOf('=')));
to get the first and second integers for computation, but I can't seem to get the last integer in string when I'm using the method above. Is it just something I'm doing wrong or is there something else I need to do?
I also cannot use arrays, regex, try/catch, or a SystemTokenizer.
And my strings will not always be in the a + b = c format with the spaces or a single digit integer.
the strings are taken from a text file that is imported by the scanner. Here's a sample of the equations in the file:
11 - 2 = 9
12 - 1 = 11
7 + 1 = 8
7 - 3 = 4
7 + 2 = 9
14 + 4 = 18

If all of your strings are in this format - a + b = c, then there is a simple way -
String[] parts = str.split("=");
String lastDigit = parts[parts.length - 1].trim();
int last = Integer.parseInt(lastDigit);
Check out the docs.
Update
As per your requirement of not wanting to use regex, you can do something like this -
public int getLastDigit(String expression) {
StringBuffer result = new StringBuffer();
for (int i = expression.length() - 1; i >= 0; i--) {
char c = expression.charAt(i);
if (c == '=') {
break;
}
else {
result.append(c);
}
}
return Integer.parseInt(result.reverse()
.toString()
.trim());
}
int last = getLastDigit("1 + 3 = 14");
System.out.println(last); // will print 14

This will work a lot easier:
String[] tokens = str.Split(" ");
int first = Integer.parseInt(tokens[0]);
int second = Integer.parseInt(tokens[1]);
int last = Integer.parseInt(tokens[3]);
Otherwise without arrays, use lastIndexOf:
int last = Integer.parseInt(str.substring(str.lastIndexOf(" "), str.length()));

simple use split and get index[1] to get last integer in string
just split with "="

Does this work?
int last = Integer.parseInt(str.substring(str.indexOf("=") + 1, str.length));
The idea is to get the index of the "=", and then parse the substring of there to the end.
I did "str.indexOf("=") + 1" so that it didn't include the "sign".

String [] tokens = str.split("=");
String finalDigit = tokens[tokens.length-1];

You would need trim the extracted digit, other wise it is possible to throw
Exception in thread "main" java.lang.NumberFormatException: For input
string: " 7"
To extract the last digit, you may follow the below code
String str1="3 + 4 = 7";
String str2= str1.substring(str1.lastIndexOf("=")+1).trim();
int i = Integer.parseInt(str2);

import java.io.*;
class GetString{
publice static void main(String []args)
{
string str,int x;
Scanner s = new Scanner(input).useDelimiter("\n"); //take each line
while((str=s.next())!=NULL)
{
str.trim();
int first = Integer.parseInt(str.substring(0, str.indexOf(" ")));
//Depending on weather the sign is '+' or '-' it will take the index of that
int second = Integer.parseInt(str.substring((x=str.indexOf('+')>-1?
str.indexOf('+'):str.indexOf('-'))+1 , result.indexOf('=')));
int Third= Integer.parseInt(str.substring(str.indexOf("="), str.Length-1))
}
s.close();
}
}
Its a general idea not a perfect code.Edits and suggestions are welcome.

Related

Validate a String to Double with max digits

For example when I parse a string "12345678901234567890" to double using Double.parseDouble() it returns the value "12345678901234567000" since it can hold up to 17 digits.
I want to validate this scenario and the user should be allowed to pass only 17 digits. How do I do this?
Example :
1.2345678901234567890 is invalid because it has more than 17 digits total
1.2345E+10 is valid
Tried something like this which can count the digits using split function
String input="12345678901234567E100";
String inputWithoutSign;
int lengthFullNumber;
int lengthFraction;
double v = Double.parseDouble(input);
if(input.startsWith("+") || input.startsWith("-")){
inputWithoutSign = input.split("[-+]",2)[1];
}
else inputWithoutSign = input;
String num = inputWithoutSign.split("[eE]", 2)[0];
if(num.indexOf('.') == -1){
lengthFullNumber = num.length();
lengthFraction = 0;
}else{
String[] splitNum = num.split("\\.", 2);
lengthFullNumber = splitNum[0].length();
lengthFraction = splitNum[1].length();
}
System.out.println("length:"+(lengthFullNumber+lengthFraction));
Presuming I understand your goal of limiting the number of digits, this may help solve the problem.
Test cases
String[] vals = {
"12345678901234567890", "123456789091919191919",
"182828282.18282828", "182828282.182828282", "191929e10",
"192929.22929e10"
};
Try and parse them
for (String v : vals) {
// remove possible decimal point and signs
String test = v.replaceAll("[.+-]", "");
// remove any exponents at end of string
test = test.replace("\\D+.*", "");
if (test.length() > 17) {
System.out.println(v + " has too many digits");
continue;
}
double d = Double.parseDouble(v);
System.out.println(v + " parses to " + d);
}

Get index of 3rd comma

For example I have this string params: Blabla,1,Yooooooo,Stackoverflow,foo,chinese
And I want to get the string testCaseParams until the 3rd comma: Blabla,1,Yooooooo
and then remove it and the comma from the original string so I get thisStackoverflow,foo,chinese
I'm trying this code but testCaseParams only shows the first two values (gets index of the 2nd comma, not 3rd...)
//Get how many parameters this test case has and group the parameters
int amountOfInputs = 3;
int index = params.indexOf(',', params.indexOf(',') + amountOfInputs);
String testCaseParams = params.substring(0,index);
params = params.replace(testCaseParams + ",","");
You can hold the index of the currently-found comma in a variable and iterate until the third comma is found:
int index = 0;
for (int i=0; i<3; i++) index = str.indexOf(',', index);
String left = str.substring(0, index);
String right = str.substring(index+1); // skip comma
Edit: to validate the string, simply check if index == -1. If so, there are not 3 commas in the string.
One option would be a clever use of String#split:
String input = "Blabla,1,Yooooooo,Stackoverflow,foo,chinese";
String[] parts = input.split("(?=,)");
String output = parts[0] + parts[1] + parts[2];
System.out.println(output);
Demo
One can use split with a limit of 4.
String input = "Blabla,1,Yooooooo,Stackoverflow,foo,chinese";
String[] parts = input.split(",", 4);
if (parts.length == 4) {
String first = parts[0] + "," + parts[1] + "," + parts[2];
String second = parts[3]; // "Stackoverflow,foo,chinese"
}
You can split with this regex to get the 2 pats:
String[] parts = input.split("(?<=\\G.*,.*,.*),");
It will result in parts equal to:
{ "Blabla,1,Yooooooo", "Stackoverflow,foo,chinese" }
\\G refers to the previous match or the start of the string.
(?<=) is positive look-behind.
So it means match a comma for splitting, if it is preceded by 2 other commas since the previous match or the start of the string.
This will keep empty strings between commas.
I offer this here just as a "fun" one line solution:
public static int nthIndexOf(String str, String c, int n) {
return str.length() - str.replace(c, "").length() < n ? -1 : n == 1 ? str.indexOf(c) : c.length() + str.indexOf(c) + nthIndexOf(str.substring(str.indexOf(c) + c.length()), c, n - 1);
}
//Usage
System.out.println(nthIndexOf("Blabla,1,Yooooooo,Stackoverflow,foo,chinese", ",", 3)); //17
(It's recursive of course, so will blow up on large strings, it's relatively slow, and certainly isn't a sensible way to do this in production.)
As a more sensbile one liner using a library, you can use Apache commons ordinalIndexOf(), which achieves the same thing in a more sensible way!

How to fix this Run time error?

I am trying to make a java program which will find and remove repetative characters in string. Like if user types "baloon", the output should be "balon". I used String variable for input and copied its content to Char array so that I can analyze each character. I get ArrayIndexOutOfBoundsException. Here is my code
class doubleKiller{
private String inputStr = " ";
private char[] catchStr = new char[inputStr.length()];
private String modifiedStr;
//Accessor method
public void getString(String inputStr)
{
this.inputStr = inputStr;
}
public String killRepeater()
{
//copying string data to char array
this.inputStr.getChars(0 , this.inputStr.length() , catchStr , 0);
//------------------
for(int counter = 0 ; counter < this.inputStr.length() ; counter++)
{
if(catchStr[counter] != catchStr[counter - 1])
{
modifiedStr = modifiedStr + catchStr[counter];
}
}
return modifiedStr;
}
}
Here is Output when killRepeater() is called.
java.lang.ArrayIndexOutOfBoundsException: src.length=5 srcPos=0 dst.length=1 dstPos=0 length=4
at java.lang.System.arraycopy(Native Method)
at java.lang.String.getChars(String.java:894)
at doubleKiller.killRepeater(Main.java:23)
at useThings.main(Main.java:49)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.aide.ui.build.java.RunJavaActivity$1.run(SourceFile:108)
at java.lang.Thread.run(Thread.java:862)
Tell me my error...Thanks in advance
You are doing
private String inputStr = " ";
private char[] catchStr = new char[inputStr.length()];
inputStr.length() returns 1, that is, the size from the string " ", so, you have a char array with size 1.
When you do:
for(int counter = 0 ; counter < this.inputStr.length() ; counter++){
if(catchStr[counter] != catchStr[counter - 1]){
With a inputStr.length() > 1 you have an ArrayIndexOutOfBoundsException.
Also, when run catchStr[counter - 1]) for the first time, counter-1 would generate -1, which isn't a valid index. Try running the counter from 1 to avoid this error.
Declare your array with a fixed size(e.g 200) or use an ArrayList. You could also put catchStr = new char[inputStr.length()] after taking the input of the String.
Good thing that you asking about specific problem, but in case you interested how to make this simpler, there is regex magic
String in = "ballooooon";
String out = in.replaceAll("(.)\\1+", "$1"); // balon
Which means
find any symbol, save it to group 1, if next symbol, or symbols are equal to group 1, delete them and leave just one from the group.
You are initializing catchStr with inputStr.length(). But at this time inputStr = " ". So catchStr has a length of 1. When you later populate inputStr to a bigger value, you try and copy that into a char[] of length 1 and it doesn't fit. Add catchStr = new char[inputStr.length()]; right before you do the copy.
When you initialise catchStr it will always have the value of 1, because inputStr is " " and therefore it's length is 1.
private String inputStr = " ";
private char[] catchStr = new char[inputStr.length()];
When you loop on counter in the method killRepeater() you will get an ArrayOutOfBoundsException because the string you pass in getString is probably greater than 1.
Consider moving new char[inputStr.length()] into getString.
public void getString(String inputStr) {
this.inputStr = inputStr;
this.catchStr = new char[inputStr.length()];
}
And, setting the attribute catchStr to uninitialised.
private char[] catchStr;
The second issue is with your for loop. You start the counter at 0 and use catchStr[counter - 1] to look back on the previous character. This will not work when counter = 0 because the index will evaluate to -1.
Consider starting your counter at 1, and continue to work on the method from there. You'll need to tweak it a little to get it output the desired string.
for (int counter = 1; counter < this.inputStr.length(); counter++) {
if (catchStr[counter] != catchStr[counter - 1]) {
modifiedStr = modifiedStr + catchStr[counter];
}
}

How can I format a two row string so that items of the bottom row line up with items of the top row in java

So I have something set up like this:
public static void main(String[] args) {
String fun = ("3000.05 500 6000.987 70 8000.00");
String lame = ("3 5 6 7 8");
String total = (fun + "\n" + lame);
System.out.println(total);
}
How can I format the total string so that when it prints it prints like this:
3000.05 500 6000.987 70 8000.00
3 5 6 7 8
I've been looking forever and can't seem to find what i'm looking for. I'm just trying to right align each part of the bottom string to the farthest part of the top string.
you can use a for loop to go through each position on the string and create a new String to store what you are looking for. Ex.
public static void main(String[] args) {
String fun = ("3000.05 500 6000.987 70 8000.00");
String newStringToBePrinted="";
for(char c: fun){
if (!(c == ' '|| c == '.')){
String ch = c+"";
newStringToBePrinted+= ch;
} else{
newStringToBePrinted+="-";
}
}
String total = (fun + "\n" + newStringToBePrinted);
System.out.println(total);
}
hope this helps.
Here is how you can do this with (moderately) readable Stream code. The below method will work, but it's a bit ugly because AFAIK Java 8 does not yet have a clean 'zip' function for streams.
As well, because of the way String.format() works, I had to pad the first thing in the list separately, which is also kind of yucky, but I couldn't quickly think of a way to make it all fit.
private String formatStringPairs(String firstLine, String secondLine, String delimiter) {
String[] firstLineArray = firstLine.split(delimiter);
String[] secondLineArray = secondLine.split(delimiter);
String formattedStringPairs =
String.format("%" + firstLineArray[0].length() + "s", secondLineArray[0]) +
IntStream.range(1, firstLineArray.length)
.mapToObj(index -> String.format("%" + (firstLineArray[index].length() + 1) + "s", secondLineArray[index]))
.reduce("", String::concat);
return firstLine + "\n" + formattedStringPairs;
}
I look forward to seeing someone post a cleaner and better way!
This should work. I believe temp is the recreation of your variable lame but the code would be the same.
package funTest;
public class funT {
public static void main(String[] args) {
String fun = ("3000.05 500 6000.987 70 8000.00");
String s2 = new String(fun);
char first=' ';
String temp="";
for (int i = 0;i < s2.length(); i++){
System.out.println("Should be: 3,5,6,7,8");
//gets first
if (i!=0){
if (s2.charAt(i)==' '){
first=s2.charAt(i+1);
}
}else{
first=s2.charAt(i);
}
System.out.println("First = "+first);
/////
//add spaces
if (s2.charAt(i)!=' '){
temp+=' ';
}
if (i<s2.length()-1&&s2.charAt(i+1)==' '){
temp+=first;
} else if (i==s2.length()-1){
temp+=first;
}
}
temp = temp.substring(1);
System.out.println(s2+"\n"+temp);
}
}
Ok so tldr. Use the .format() method of PrintStream (for byte streams) or PrintWriter (for char streams)
Luckily System.out is one of these objects. Documentation for format can be found here
Here is a nice demonstration of using .format() I mentioned for your purpose, this code assumes the two strings have an equal number of numbers separated by whitespace. It also assumes that the second-row item length will be <= in length to its' first-row counterpart
public static void main(String[] args)
{
String fun = "3000.05 500 6000.987 70 8000.00";
String lame = "3 5 6 7 8";
String[] funs = fun.split(" ");
String[] lames = lame.split(" ");
for(String s : funs)
{
System.out.printf("%s\t", s);
}
System.out.printf("%n");
for(int i = 0; i < lames.length; i++) //use index iterator so we can get le funz
{
System.out.printf("%" + funs[i].length() + "s\t", lames[i]);
}
System.out.printf("%n");
}
Output:
run:
3000.05 500 6000.987 70 8000.00
3 5 6 7 8
BUILD SUCCESSFUL (total time: 0 seconds)
To improve this code more It might be possible to associate the first row and second row in a Map type object, and then when printing: set the padding size
to the size of the entry key or value which has the greatest length. Also add a handler for empty entries.

How to split numbers in java?

I am trying to split number but don't know how to do this.
I referred this link.
https://stackoverflow.com/a/12297231/1395259
Suppose I have a number 12345678.
using above link I am splitting by 3 places.So the output becomes 123 456 78.
But I want it as 12 345 678 And I want to take the string that was split in the form 12.345.678 .
Can anybody help me please??
java.text package provides all reasonable options for formatting numbers
DecimalFormat f = new DecimalFormat("#,###");
DecimalFormatSymbols fs = f.getDecimalFormatSymbols();
fs.setGroupingSeparator('.');
f.setDecimalFormatSymbols(fs);
String s = f.format(12345678);
System.out.println(s);
output
12.345.678
using DecimalFormat directly is very flexible, but typically we can use a shorter version
String s = NumberFormat.getNumberInstance(Locale.GERMAN).format(12345678);
which produces the same string
12.345.678
Different countries have different rules for formatting numbers (and dates). Usually we want our programs to be internationalized / localized and use default locale version
NumberFormat.getNumberInstance().format(number);
One lazy way is to reverse the string, apply above method, and then reverse it again.
You can use StringBuffer's Reverse Function, as shown in Reverse each individual word of "Hello World" string with Java
12345678
87654321
876 543 21
12 345 678
I am assuming of course that you want to split by 3s and the group with <3 digits left appears in the start rather than the end as in the method you link.
The not so lazy way would be to use string length to adapt the method you link to start with length%3 characters.
Using the solution from your link i would rephrase that as following (TESTED!):
public String[] splitStringEvery(String s, int interval) {
int arrayLength = (int) Math.ceil(((s.length() / (double)interval)));
String[] result = new String[arrayLength];
int j = s.length();
int lastIndex = result.length;
for (int i = lastIndex - 1; i > 0; i--) {
result[i] = s.substring(j - interval, j);
j -= interval;
} //Add the last bit
result[0] = s.substring(0, j);
return result;
}
Here is a method that splits an int value and returns an String in the specified format:
public static String split( int n ) {
String result = "", s = Integer.toString( n );
while ( s.length() > 3 ) {
result = s.substring( s.length() -3, s.length() ) + ((result.length() > 0)? "." + result : "" );
s = s.substring( 0, s.length() -3 );
}
return s + "." + result;
}
Input:
12345678
Output:
12.345.678
If it's a String, use StringBuilder or StringBuffer. Here's the code:
public class SplitNumber {
public static void main(String[] args){
int number = 12345678;
String numberStrBefore = Integer.toString(number);
StringBuffer numberStrAfter = new StringBuffer();
numberStrAfter.append(numberStrBefore.charAt(0));
numberStrAfter.append(numberStrBefore.charAt(1));
numberStrAfter.append('.');
numberStrAfter.append(numberStrBefore.charAt(2));
numberStrAfter.append(numberStrBefore.charAt(3));
numberStrAfter.append(numberStrBefore.charAt(4));
numberStrAfter.append('.');
numberStrAfter.append(numberStrBefore.charAt(5));
numberStrAfter.append(numberStrBefore.charAt(6));
numberStrAfter.append(numberStrBefore.charAt(7));
System.out.println("Number Before: " + numberStrBefore);
System.out.println("Number After: " + numberStrAfter.toString());
}
}
And here is the same thing with a method:
public class SplitNumber {
public static void main(String[] args){
int number = 12345678;
int[] split = {2,3,3}; //How to split the number
String numberStrAfter = insertDots(number, split);
System.out.println("Number Before: " + number);
System.out.println("Number After: " + numberStrAfter);
}
public static String insertDots(int number, int[] split){
StringBuffer numberStrAfter = new StringBuffer();
String numberStr = Integer.toString(number);
int currentIndex = 0;
for(int i = 0; i < split.length; i++){
for(int j = 0; j < split[i]; j++){
numberStrAfter.append(numberStr.charAt(currentIndex));
currentIndex++;
}
numberStrAfter.append('.');
}
numberStrAfter.deleteCharAt(numberStrAfter.length()-1); //Removing last "."
return numberStrAfter.toString();
}
}
This version, with the method, allows you to split any number into any format that you want, simply change the "split" variable into the format that you want to split the string into. (Ex: Splitting 12345678 into: 1.1234.5.67.8 would mean that "split" must be set to {1,4,1,2,1}).

Categories

Resources