Add both string and int value in one JTextField - java

Convert user input of meters to feet and inches with the
// following format (16ft. 4in.). Disable the button so that
// the user is forced to clear the form.
Problem is that I don't know how to put both string and int value in one text Field, than how can i set them to in if else statement
private void ConversionActionPerformed(ActionEvent e )
{
String s =(FourthTextField.getText());
int val = Integer.parseInt(FifthTextField.getText());
double INCHES = 0.0254001;
double FEET = 0.3048;
double meters;
if(s.equals("in" ) )
{
FourthTextField.setText(" " + val*INCHES + "inch");
}
else if(s.equals("ft"))
{
FourthTextField.setText(" " +val*FEET + "feet");
}
}
Is it possible to add both string and int value in one JTextField?

You could do ...
FourthTextField.setText(" " + (val*INCHES) + "inch");
or
FourthTextField.setText(" " + Double.toString(val*INCHES) + "inch");
or
FourthTextField.setText(" " + NumberFormat.getNumberInstance().format(val*INCHES) + "inch");
Updated
If all you care about is extract the numeric portion of the text, you could do something like this...
String value = "1.9m";
Pattern pattern = Pattern.compile("\\d+([.]\\d+)?");
Matcher matcher = pattern.matcher(value);
String match = null;
while (matcher.find()) {
int startIndex = matcher.start();
int endIndex = matcher.end();
match = matcher.group();
break;
}
System.out.println(match);
This will output 1.9, having stripped of every after the m. This would allow you to extract the numeric element of the String and convert to a number for conversion.
This will handle both whole and decimal numbers.

Related

Java parse string using regex into variables

I need to extract variables from a string.
String format = "x:y";
String string = "Marty:McFly";
Then
String x = "Marty";
String y = "McFly";
but the format can be anything it could look like this y?x => McFly?Marty
How to solve this using regex?
Edit: current solution
String delimiter = format.replace(Y, "");
delimiter = delimiter.replaceAll(X, "");
delimiter = "\\"+delimiter;
String strings[] = string.split(delimiter);
String x;
String y;
if(format.startsWith(X)){
x = strings[0];
y = strings[1];
}else{
y = strings[0];
x = strings[1];
}
System.out.println(x);
System.out.println(y);
This works well, but I would prefer more clean solution.
There is no need for regex at all.
public static void main(String[] args) {
test("x:y", "Marty:McFly");
test("y?x", "McFly?Marty");
}
public static void test(String format, String input) {
if (format.length() != 3 || Character.isLetterOrDigit(format.charAt(1))
|| (format.charAt(0) != 'x' || format.charAt(2) != 'y') &&
(format.charAt(0) != 'y' || format.charAt(2) != 'x'))
throw new IllegalArgumentException("Invalid format: \"" + format + "\"");
int idx = input.indexOf(format.charAt(1));
if (idx == -1 || input.indexOf(format.charAt(1), idx + 1) != -1)
throw new IllegalArgumentException("Invalid input: \"" + input + "\"");
String x, y;
if (format.charAt(0) == 'x') {
x = input.substring(0, idx);
y = input.substring(idx + 1);
} else {
y = input.substring(0, idx);
x = input.substring(idx + 1);
}
System.out.println("x = " + x);
System.out.println("y = " + y);
}
Output
x = Marty
y = McFly
x = Marty
y = McFly
If the format string can be changed to be a regex, then using named-capturing groups will make it very simple:
public static void main(String[] args) {
test("(?<x>.*?):(?<y>.*)", "Marty:McFly");
test("(?<y>.*?)\\?(?<x>.*)", "McFly?Marty");
}
public static void test(String regex, String input) {
Matcher m = Pattern.compile(regex).matcher(input);
if (! m.matches())
throw new IllegalArgumentException("Invalid input: \"" + input + "\"");
String x = m.group("x");
String y = m.group("y");
System.out.println("x = " + x);
System.out.println("y = " + y);
}
Same output as above, including value order.
You can use the following regex (\\w)(\\W)(\\w)
This will find any alphanumeric characters followed by any non alpha-numeric followed by another set of alpha numeric characters. The parenthesis will group the finds so group 1 will be parameter 1, group 2 will be the delimiter and group 3 will be parameter 2.
Comparing parameter 1 with parameter 2 can determine which lexical order they go in.
Sample
public static void main(String[] args) {
testString("x:y", "Marty:McFly");
testString("x?y", "Marty?McFly");
testString("y:x", "Marty:McFly");
testString("y?x", "Marty?McFly");
}
/**
*
*/
private static void testString(String format, String string) {
String regex = "(\\w)(\\W)(\\w)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(format);
if (!matcher.find()) throw new IllegalArgumentException("no match found");
String delimiter = matcher.group(2);
String param1 = matcher.group(1);
String param2 = matcher.group(3);
String[] split = string.split("\\" + delimiter);
String x;
String y;
switch(param1.compareTo(param2)) {
case 1:
x = split[1];
y = split[0];
break;
case -1:
case 0:
default:
x = split[0];
y = split[1];
};
System.out.println("String x: " + x);
System.out.println("String y: " + y);
System.out.println(String.format("%s%s%s", x, delimiter, y));
System.out.println();
}
This approach will allow you to have any type of format not just x and y. You can have any format that matches the regular expression.

CharAt(0) out of bounds exception when I have too much white space

Currently stuck on an assignment that requires me to print out the users name as such: Last,First Initial.
(Bob, Billy H.) If I add too many spaces between the first and middle name when inputting, I get an index out of bounds exception. (String out of bounds 0) The program runs completely fine unless I have more than one space between the first and middle name.
I can only use the trim, indexOf, substring,and charAt methods in this program.
import java.util.Scanner;
public class Name {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Enter your name in this format: <spaces>First name<spaces>Middle name<spaces>Last name<spaces>");
String name = s.nextLine();
name = name.trim();
String first, middle, last;
int firstSpace = name.indexOf(' ');
first = name.substring(0, firstSpace);
int secondSpace = name.indexOf(" ", (firstSpace + 1));
middle = name.substring((firstSpace + 1), secondSpace);
middle.trim();
last = name.substring(secondSpace+1);
char middleInitial = middle.charAt(0);
String initial = "";
initial = initial + middleInitial;
for(int i = 1; i < middle.length(); i++) {
char currentLetter = middle.charAt(i);
char lastLetter = middle.charAt(i - 1);
if(lastLetter == ' ') {
initial = initial + "." + currentLetter;
}
}
System.out.println(last + "," + first + ' ' + initial + ".");
}
}
The reason for error is for input
amid skum asdf
for above input:
int firstSpace = name.indexOf(' '); //firstSpace = 0
int secondSpace = name.indexOf(" ", (firstSpace + 1));//secondSpace = 1
middle = name.substring((firstSpace + 1), secondSpace); // as the two or more continues space inputted, this will select empty string as firstSpace + 1 == secondSpace and later causing the exception
Do name = name.replaceAll(" +", " "); to replace all two or more white spaces.
As karthik suggested in comments, perform assignment middle = middle.trim();.
EDIT:
Since you can not use replaceAll, Modified the code just by using trim method. Have a closer look at the below snippets:
String middleNameLastName = name.substring(firstSpace+1).trim();
last = middleNameLastName.substring(index+1).trim();
These removes trailing spaces.
import java.util.Scanner;
public class Post1 {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Enter your name in this format: <spaces>First name<spaces>Middle name<spaces>Last name<spaces>");
String name = s.nextLine();
name = name.trim();
String first, middle, last;
int firstSpace = name.indexOf(' ');
first = name.substring(0, firstSpace);
String middleNameLastName = name.substring(firstSpace+1).trim();
int index = middleNameLastName.indexOf(" ");
middle = middleNameLastName.substring(0, index);
last = middleNameLastName.substring(index+1).trim();
System.out.println(last + "," + first + ' ' + middle.charAt(0) + ".");
s.close();
}
}

How to convert a location in Degrees Minutes Seconds represented as a String to Double

My app lets users search a location and one of the queries I got was
"78°14'09"N 15°29'29"E"
Obviously the user wants to go to this location.
First how do I check if this string fits the decimal format correctly. Then how do I convert it to double format?
double latitude = convertToDouble("78°14'09"N")
I searched here on stackoverflow but they are all looking for the opposite: double to decimal.
78°14'09"N 15°29'29"E
First how do I check if this string fits the decimal format correctly. Then how do I convert it to double format?
The string is not in decimal (degrees) format. It is in degrees, minutes, and seconds, which is more or less the opposite of decimal degrees format. I therefore interpret you to mean that you want to test whether the string is in valid D/M/S format, and if so, to convert it to decimal degrees, represented as a pair of doubles.
This is mostly a parsing problem, and regular expressions are often useful for simple parsing problems such as this one. A suitable regular expression can both check the format and capture the numeric parts that you need to extract. Here is one way to create such a pattern:
private final static Pattern DMS_PATTERN = Pattern.compile(
"(-?)([0-9]{1,2})°([0-5]?[0-9])'([0-5]?[0-9])\"([NS])\\s*" +
"(-?)([0-1]?[0-9]{1,2})°([0-5]?[0-9])'([0-5]?[0-9])\"([EW])");
That's a bit dense, I acknowledge. If you are not familiar with regular expressions then this is no place for a complete explanation; the API docs for Pattern provide an overview, and you can find tutorials in many places. If you find that your input matches this pattern, then not only have you verified the format, but you have also parsed out the correct pieces for the conversion to decimal degrees.
The basic formula is decimal = degrees + minutes / 60 + seconds / 3600. You have the additional complication that coordinates' direction from the equator / prime meridian might be expressed either via N/S, E/W or by signed N, E, or by a combination of both. The above pattern accommodates all of those alternatives.
Putting it all together, you might do something like this:
private double toDouble(Matcher m, int offset) {
int sign = "".equals(m.group(1 + offset)) ? 1 : -1;
double degrees = Double.parseDouble(m.group(2 + offset));
double minutes = Double.parseDouble(m.group(3 + offset));
double seconds = Double.parseDouble(m.group(4 + offset));
int direction = "NE".contains(m.group(5 + offset)) ? 1 : -1;
return sign * direction * (degrees + minutes / 60 + seconds / 3600);
}
public double[] convert(String dms) {
Matcher m = DMS_PATTERN.matcher(dms.trim());
if (m.matches()) {
double latitude = toDouble(m, 0);
double longitude = toDouble(m, 5);
if ((Math.abs(latitude) > 90) || (Math.abs(longitude) > 180)) {
throw new NumberFormatException("Invalid latitude or longitude");
}
return new double[] { latitude, longitude };
} else {
throw new NumberFormatException(
"Malformed degrees/minutes/seconds/direction coordinates");
}
}
The convert() method is the main one; it returns the coordinates as an array of two doubles, representing the coordinates in decimal degrees north and east of the intersection of the equator with the prime meridian. Latitudes south of the equator are represented as negative, as are longitudes west of the prime meridian. A NumberFormatException is thrown if the input does not match the pattern, or if the latitude or longitude apparently represented is invalid (the magnitude of the longitude cannot exceed 180°; that of the latitude cannot exceed 90°).
You won't be able to parse that into a double without removing the non number chars but,
String string = "78°14'09"N";
Double number = 0;
try{
number = Double.parseDouble(string);
//do something..
}catch (NumberFormatException e){
//do something.. can't be parsed
}
If you first remove any characters from the string that are not alphanumeric, then something along these lines will work. This code compiles.
public class HelloWorld{
public static void main(String []args){
String input = "78 14'09 N 15 29'29 E".replaceAll("[^A-Za-z0-9]", " ");
String[] array = input.split(" ");
int nDegree = Integer.parseInt(array[0]);
int nMinute = Integer.parseInt(array[1]);
int nSecond = Integer.parseInt(array[2]);
int eDegree = Integer.parseInt(array[4]);
int eMinute = Integer.parseInt(array[5]);
int eSecond = Integer.parseInt(array[6]);
double nDegrees = nDegree + (double) nMinute/60 + (double) nSecond/3600;
double eDegrees = eDegree + (double) eMinute/60 + (double) eSecond/3600;
String nResult = "Decimal = N " + Double.toString(nDegrees).substring(0,10);
String eResult = "Decimal = E " + Double.toString(eDegrees).substring(0,10);
System.out.println(nResult);
System.out.println(eResult);
}
}
Output:
Decimal = N 78.2358333
Decimal = E 15.4913888
The problem is that Java can't store the degrees ° character as part of a String, or internal quotes (the minute character). If you can find a way to remove them from the string before inputting the data, then this will work.
I don't have a solution for handling the degrees symbol, but you could use an escape symbol \" to allow the use of a quotation mark within a string.
So I've used a regex with capturing groups to grab each of the numbers and the N/S/E/W. After capturing each individually it's just a matter of doing a bit of dividing to get the numbers and then formatting them however you'd like. For example I went with 5 digits of precision here.
public static void main(String[] args) {
String coords = "78°14'09N 15°29'29E";
String[] decimalCoords = degreesToDecimal(coords);
System.out.println(decimalCoords[0]);
System.out.println(decimalCoords[1]);
}
public static String[] degreesToDecimal(String degMinSec) {
String[] result = new String[2];
Pattern p = Pattern.compile("(\\d+).*?(\\d+).*?(\\d+).*?([N|S|E|W]).*?(\\d+).*?(\\d+).*?(\\d+).*?([N|S|E|W]).*?");
Matcher m = p.matcher(degMinSec);
if (m.find()) {
int degLat = Integer.parseInt(m.group(1));
int minLat = Integer.parseInt(m.group(2));
int secLat = Integer.parseInt(m.group(3));
String dirLat = m.group(4);
int degLon = Integer.parseInt(m.group(5));
int minLon = Integer.parseInt(m.group(6));
int secLon = Integer.parseInt(m.group(7));
String dirLon = m.group(8);
DecimalFormat formatter = new DecimalFormat("#.#####", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
formatter.setRoundingMode(RoundingMode.DOWN);
result[0] = formatter.format(degLat + minLat / 60.0 + secLat / 3600.0) + " " + dirLat;
result[1] = formatter.format(degLon + minLon / 60.0 + secLon / 3600.0) + " " + dirLon;
}
return result;
}
There is no error handling here, it's just a basic example of how you could make this work with your input.

How to utilize a switch statement in this instance?

I'm writing a program that converts units (ex. oz & lb) to new units of measurement (g & kg). I was going to have the user to input the unit they want to convert from and the value of the original unit. I also set constants to convert the selected units. What I'm having an issue with is using a switch statement to determine what conversion I should use (oz ---> g, oz --->, etc).
Here's the code:
System.out.print("Convert from: ");
String origMeasure = input.nextLine();
System.out.print("Convert to: ");
String newMeasure = input.nextLine();
System.out.print("Value: ");
double value = input.nextDouble();
double newValue = 0;
final double OZ_TO_G = 28.3;
final double OZ_TO_KG = 0.028;
final double LB_TO_G = 453.6;
final double LB_TO_KG = 0.045;
final double IN_TO_MM = 25.4;
final double IN_TO_CM = 2.54;
final double IN_TO_M = 0.0254;
final double FT_TO_MM = 304.8;
final double FT_TO_CM = 30.48;
final double FT_TO_M = 0.3048;
final String OZ = " oz";
final String LB = " lb";
final String IN = " in";
final String FT = " ft";
final String G = " g";
final String KG = " kg";
final String MM = " mm";
final String CM = " cm";
final String M = " m";
switch(origMeasure){
case(OZ):
newValue = (value * OZ_TO_G);
break;
}
System.out.println(value + origMeasure + "=" + newValue + newMeasure);
}
}
Concatinate the two strings together and use that as your case statement. So if the user inputs oz for the initial measurement, and then g for the final measurement, you will have switch(initial + final) to yield: ozg.
Have your case statement check for each:
String orig = input.next();
String end = input.next();
switch(orig + end){
case "ozg": //DO MATHEMETICAL FUNCTION HERE TO GET RESULT OF OZ --> G
}
}
You could use a input concatenation + dictionary to do this without a switch statement.
Dictionary<string, float> conversions = new Dictionary<string, float>();
conversion.add("OZ_TO_KG", 28.3);
System.out.print("Convert from: ");
String origMeasure = input.nextLine();
System.out.print("Convert to: ");
String newMeasure = input.nextLine();
System.out.print("Value: ");
double value = input.nextDouble();
string conversion = origMeasure + "_TO_" + newMeasure;
float rate = conversions[conversion];
double newValue = value * rate;
You have to validate if the conversion exists in order to not raise Exceptions.
I suggest you break down your code , in different classes one for each kind of measurement
1. One For Height,Weight etc ..(This would break your problem down)
Each of these classes may have a map , which would hold conversion unit eg,
kg-lb(key) -- > 2.20462(value)
m-cm --> 100 etc
You can put in a Parser which would parse the user input. User input can be in the format like ( 10 kg to lb) . parse the user input and create keys(kg-lb) to be used with map and just multiply the conversion unit
If this utility is something that you intend to extend and maintain in the future, I would suggest that you use enums and separate the conversion into two steps through a common base unit:
public enum UnitType
{
WGT("Weight"),
DST("Distance");
public final String title;
UnitType(String pTitle)
{
title = pTitle;
}
}
public enum Unit
{
//Weight Units: base unit for all is GM
GM(UnitType.WGT, BigDecimal.ONE, "Grams"),
KG(UnitType.WGT, new BigDecimal("1000"), "Kilograms"),
MG(UnitType.WGT, new BigDecimal("0.001"), "Milligrams"),
OZ(UnitType.WGT, new BigDecimal("28.3"), "Ounces"),
LB(UnitType.WGT, (new BigDecimal("16")).multiply(OZ.baseFactor), "Pounds"),
//Distance Units: base unit for all is MTR
MTR(UnitType.DST, BigDecimal.ONE, "Meters"),
MM(UnitType.DST, new BigDecimal("0.001"), "Millimeters"),
CM(UnitType.DST, new BigDecimal("0.01"), "Centimeters"),
KM(UnitType.DST, new BigDecimal("1000"), "Kilometers"),
FT(UnitType.DST, new BigDecimal("0.3048"), "Feet"),
YD(UnitType.DST, (new BigDecimal("3")).multiply(FT.baseFactor), "Yards"),
IN(UnitType.DST, FT.baseFactor.divide(new BigDecimal("12"), 10, BigDecimal.ROUND_HALF_UP), "Inches");
public final UnitType unitType;
public final BigDecimal baseFactor;
public final String title;
Unit(UnitType pUnitType, BigDecimal pBaseFactor, String pTitle)
{
unitType = pUnitType;
baseFactor = pBaseFactor;
title = pTitle;
}
public BigDecimal convert(Unit pTargetUnit, BigDecimal pValue, int pScale)
{
if (pTargetUnit.unitType != unitType)
{
throw new IllegalArgumentException(getErrorMsg(this, pTargetUnit));
}
return pValue.multiply(baseFactor).divide(pTargetUnit.baseFactor, pScale, BigDecimal.ROUND_HALF_UP);
}
private static String getErrorMsg(Unit pSourceUnit, Unit pTargetUnit)
{
StringBuilder sb = new StringBuilder("Cannot convert ");
sb.append(pSourceUnit.unitType.title).append(" (").append(pSourceUnit.title).append(") to ");
sb.append(pTargetUnit.unitType.title).append(" (").append(pTargetUnit.title).append(")");
return sb.toString();
}
}
So usage might look something like this:
public class UnitConverter
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
while (true)
{
System.out.print("Convert from: ");
String sourceUnitName = scanner.next().toUpperCase();
if (sourceUnitName.equals("EXIT"))
{
break;
}
Unit sourceUnit = Unit.valueOf(sourceUnitName);
System.out.println("Source unit: " + sourceUnit.title + System.lineSeparator());
System.out.print("Convert to: ");
String targetUnitName = scanner.next().toUpperCase();
Unit targetUnit = Unit.valueOf(targetUnitName);
System.out.println("Target unit: " + targetUnit.title + System.lineSeparator());
System.out.print("Value: ");
BigDecimal sourceValue = new BigDecimal(scanner.next());
BigDecimal targetValue = sourceUnit.convert(targetUnit, sourceValue, 10);
System.out.println(sourceValue.toString() + " " + sourceUnit.title + " = " + targetValue.toString() + " " + targetUnit.title);
}
}
}
This approach converts in two steps: 1) source unit to common base unit, 2) common base unit to target unit. Without converting through a common base unit, anything other than a very limited number of units and types quickly devolves into an unmaintainable Cartesian product of all-to-all conversion factors

Know the number in a determinate position from a String - Java

I'm getting a number from an addition of Int and then put it as String. I need to know what is the first, second etc. number of the addition. For example the number is 7654, how to know that "7" is the first number? And "6" the second? etc.
String result += "\nThe result of addition"
+ String.valueOf(add_1) + "+" + String.valueOf(add_2)
"+ is" + String.valueOf(int_result);
I want to know the number of a determinate position of the String that contain the result.
The string is String.valueOf(int_result), I can use directly int_result too.
Thanks!
Just walk each character in the resulting string:
String result = String.valueOf(int_result);
for (int i=0; i< result.length(); i++) {
char c = result.charAt(i);
System.out.println("Digit " + i + " = " + c);
// And if you need this as an integer
int digit = Integer.parseInt(""+c);
}
In Java to get the character at a particular position in a string just use this
String number ="7564";
char c = number.charAt(0);
The above code will asign '5' to char variable c. You can further parse it to integer by doing this
int i = Integer.parseInt(c);

Categories

Resources