Was just wondering if I was using nested if statements to much. I've been looking around and it seems that people try to not use them. Also does the code look messy in any way? Anyways here it is:
import java.util.Arrays;
public class Main {
private String user_input = "";
private int max_score = 6;
private int sum;
private void check_scores(String scores){
user_input = scores;
String[] temp;
// Check if user_input is valid
// ^ Match with beginning of line | [0-9] Allow 0-9 | , Allow comma | + Match one or more | $ Match End of line
if (user_input.matches("^[0-9,]+$")) {
// Check if string starts with an ,
if(user_input.charAt(0) == ',') {
// If it does parse and substring to remove them
// otherwise the following regex leaves one behind
int i = 0;
while (!Character.isDigit(user_input.charAt(i))) i++;
int j = user_input.length();
user_input = user_input.substring(i,j);
}
// (.) Match any character) | \1 If it is followed by itself | + Match one or more | $1 replace by the first captured char.
user_input = user_input.replaceAll("(.)\\1+", "$1");
System.out.println(user_input);
// Split at the ',' and put each number in it's own cell in the array
temp = user_input.split(",");
System.out.println(Arrays.toString(temp));
// Check if temp is equal to max_scores
if (temp.length == max_score){
int[] ui_array = new int[temp.length];
// Parse String[] into int[]
for (int i = 0; i < temp.length; i++){
try {
ui_array[i] = Integer.parseInt(temp[i]);
} catch (NumberFormatException nfe) {}; // If triple checking isn't enough...
}
System.out.println("temp array(String): " + Arrays.toString(temp));
System.out.println("ui_array(int): " + Arrays.toString(ui_array));
// Add up all elements in ui_array
for (int j = 0 ; j < ui_array.length; j++) {
sum += ui_array[j];
}
System.out.println("Scores sum:" + sum + " Number of scores:" + ui_array.length + " Number of ends:" + ui_array.length/6);
}
else {
System.out.println("You have " + temp.length + " scores. Acceptable amount is " + max_score);
}
}
else {
System.out.println("Invalid Input. (Only #'s and ,'s allowed)");
}
}
public static void main(String[] args) {
Main main = new Main();
main.check_scores("1,M,7,10,,4,8,");
main.check_scores("1,6,7,10,,4,8,,,,,,,1,2,6,10,2,10");
main.check_scores(",,,,,,,1,2,6,10,2,10");
main.check_scores("10,2,1,5,7,1");
main.check_scores("6,2, ,,5,6,1");
}
}
I have just been wondering for a while what people think about how I go about doing things.
A few things I would note:
Personally, I think something like
public void method()
{
}
Is much more readable than
public void method() {
}
Particularly when you have methods that contain other structures. I'm sure some may not mind either, but I've never heard of someone saying the first isn't readable, while plenty have complained about the second. Sorry about the first one not being formatted correctly, but SO would not allow it.. it seems the site admins disagree with me on this one.
It is a standard to name variables such as someVariableName rather than some_variable_name. The first word should be lower case, all others capital, and they should be contiguous. The same is true for methods.
In your check_scores(String) method you have user_input = scores;, yet with your implementation there is no need for a global variable or to assign the passed variable elsewhere, so this is a waste of memory. Actually, since none of your class variables are used outside of the scope of this method, you should probably declare all of them inside the method.
I understand that this is a trivial example, but to go with the idea of object oriented programming, your Main class should probably be in a separate file and be run by creating an object in your main method in a driver class instead.
Also, as you mentioned, nesting several statements, when not necessary, can be sloppy since it will quickly become hard to read and follow.
Related
I need help checking rows, columns, and boxes for a Sudoku program. I am a high school student that needs help completing this project. If any one could provide help that would be awesome! I am currently working on checking boxes where I have a comment saying "Start Here". Thanks!
import java.util.*;
public class Run
{
Scanner scanner = new Scanner(System.in);
public static void main(String[] args)
{
char [][] board = new char [9][9];
Scanner scanner = new Scanner(System.in);
System.out.println("Welcome to Sudoku!\n");
fill(board);
printBoard(board);
inputLengthandDigits(board);
System.out.println();
printBoard(board);
}
public static void fill(char[][] arr){
for(int row = 0; row < arr.length; row++){
for(int col= 0; col< arr[row].length; col++){
arr[row][col] = '-';
}
}
}
public static void printBoard(char [][] array)
{
for(char[] row: array)
{
for(char play: row)
{
System.out.print(play+ " ");
}
System.out.println();
}
}
public static void inputLengthandDigits(char[][] array){
Scanner in = new Scanner(System.in);
for (int i = 0; i < 9; i++)
{
System.out.println("\nEnter the numbers in row " + (i+1) + ":");
String input = in.nextLine();
String numbers = "123456789-";
boolean numberscheck = false;
boolean endCheck = true;
boolean onlyOnce = true;
//Input Validation Starts Here!
//Checks if Input is only digits 0-9
do{
if(endCheck==false){
System.out.println("\nPlease input numbers only (1-9)!");
input = in.nextLine();
}
if(onlyOnce==false){
System.out.println("\nPlease input numbers only once!");
input = in.nextLine();
}
//Checks Length of User Input
while(input.length() < 9 || input.length() > 9){
System.out.println("\nPlease input 9 numbers!");
input = in.nextLine();
}
//Start Here
for(int a = 0; a<input.length()-1; a++){
for(int b= a + 1; b<input.length(); b++){
if(input.charAt(a)==input.charAt(b)){
onlyOnce = false;
}
}
}
for(int x = 0; x < input.length(); x++){
char thing = input.charAt(x);
numberscheck = false;
for(int y = 0; y < numbers.length(); y++){
char numbersn = numbers.charAt(y);
if(thing == numbersn){
numberscheck = true;
endCheck = true;
break;
}
}
if(numberscheck == false){
endCheck = false;
break;
}
}
}while(endCheck==false || onlyOnce==false);
for(int j=0; j<9; j++){
array[i][j] = input.charAt(j);
}
}
}
}
My initial response is too long for a comment. I'm not sure I have a solution to your problem, largely because you haven't actually pointed out which bit is a problem yet, but these pointers should help improve things anyway:
Please reformat your code. It is actually quite painful to look at. Spaces should be used consistently around variables, key words, brackets and operands. Opening curly braces should be on the same line as the method signature, for() loop or whatever else comes first. You have random blank lines within methods which don't separate logical sections so are just confusing. The compiler won't care about any of this, but if you can make your code look neater people will instinctively presume you care and are more likely to credit you with the ability to write decent code.
You have declared a new scanner variable three times. This is redundant and wasteful clutter. Either have a single, class-wide scanner, or (preferably), only create a scanner in a method which actually uses it and then remember to call scanner.close() once the scanner is no longer required.
inputLengthandDigits is a weird name. Is 'Lengthand' a single word, or should it be 'inputLengtHandDigits' or 'inputLengthAndDigits'? In camel case, capitalise every word except the first to make the whole easier to read. Whatever it should be, I don't understand from the name what this method does. It isn't inputting anything, it's getting inputs from someone else. Perhaps getData or populateGrid might be more explanatory.
9 appears quite a few times, with no explanation. I know where it came from, because I spend far too much time playing Sudoku, but it is a magic number and these are to be avoided at all costs. I met a magic number in the workplace once, wasted half a day trying to do what could have been a ten minute job if colleagues had recorded what the number was and where it came from. Here, just have a private static final int maxNumber = 9; statement.
A good thing: your main() method has almost no fiddly details in it. You have effectively used method calls to tell a story and describe what is happening elsewhere. This is a really, really good thing to do :)
Some of your logic tests can be tidied up a bit, e.g. !onlyOnce is the same as onlyOnce == false, and input.length() < maxNumber || input.length() > maxNumber can be simplified to input.length() != maxNumber. It's exactly the same logic, but faster to type and easier to read :)
It looks like your code under the //Start here comment is checking that you don't have any duplicate numbers. If you do get duplicate numbers, the program is still going to try and run the next bit of code before asking the user for alternative input. Is that something you want to happen, or a waste of time?
I actually burst out laughing when I saw a variable called 'thing'. Please, find a name which actually describes the purpose of this variable.
I have now run the code, and it rightly pointed out an error when I tried to key in duplicate numbers for row 4. However, it's now stuck there and keeps asking me to try again even when I put in a valid set of digits. This needs to be fixed. Look closely at which flags are triggering the request to retry. Run your code in debugging mode (you are using an IDE like IntelliJ or Eclipse, aren't you?) and deliberately enter a bad row to see the behaviour for yourself and where the logic is going wrong.
This whole method to get the row input, validate it, and then populate the array, is very big and confusing. You need to refactor it into a lot of smaller methods. Here is a suggestion to play with:
private static char[][] populateGrid(char[][] array) {
Scanner scanner = new Scanner(System.in);
for (int i = 0; i <maxNumber; i++) {
String rowData = getRowInput(scanner);
populateRow(array, rowNumber, rowData);
}
scanner.close;
return array;
}
private static String getRowInput(Scanner scanner) {
System.out.println("\nEnter the numbers in row " + (i + 1) + ":");
String input = scanner.nextLine();
while (!isValidInput(input) {
System.out.println("Please enter only the digits 1-9 in any order, with no duplicates or omissions");
input = scanner.nextLine();
}
return input;
}
private static boolean isValidInput(String input) {
if (!rightLengthOfInput(input)) {
return false;
}
if (!allUniqueDigits(input)) {
return false;
}
if (!usesCorrectCharacters(input)) {
return false;
}
return true;
}
I'll leave you to make the different input validation methods. It will largely be a case of moving your existing code, but the method names will help humans understand what each section is doing. This structure also allows you to cleanly add more validation checks, should such a thing be desired in the future.
Things to consider after all that:
Are you going to check that you have a viable Sudoku solution, or will you trust the user to put in correct data such that the columns also have each of the nine digits in them? How will you handle an invalid grid, e.g. each row is identical?
How far does this assignment want you to go? Do you need to systematically remove numbers to get a solvable puzzle rather than a completed grid? Will the assignment stop at a puzzle which can be seen in the console, or do you need a printable format, or will the user be able to play through the program? If the latter option, will this be in the console or using a graphical interface?
I appreciate that there is a lot to think about and work on here. Take it steadily, one step at a time, and keep asking questions if you need too.
System.out.println("How many teams are in this tournament?");
no_of_teams=kb.nextInt();
for(int x=1; x<=no_of_teams; x+=1)
{
System.out.println("Please enter the name of team " + x);
team=kb.next();
}
I would like to have team contain all the user inputs, so I can then use String.split later on in the program to output the team names once again.
I asked my original question on Reddit but to no avail, it went like this:
We have been asked to create a program which runs to collect data
based on a round robin soccer tournament for 'n' no. of teams. My
issue is when I must ask for all the team names at the beginning
(which I must) based on what no. of teams the user inputs of course, I
can do this with a for loop and the output is perfect:
input the code from up above here
However, as I am sure you are aware, this
basically means that team will now just be stored as whichever team
name was entered last as the for loop caused it to be overwritten.
This is a problem because later down in the program you are meant to
then output all the different team names for when they are playing
against each other but team is only storing one team name. Using
team1, team2, team3, etc. is impractical because the user can enter an
infinite amount for the number of teams. We are not allowed to use
arrays because we have not covered them yet, and by all accounts the
way I am to get around this is to use String concatenation and while
loops, but I am unsure how this would apply. Any help would be
gratefully appreciated! Thanks.
You can just append names to a String with an attached delimiter:
StringBuilder team = new StringBuilder();
for(int x=1; x<=no_of_teams; x+=1)
{
System.out.println("Please enter the name of team " + x);
//this will add a - after each name, and then you could split on the - character
team.append(kb.next()).append("-");
}
However, this is really not the best options. I would use an array to store names. The answer I gave t would return one big string, that you would have to split on the '-'.
After you got your string, you could split it by doing:
team.toString().split("-");
If you wanted to output all the team names you would do something like:
for(String aTeam : team.toString().split("-")){
System.out.println("Team Name: " + aTeam);
}
Actually, it is possible! You do not have to use arrays or lists provided by java for your convenience, even implicitly like the split method BlackHatSamurai provided in his answer. It's simple - you implement your own ArrayList! Well, ArrayList-like thing anyway.
class MyStringStringList {
private static final char delimeter = '%'; //just a character not in the input
private String internalMemory = "";
public void add(String s) {
internalMemory += s + delimeter;
}
public String getAll() {
return internalMemory;
}
public String get(int index) {
int delimeterCount = 0;
StringBuilder currentWord = new StringBuilder();
for (int j = 0; j < internalMemory.length(); j++) {
if (internalMemory.charAt(j) == delimeter) {
if (delimeterCount == index) {
return currentWord.toString();
} else {
delimeterCount++;
currentWord = new StringBuilder();
}
} else {
currentWord.append(internalMemory.charAt(j));
}
}
throw new ArrayIndexOutOfBoundsException(index);
}
}
I moved this code to a new class for clarity, but you could just paste the insides into your main class and use it from there.
Some usage:
MyStringStringList list = new MyStringStringList();
for (int x = 1; x <= no_of_teams; x += 1) {
System.out.println("Please enter the name of team " + x);
list.add(kb.next());
}
for (int i = 0; i < no_of_teams; i++) {
System.out.println("Team number " + i+1 + ": " + list.get(i));
}
Do note, that only a crazy person would do that. Inefficient, probably buggy, incomplete feature-wise... But if you are not mistaken, and you were in fact prohibited from using the built-in array or collections that could be the "Your rules are stupid" solution your teacher deserves.
I am very new to Java and as a starter I have been offered to try this at home.
Write a program that will find out number of occurences of a smaller string in a bigger string as a part of it as well as an individual word.
For example,
Bigger string = "I AM IN AMSTERDAM", smaller string = "AM".
Output: As part of string: 3, as a part of word: 1.
While I did nail the second part (as a part of word), and even had my go at the first one (searching for the word as a part of the string), I just don't seem to figure out how to crack the first part. It keeps on displaying 1 for me with the example input, where it should be 3.
I have definitely made an error- I'll be really grateful if you could point out the error and rectify it. As a request, I am curious learner- so if possible (at your will)- please provide an explanation as to why so.
import java.util.Scanner;
public class Program {
static Scanner sc = new Scanner(System.in);
static String search,searchstring;
static int n;
void input(){
System.out.println("What do you want to do?"); System.out.println("1.
Search as part of string?");
System.out.println("2. Search as part of word?");
int n = sc.nextInt();
System.out.println("Enter the main string"); searchstring =
sc.nextLine();
sc.nextLine(); //Clear buffer
System.out.println("Enter the search string"); search = sc.nextLine();
}
static int asPartOfWord(String main,String search){
int count = 0;
char c; String w = "";
for (int i = 0; i<main.length();i++){
c = main.charAt(i);
if (!(c==' ')){
w += c;
}
else {
if (w.equals(search)){
count++;
}
w = ""; // Flush old value of w
}
}
return count;
}
static int asPartOfString(String main,String search){
int count = 0;
char c; String w = ""; //Stores the word
for (int i = 0; i<main.length();i++){
c = main.charAt(i);
if (!(c==' ')){
w += c;
}
else {
if (w.length()==search.length()){
if (w.equals(search)){
count++;
}
}
w = ""; // Replace with new value, no string
}
}
return count;
}
public static void main(String[] args){
Program a = new Program();
a.input();
switch(n){
case 1: System.out.println("Total occurences: " +
asPartOfString(searchstring,search));
case 2: System.out.println("Total occurences: " +
asPartOfWord(searchstring,search));
default: System.out.println("ERROR: No valid number entered");
}
}
}
EDIT: I will be using the loop structure.
A simpler way would be to use regular expressions (that probably defeats the idea of writing it yourself, although learning regexes is a good idea because they are very powerful: as you can see the core of my code is 4 lines long in the countMatches method).
public static void main(String... args) {
String bigger = "I AM IN AMSTERDAM";
String smaller = "AM";
System.out.println("Output: As part of string: " + countMatches(bigger, smaller) +
", as a part of word: " + countMatches(bigger, "\\b" + smaller + "\\b"));
}
private static int countMatches(String in, String regex) {
Matcher m = Pattern.compile(regex).matcher(in);
int count = 0;
while (m.find()) count++;
return count;
}
How does it work?
we create a Matcher that will find a specific pattern in your string, and then iterate to find the next match until there is none left and increment a counter
the patterns themselves: "AM" will find any occurrence of AM in the string, in any position. "\\bAM\\b" will only match whole words (\\b is a word delimiter).
That may not be what you were looking for but I thought it'd be interesting to see another approach. An technically, I am using a loop :-)
Although writing your own code with lots of loops to work things out may execute faster (debatable), it's better to use the JDK if you can, because there's less code to write, less debugging and you can focus on the high-level stuff instead of the low level implementation of character iteration and comparison.
It so happens, the tools you need to solve this already exist, and although using them requires knowledge you don't have, they are elegant to the point of being a single line of code for each method.
Here's how I would solve it:
static int asPartOfString(String main,String search){
return main.split(search, -1).length - 1;
}
static int asPartOfWord(String main,String search){
return main.split("\\b" + search + "\\b", -1).length - 1
}
See live demo of this code running with your sample input, which (probably deliberately) contains an edge case (see below).
Performance? Probably a few microseconds - fast enough. But the real benefit is there is so little code that it's completely clear what's going on, and almost nothing to get wrong or that needs debugging.
The stuff you need to know to use this solution:
regex term for "word boundary" is \b
split() takes a regex as its search term
the 2nd parameter of split() controls behaviour at the end of the string: a negative number means "retain blanks at end of split", which handle the edge case of the main string ending with the smaller string. Without the -1, a call to split would throw away the trailing blank in this edge case.
You could use Regular Expressions, try ".*<target string>.*" (Replace target string with what you are searching for.
Have a look at the Java Doc for "Patterns & Regular Expressions"
To search for the occurrences in a string this could be helpful.
Matcher matcher = Pattern.compile(".*AM.*").matcher("I AM IN AMSTERDAM")
int count = 0;
while (matcher.find()) {
count++;
}
Here's an alternative (and much shorter) way to get it to work using Pattern and Matcher,or more commonly known as regex.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CountOccurances {
public static void main(String[] args) {
String main = "I AM IN AMSTERDAM";
String search = "AM";
System.out.printf("As part of string: %d%n",
asPartOfString(main, search));
System.out.printf("As part of word: %d%n",
asPartOfWord(main, search));
}
private static int asPartOfString(String main, String search) {
Matcher m = Pattern.compile(search).matcher(main);
int count = 0;
while (m.find()) {
count++;
}
return count;
}
private static int asPartOfWord(String main, String search) {
// \b - A word boundary
return asPartOfString(main, "\\b" + search + "\\b");
}
}
Output:
As part of string: 3
As part of word: 1
For the first part of your Exercise this should work:
static int asPartOfWord(String main, String search) {
int count = 0;
while(main.length() >= search.length()) { // while String main is at least as long as String search
if (main.substring(0,search.length()).equals(search)) { // if String main from index 0 until exclusively search.length() equals the String search, count is incremented;
count++;
}
main = main.substring(1); // String main is shortened by cutting off the first character
}
return count;
You may think about the way you name variables:
static String search,searchstring;
static int n;
While search and searchstring will tell us what is meant, you should write the first word in lower case, every word that follows should be written with the first letter in upper case. This improves readability.
static int n won't give you much of a clue what it is used for if you read your code again after a few days, you might use something more meaningful here.
static String search, searchString;
static int command;
I have got one string array each in 2 different classes in java.
When I enter a value from any of the arrays, I want to get the class to which that array value belongs.
So how do I get to know the class just by entering an array value?
eg:
import java.io.*;
class Car {
public static void main(String args[]) throws Exception {
System.out.println("The parts of a car are as follows");
for (int i = 1; i <= 5; i++) {
System.out.println(i + str[i]);
}
for (int j = 1; j <= 5; j++) {
System.out.println(j + ch[j]);
}
DataInputStream dis = new DataInputStream(System.in);
System.out.println("Choose and enter any part name to group it under following categories:" + "\n" + "Engine" + "\t" + "\t" + "Bonet");
String part = dis.readLine();
if (part == ch[]) {
System.out.println("Your choosen part is " + part + " and it comes under Engine category");
} else {
System.out.println("Your choosen part is " + part + " and it comes under Bonet category");
}
}
}
class Engine {
String ch[] = {"asd", "fgh"};
}
class Bonet {
String str[] = {"qwe", "rty"};
}
now when a user enters asd i want to display to which class it belongs
I wont give you full code because I believe that creating it yourself will be better for you. Instead here are few facts that you need to take into consideration:
To have access to array stored in other class you would aether have to create instance of that class
Engine engine = new Engine();
engine.ch[0];
or in your case you should probably make your array static
class Engine {
static String ch[] = { "asd", "fgh" };
}
and access it via class name Engine.ch[0]
Arrays are indexed from 0 to arraySize-1
To get size of array you can use its filed length and later use it like
for(int i=0; i<Bonet.str.length; i++){
System.out.println(i+Bonet.str[i]);
}
readLine() from DataInputStream is depracated. Instead you can use nextLine from java.util.Scanner
Scanner scanner = new Scanner(System.in);
//...
String part = scanner.nextLine();
To check if some object is stored in array you will have to iterate over all elements of that array and compare them with your object. Also remember that to compare String objects you should use equals method like part.equals(otherString).
But to make it with less code you can wrap your array into List and use its contains(Object o) method. To wrap array into list you can use asList method from java.util.Arrays class.
if(Arrays.asList(Engine.ch).contains(part)){...
Bare minimum changes to get this to work are as below. Key points:
the contents of Engine and bonet belong to instances of those classes not to car
arrays of size 5 have indicies 0,1,2,3,4, not 1,2,3,4,5
Where going through an array in a loop do not hard code the array size, use .length instead
import java.io.*;
public class Car {
public static void main(String args[]) throws Exception {
System.out.println("The parts of a car are as follows");
Engine engine=new Engine(); //we must create any components we have
Bonet bonet=new Bonet(); //we must create any components we have
for (int i = 0; i <bonet.str.length; i++) {
System.out.println(i +":"+ bonet.str[i]);
}
for (int j = 0; j < engine.ch.length; j++) {
System.out.println(j +":"+ engine.ch[j]);
}
DataInputStream dis = new DataInputStream(System.in);
System.out.println("Choose and enter any part name to group it under following categories:" + "\n" + "Engine" + "\t" + "\t" + "Bonet");
String part = dis.readLine();
boolean isInEngine=false; //assume isn't in engine, try to prove otherwise
for(int i=0;i<engine.ch.length;i++){
if (engine.ch[i].equals(part)){
isInEngine=true;
}
}
if (isInEngine==true) {
System.out.println("Your choosen part is " + part + " and it comes under Engine category");
} else {
System.out.println("Your choosen part is " + part + " and it comes under Bonet category");
}
}
}
class Engine {
String ch[] = {"asd", "fgh"};
}
class Bonet {
String str[] = {"qwe", "rty"};
}
Note; this is far from an optimal solution, ideas to consider:
It is bad practice to refer to the insides of annother class like this, it would be better for each class (engine and bonnet) to include a method .testPart(String string) that would return a boolean as to if it contains the part
The code assumes that if its not in engine it must be in bonet, what if the user enters something crazy
An array list (rather than an array) would allow us to use .contains(String string) rather than using a loop to look though the array
The DataInputStream is no longer supported (note that it appears with a strike through in most IDEs), consider using Scanner scanner = new Scanner(System.in); and then use scanner.nextLine(); to get the line
What if you add a third type of component, better to hold all your parts in an array, then you can easily add annother. An interface (or abstract base class) would promise that all the array contents held the .testPart(String string) and a getName() method; the array/arraylist would be declared as containing the interface/abstract-base-class
You never actually create an instance of Car, which you would do by Car car=new Car();, the Car class could then have methods like car.printOptions(); and car.testComponent(String testString);. The way you're doing it (one long main function) will work fine for small programs, but the bigger your program becomes the harder it will be to work like this. In this case the engine and bonet would be fields of the car class (which logically makes a lot more sense than them just 'hanging around')
I am working on a class assignment this morning and I want to try and solve a problem I have noticed in all of my team mates programs so far; the fact that spaces in an int/float/double cause Java to freak out.
To solve this issue I had a very crazy idea but it does work under certain circumstances. However the problem is that is does not always work and I cannot figure out why. Here is my "main" method:
import java.util.Scanner; //needed for scanner class
public class Test2
{
public static void main(String[] args)
{
BugChecking bc = new BugChecking();
String i;
double i2 = 0;
Scanner in = new Scanner(System.in);
System.out.println("Please enter a positive integer");
while (i2 <= 0.0)
{
i = in.nextLine();
i = bc.deleteSpaces(i);
//cast back to float
i2 = Double.parseDouble(i);
if (i2 <= 0.0)
{
System.out.println("Please enter a number greater than 0.");
}
}
in.close();
System.out.println(i2);
}
}
So here is the class, note that I am working with floats but I made it so that it can be used for any type so long as it can be cast to a string:
public class BugChecking
{
BugChecking()
{
}
public String deleteSpaces(String s)
{
//convert string into a char array
char[] cArray = s.toCharArray();
//now use for loop to find and remove spaces
for (i3 = 0; i3 < cArray.length; i3++)
{
if ((Character.isWhitespace(cArray[i3])) && (i3 != cArray.length)) //If current element contains a space remove it via overwrite
{
for (i4 = i3; i4 < cArray.length-1;i4++)
{
//move array elements over by one element
storage1 = cArray[i4+1];
cArray[i4] = storage1;
}
}
}
s = new String(cArray);
return s;
}
int i3; //for iteration
int i4; //for iteration
char storage1; //for storage
}
Now, the goal is to remove spaces from the array in order to fix the problem stated at the beginning of the post and from what I can tell this code should achieve that and it does, but only when the first character of an input is the space.
For example, if I input " 2.0332" the output is "2.0332".
However if I input "2.03 445 " the output is "2.03" and the rest gets lost somewhere.
This second example is what I am trying to figure out how to fix.
EDIT:
David's suggestion below was able to fix the problem. Bypassed sending an int. Send it directly as a string then convert (I always heard this described as casting) to desired variable type. Corrected code put in place above in the Main method.
A little side note, if you plan on using this even though replace is much easier, be sure to add an && check to the if statement in deleteSpaces to make sure that the if statement only executes if you are not on the final array element of cArray. If you pass the last element value via i3 to the next for loop which sets i4 to the value of i3 it will trigger an OutOfBounds error I think since it will only check up to the last element - 1.
If you'd like to get rid of all white spaces inbetween a String use replaceAll(String regex,String replacement) or replace(char oldChar, char newChar):
String sBefore = "2.03 445 ";
String sAfter = sBefore.replaceAll("\\s+", "");//replace white space and tabs
//String sAfter = sBefore.replace(' ', '');//replace white space only
double i = 0;
try {
i = Double.parseDouble(sAfter);//parse to integer
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
System.out.println(i);//2.03445
UPDATE:
Looking at your code snippet the problem might be that you read it directly as a float/int/double (thus entering a whitespace stops the nextFloat()) rather read the input as a String using nextLine(), delete the white spaces then attempt to convert it to the appropriate format.
This seems to work fine for me:
public static void main(String[] args) {
//bugChecking bc = new bugChecking();
float i = 0.0f;
String tmp = "";
Scanner in = new Scanner(System.in);
System.out.println("Please enter a positive integer");
while (true) {
tmp = in.nextLine();//read line
tmp = tmp.replaceAll("\\s+", "");//get rid of spaces
if (tmp.isEmpty()) {//wrong input
System.err.println("Please enter a number greater than 0.");
} else {//correct input
try{//attempt to convert sring to float
i = new Float(tmp);
}catch(NumberFormatException nfe) {
System.err.println(nfe.getMessage());
}
System.out.println(i);
break;//got correct input halt loop
}
}
in.close();
}
EDIT:
as a side note please start all class names with a capital letter i.e bugChecking class should be BugChecking the same applies for test2 class it should be Test2
String objects have methods on them that allow you to do this kind of thing. The one you want in particular is String.replace. This pretty much does what you're trying to do for you.
String input = " 2.03 445 ";
input = input.replace(" ", ""); // "2.03445"
You could also use regular expressions to replace more than just spaces. For example, to get rid of everything that isn't a digit or a period:
String input = "123,232 . 03 445 ";
input = input.replaceAll("[^\\d.]", ""); // "123232.03445"
This will replace any non-digit, non-period character so that you're left with only those characters in the input. See the javadocs for Pattern to learn a bit about regular expressions, or search for one of the many tutorials available online.
Edit: One other remark, String.trim will remove all whitespace from the beginning and end of your string to turn " 2.0332" into "2.0332":
String input = " 2.0332 ";
input = input.trim(); // "2.0332"
Edit 2: With your update, I see the problem now. Scanner.nextFloat is what's breaking on the space. If you change your code to use Scanner.nextLine like so:
while (i <= 0) {
String input = in.nextLine();
input = input.replaceAll("[^\\d.]", "");
float i = Float.parseFloat(input);
if (i <= 0.0f) {
System.out.println("Please enter a number greater than 0.");
}
System.out.println(i);
}
That code will properly accept you entering things like "123,232 . 03 445". Use any of the solutions in place of my replaceAll and it will work.
Scanner.nextFloat will split your input automatically based on whitespace. Scanner can take a delimiter when you construct it (for example, new Scanner(System.in, ",./ ") will delimit on ,, ., /, and )" The default constructor, new Scanner(System.in), automatically delimits based on whitespace.
I guess you're using the first argument from you main method. If you main method looks somehow like this:
public static void main(String[] args){
System.out.println(deleteSpaces(args[0]);
}
Your problem is, that spaces separate the arguments that get handed to your main method. So running you class like this:
java MyNumberConverter 22.2 33
The first argument arg[0] is "22.2" and the second arg[1] "33"
But like other have suggested, String.replace is a better way of doing this anyway.