Fill two-dimensional array with Chars from String Input - java

I'm making a basic game of Tic Tac Toe, accepting player input in the form of a string (i.e. a2). The first char is made into an int called row depending on the letter, the same being said for the second char into col (for array grid[row][col]). I have a block of code that throws a custom exception in the event that the first char isn't a, b, or c, and if the second char isn't 1, 2, or 3:
if(input == null) {
throw new NullInputException();
}
else if(input.length() != 2) {
throw new InvalidInputException();
}
else if(!(input.substring(0,1).equalsIgnoreCase("a") &&
input.substring(0,1).equalsIgnoreCase("b") &&
input.substring(0,1).equalsIgnoreCase("c") ||
input.substring(1).equals("1") &&
input.substring(1).equals("2") &&
input.substring(1).equals("3"))) {
throw new InvalidInputException();
}
The problem is, this code throws an error even when the input is valid, and I don't know why. I've tried using .charAt() as opposed to .substring(), as well as messed around with my conditional statements. My question is: How do I fix this so that it accepts valid input?
Other questions that just don't help:
fill two dimensional array with parts of a string;
fill a 2d array with chars of 2 string

Sometimes it is better to write a series of simpler tests which are easier to read and verify
row = input.substring(0,1).toUpperCase();
col = input.substring(1);
boolean validRow = (row.equals("A") ||
row.equals("B") ||
row.equals("C"));
boolean validCol =
(col.equals("1") ||
col.equals("2") ||
col.equals("3"));
if(!(validRow && validCol)) {

You AND two conditions:
input.substring(0,1).equalsIgnoreCase("a") &&
input.substring(0,1).equalsIgnoreCase("b")
Both cannot be true in the same time. That is why the result is always false and an exception is thrown.
What you really want is:
String first = input.substring(0,1);
String second = input.substring(1);
if (!((first.equalsIgnoreCase("a") ||
first.equalsIgnoreCase("b") ||
first.equalsIgnoreCase("c")) &&
(second.equals("1") ||
second.equals("2") ||
second.equals("3"))) {
throw new InvalidInputException();
}
Small edit for Neil...

Related

Result not null in my code, if "sorIndex" is invalid

I would need some guidance from You, at the moment I have this challenge with this exercise:
The aim of this code would be, to split a String(szoveg) to rows and give back the result row(sorIndex) as a result, if sorIndex is in the range of the String Array(String szoveg is splitted into this array).
If the requested number of the row is not in the valid range(0-length of the array) it should give back a null value. The IDE for testing the excercise returns a mistake, which is the following(Hungarian + English):
"A getSor() metódus nem működik jól. Nem létező sorIndexet megadva
null-t kell visszaadjon a metódus. A konstruktor paramétere:"
"The getSor() method is not working properly. Given a not valid
sorIndex, the method should return null. The parameter of the
constructor:" -there is nothing after this part in the IDE.
public String getSor(int sorIndex) {
int sorok= szoveg.split("\n").length;
String sor;
if (sorIndex >= 0 && sorIndex <= sorok) {
String[] stringTomb = new String[sorok];
stringTomb = szoveg.split("\n");
sor = stringTomb[sorIndex];
} else {
sor = null;
}
return sor;
}
Does anyone have any idea where did I made the mistake?
Thank you!
The error message tells you that if an invalid sorIndex is passed, then a null should be returned. This means that instead of getting into the else branch in your logic, it goes into the if in an invalid manner.
The reason of this is that arrays are 0-indexed, so you should compare against rows (sorok) in a srict manner:
if (sorIndex >= 0 && sorIndex < sorok) {
That should fix the issue. However, your code computes split several times and is superfluous. I would refactor it to:
public String getSor(int sorIndex) {
if (szoveg == null) return null; // Handling the case when szöveg is not properly initialized
String stringTomb[] = szoveg.split("\n");
return ((sorIndex >= 0) && (sorIndex < szoveg.length)) ? stringTomb[sorIndex] : null;
}
I used the ternary operator to make this more readable, concise and short.

Dealing with StringIndexOutOfBoundsException in if statement Java

I have a program that gets an input from the console. It checks what the input is then using 'if's it decides what to do. One section test to see what the first four letters of the string are, to see if it needs to deal with it, but not all of the strings are always 4 or more letters long. This means that if you type in something that is less than 4 letters long, it encounters an error, and quits. I can't put that section at the end, because at the end there is an else, which if the command is unknown, is called and something happens. Is there a way I can stop the error from occurring?
My code is:
if(input.equals("help")){
int commandsSize = commands.size();
for(int i = 0; i < commandsSize; i++) {
String value = commands.get(i);
System.out.println(value);
} else if((input.substring(0, 4)).equals("open")) {
...
}
You can check the size of the string the user inputs,
if (input.length() != 4) {
System.out.println("You must enter valid input");
// Probably do something here.
}
if(input.equals("help")){
int commandsSize = commands.size();
for(int i = 0; i < commandsSize; i++) {
String value = commands.get(i);
System.out.println(value);
}
} else if((input.substring(0, 3)).equals("open")) {
...
}
Your code is erroring out on the substring method because if the string is less than 4 characters, the method is going outside the bounds of the string (or the char array that makes up the string). You will also want to check that you string is not null before calling methods on the string object.
To have the same flow as you currently have, but to protect your code against the substring error and not being null, you can do this:
if(input != null && input.equals("help")){
//some code
} else if((input != null && input.length() >= 4) && (input.substring(0, 4)).equals("open")) {
//some code
}

Constructor throwing runtime exception

I have a constructor that takes in a string as a parameter. I want to throw a runtime exception everytime the string that is passed into the constructor contains anything that is not either "A", "C", "G", or "T". Currently this is what my code looks like:
public DNAStrandNovice(String strand) {
passedStrand = strand;
if (passedStrand.contains("a") || passedStrand.contains("c")
|| passedStrand.contains("g") || passedStrand.contains("t")) {
throw new RuntimeException("Illegal DNA strand");
} else if (passedStrand.contains("1") || passedStrand.contains("2")
|| passedStrand.contains("3") || passedStrand.contains("4")
|| passedStrand.contains("5") || passedStrand.contains("6")
|| passedStrand.contains("7") || passedStrand.contains("8")
|| passedStrand.contains("9") || passedStrand.contains("0")) {
throw new RuntimeException("Illegal DNA Strand");
} else if (passedStrand.contains(",") || passedStrand.contains(".")
|| passedStrand.contains("?") || passedStrand.contains("/")
|| passedStrand.contains("<") || passedStrand.contains(">")) {
throw new RuntimeException("Illegal DNA Strand");
}
}
I feel like this could be implemented in a much more concise way, but I don't know how. Right now I'm just checking for every character that is not the capital letters "A", "C", "G", or "T" and throwing a run time exception but I feel like it's too tedious and bad programming style. Anyone have any ideas?
Check negatively, instead of positively.
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != 'A' && str.charAt(i) != 'C'
&& str.charAt(i) != 'G' && str.charAt(i) != 'T') {
throw new IllegalArgumentException("Bad character " + str.charAt(i));
}
}
...or, even shorter,
for (int i = 0; i < str.length(); i++) {
if (!"ACGT".contains(str.charAt(i))) {
throw new IllegalArgumentException("Bad character " + str.charAt(i));
}
}
You can achieve this using regex (regular expressions):
public DNAStrandNovice(String strand) {
if (!strand.matches("[ACGT]+")) { //or [ACGT] <-- see note below
throw new RuntimeException("Illegal DNA strand");
}
passedStrand = strand;
}
The regular expression [ACGT]+ means the string must have one or more characters, and each of them must be one of A, C, G or T. The ! in front of strand.matches reverses the boolean value returned by matches, essentially meaning if the string does not match the regex, then throw RuntimeException.
Note: If you need the string to have exactly one character, use the regex [ACGT]. If you need to allow spaces, you can use [ACGT ]+ (then trim and check for empty) or [ACGT][ACGT ]+ (which ensures the first character is not a space).
You can even do much more complex and powerful regex checks such as patterns that should contain exactly four characters repeated with spaces in between (example ATCG TACG) or even where only certain characters appear in certain places, like only A and C can appear as first two characters, and only G and T can appear following it (example ACTG is correct while AGTC is wrong). I will leave all that as an exercise.
Recommend against using an exception. Define an Enum and pass that.
public enum DnaCode { A, C, G, T }
...
public DNAStrandNovice(List<DnaCode> strand) {
...
}
Or make it a DnaCode[] if you prefer. You can control the input and avoid dealing with interrupted control flow. Exceptions are rather expensive to throw and are not really intended for use as a method of flow control.
You can make the code slightly more efficient by manaully looping through the characters and checking for the letters either with ifs or a Set.
But honestly, unless performance is a problem, it's good how it. Very obvious and easy to maintain.
I was going to jump in with a possibility...
public boolean validateLetter(String letter){
HashMap<String, String> dna = new HashMap<String, String>();
dna.put("A", "A");
dna.put("C", "C");
dna.put("G", "G");
dna.put("T", "T");
if(dna.get(letter) == null){
System.out.println("fail");
return false;
} else {
return true;
}
}
I would also not put that code in the constructor, rather put it in its own method and call from the constructor.
public DNAStrandNovice(String strand){
if(strand.matches("^[A-Za-z]*[0-9]+[A-Za-z]*$") || strand.matches("^[a-zA-Z]*[^a-zA-Z0-9][a-zA-Z]*$") || strand.matches("^[A-Za-z]*[acgt]+[A-Za-z]*$")){
throw new RuntimeException("Illegal DNA strand");
}
}

Removing Characters within a string-Java

I keep getting an error with removing a character from within a string. I have tried everything that i could find on this site and nothing has worked. This is NOT a help post. Rather maybe an answer that explains why this shows up and how to fix it in case someone else encounters this issue. Without further a due, here is my code:
public JTextField Clean()
{
String Cleaner = TopField.getText();
Cleaner=Cleaner.toLowerCase();
int Length = Cleaner.length();
StringBuilder Combiner = new StringBuilder(Cleaner);
for (int x=0;x+1<Length;x++)
{
char c = Cleaner.charAt(x);
char c1 = Cleaner.charAt(x+1);
if(c==' ' && c1==' ')
{
Combiner.deleteCharAt(x);
Cleaner=Combiner.toString();
}
if(c!='a' && c=='b' && c!='c' && c!='d' && c!='f' && c!='g' && c!='h' && c!='i' && c!='j' && c!='k' && c!='l' && c!='m' && c!='n' && c!='o' && c!='p' && c!='q' && c!='r' && c!='s' && c!='t' && c!='u' && c!='v' && c!='w' && c!='x' && c!='y' && c!='z' && c!=' ')
{Combiner.deleteCharAt(x);
Cleaner=Combiner.toString();}
}
TopField.setText(Cleaner);
return TopField;
}
I receive an error that states that My value is out of bounds by the length of the string that i input. Please note that this is a method inside a class that i created that removes any character that is not an alphabet or space.
Thanks in advance
As you remove characters, Cleaner becomes shorter, so you're likely to reach a point where x is too large.
I would suggest a different approach using regular expressions:
string cleaned = TopField.getText().toLowerCase().replaceAll("[^a-z ]", "");
There are a number of things that pop out at me.
Your basing your loop on a fixed value (Length), but where the actual length of the String can decrease...
You are potentially removing 2 characters per loop (there are two deleteCharAt calls)
The loop doesn't take into account the shrinking size of the String. For example. x == 1, you remove the character at x, you increment x by 1 (x == 2), effectively skipping a character (the character at position 2 is now at position 1
Your if statement is unnecessarily long. In fact, depending on your needs, you could use Character.isDigit or Character.isLetter and Character.isWhiteSpace
String Cleaner = TopField.getText();
Cleaner = Cleaner.toLowerCase();
StringBuilder Combiner = new StringBuilder(Cleaner);
int x =0;
while (x < Combiner.length()) {
char c = Combiner.charAt(x);
if (c >= 'a' && c <= 'z' || c == ' ') {
Combiner.deleteCharAt(x);
} else {
x++;
}
}
From the looks of your code, you appear to wanting to filter a JTextField so it will only allow numeric values. It would be much better to use something like a JSpinner, JFormattedTextField or DocumentFilter and ensure the correctness of the data as it's entered...IMHO
I used a isDigit() function and found the output as incorrect. Look at the code I tested and found problem with the output. Any one explain.
public static void main(String[] args) {
// TODO Auto-generated method stub
String temp="you got 211111 out of 211111?";
StringBuilder cleaner=new StringBuilder(temp);
for(int i=0;i<cleaner.length();i++)
{
char c=cleaner.charAt(i);
if(Character.isDigit(c))
{
cleaner.deleteCharAt(i);
}
}
System.out.println(cleaner);
I am getting output as : you got 111 out of 111?
it is not removing some digits.
Also found that no function called replaceAll() is there in Java.

I cant find what causes the Exception

I am a java noob as well as very new to this site so please bear with me here. If I do something wrong in posting this please let me know and I apologize in advance for anything I do happen to do or any bad grammar.
I need to write a custom CSV parser in java that does not separate commas inside quotations. I cannot use anything related to the CSV class.
1,2,3,4 -> 1 2 3 4
a,"b,c",d -> a b,c d
No matter what i try i always get an exception
import java.io.*;
import java.util.*;
public class csv
{
public static void main(String[] args)
{
File file = new File("csv.test");
BufferedReader buf = null;
try
{
buf = new BufferedReader(new FileReader(file));
String str;
while ((str = buf.readLine()) != null)
{
String[] values = null; // array for saving each split substr
int c1 = 0; // counter for current position in string
int c2 = 0; // counter for next space in array to save substr
int c3 = 0; // location of last comma or quotation for substring creation
int i = 0; // counter used later for printing
while (c1 <= str.length())
{
char x = str.charAt(c1);
String s = Character.toString(x);
if (c1 == str.length())
{
values[c2] = str.substring(c3, (c1 - 1));
}
else if (s == ",")
{
values[c2] = str.substring(c3, (c1 - 1));
c1++;
c2++;
c3++;
}
else if (s == "\"")
{
c1++;
c3 = c1;
while (s != "\"")
c1++;
values[c2] = str.substring(c3, (c1 - 1));
c1 = c1 + 2;
c2++;
c3 = c1;
}
else
{
c1++;
}
while (i < values.length)
System.out.println("\"" + values[i] + "\"");
}
}
}
catch (Exception e)
{
System.out.println("Error locating test file");
}
}
}
I have tried cutting out all logic and testing if it is file io related. that reads fine so im down to it being logic related. I looked it over and cannot find anything wrong with it. I even had a friend look it through and said it looked fine. Where is the exception thrown?
You are not initializing your values in this line String[] values = null; hence it will fail when you use it i.e. at list values[c2] = str.substring(c3, (c1 - 1));.
To resolve the issue, please initialize the values array with proper length e.g. String[] values = new String[SIZE];. Probably you need to use str.length() as SIZE of the array.
Also in your comparison else if (s == ","), you are comparing String using ==, which is incorrect. Instead, you can use x itself as else if (x == ',').
Edit: Your condition below will make c1 in increment indefinitely as you are not changing the value of str(x after correction as advised) anywhere.
Old condition:
while (s != "\"")
c1++;
After change as advised(still wrong as x is not changing within the while loop):
while (x != '"')
c1++;
Please correct the loop logic.
Not related to the concrete problem but instead of s == ",", you should do ",".equals(s), similar for other string equality checks.
This is not the cause of your exception, but it is obviously incorrect nonetheless:
while (s != "\"")
c1++;
It is incorrect for two reasons:
Since the c1++ doesn't alter the loop condition, this will loop for ever.
You are using == / != to compare strings when you should be using equals(...). You appear to have made this mistake in other places too.
To find out what is causing the exception, the first thing you should do is to print out the stacktrace. Add e.printStackTrace(); to the catch block.
Or better still, change it to just catch IOException. Catching Exception is a bad idea ... unless you are going to log / output the full stacktrace.

Categories