Java Scanner delimiter on values of nextLine - java

I have a file in .dat format. Here is a sample
||= (N ) =|| 1|| 0.938 || --- || 0.5 || (****)|| 0.5 || 0 || 0 || 0 || 0.700 || (p)=2212, (n)=2112 ||
||= (\Delta ) =|| 2|| 1.232 || 0.118 || 1.5 || (****)|| 1.5 || 0 || 0 || 3 || 1.076 || (\Delta^{++})=2224, (\Delta^+)=2214, (\Delta^0)=2114, (\Delta^-)=1114 ||
||= (P_{11}(1440) ) =|| 3|| 1.462 || 0.391 || 0.5 || (****)|| 0.5 || 0 || 0 || 3 || 1.076 || 202212, 202112 ||
||= (S_{11}(1535) ) =|| 4|| 1.534 || 0.151 || 0.5 || ( ***)|| 0.5 || 0 || 0 || 3 || 1.076 || 102212, 102112 ||
I am trying to use Scanner to read this file and delimit the line by the "||" and then send into and ArrayList for future processing. Here is a sample of my code where I use the delimiter
String file = "data.dat";
Scanner s = null;
try {
s = new Scanner(new File(file)).useDelimiter("\\|\\|"); //here is the use of my delimiter
ArrayList<String> list = new ArrayList<String>();
while (s.hasNextLine()) { //notice I am using hasNextLine because each line must be unique to create the HashMap
list.add(s.nextLine());
}
s.close();
for (String string : list) { //Lets print out the values of the list
System.out.println(string);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But my output still has values of the delimiter, i.e. here is the output:
||= (N ) =|| 1|| 0.938 || --- || 0.5 || (****)|| 0.5 || 0 || 0 || 0 || 0.700 || (p)=2212, (n)=2112 ||
||= (\Delta ) =|| 2|| 1.232 || 0.118 || 1.5 || (****)|| 1.5 || 0 || 0 || 3 || 1.076 || (\Delta^{++})=2224, (\Delta^+)=2214, (\Delta^0)=2114, (\Delta^-)=1114 ||
||= (P_{11}(1440) ) =|| 3|| 1.462 || 0.391 || 0.5 || (****)|| 0.5 || 0 || 0 || 3 || 1.076 || 202212, 202112 ||
||= (S_{11}(1535) ) =|| 4|| 1.534 || 0.151 || 0.5 || ( ***)|| 0.5 || 0 || 0 || 3 || 1.076 || 102212, 102112 ||
I have searched and found no answer that helped. I am also seeing a warning about a "Resource leak: '' is never closed" with the line
s = new Scanner(new File(file)).useDelimiter("\\|\\|");
which disappears if the line is broken into
s = new Scanner(new File(file));
s.useDelimiter("\\|\\|");
Any help is appreciated.

You don't need to use backslash escape. instead of \\|\\| as your delimiter, just split the string after it's read from the file.
String file = "data.dat";
Scanner s = null;
try {
s = new Scanner(new File(file)); //no more delimiter. It's not needed
ArrayList<String> list = new ArrayList<String>();
while (s.hasNextLine()) {
String[] strings = s.nextLine().split("[||]");
for (int i = 0; i < strings.length; i++) {
list.add(strings[i]);
}
}
s.close();
for (String string : list) { //Lets print out the values of the list
System.out.println(string);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This should fix it.

You can just read the line without delimiter, and then replace || with whatever you want using replace method.
Code
public static void main (String[] args) throws java.lang.Exception{
Scanner s = new Scanner(System.in);
ArrayList<String> list = new ArrayList<String>();
while (s.hasNextLine()) {
String newLine = s.nextLine().replace("||","");
list.add(newLine);
// or just like this
//list.add(s.nextLine().replace("||",""));
}
s.close();
for (String string : list) {
System.out.println(string);
}
}
Check the output here.

Related

Java && || operators precedent

I need help with one if condition in java code
public class Main
{
public static void main(String[] args) {
String sHeaderStatus = "1";
Boolean hasButton = false;
Boolean editableLineStatus =true;
String sFrom = "REQ";
int canChangeSupplier = 0;
if ((sHeaderStatus.equals("1") || canChangeSupplier == 1 &&
(sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton && editableLineStatus && !sHeaderStatus.equals("85")) || sFrom.equals("APPROVAL")) {
String valdiaton ="true11";
System.out.println(valdiaton);
}
}
result is true11
public class Main
{
public static void main(String[] args) {
String sHeaderStatus = "1";
Boolean hasButton = false;
Boolean editableLineStatus =false; //changed this one to false
String sFrom = "REQ";
int canChangeSupplier = 0;
if ((sHeaderStatus.equals("1") || canChangeSupplier == 1 &&
(sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton && editableLineStatus && !sHeaderStatus.equals("85")) || sFrom.equals("APPROVAL")) {
String valdiaton ="true11";
System.out.println(valdiaton);
}
}
result is still true11
I am not able to understood the issue.
Per my understanding...
sHeaderStatus.equals("1") || canChangeSupplier == 1 // gave true
(sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton // gave false
become true && false && true && true
Similarly second code would become true && false && false &&true
Am not sure how this become true and below line printed.
&& happens before ||
Write the code like this
if (
(
sHeaderStatus.equals("1")
|| canChangeSupplier == 1 && (sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton && editableLineStatus && !sHeaderStatus.equals("85")
)
|| sFrom.equals("APPROVAL")
)
You can see that you always will have (something) || false with the values given.
And changing only editableLineStatus will modify only the operator "grouping" for hasButton && editableLineStatus && !sHeaderStatus.equals("85").
However, regardless of what you change that to, you have sHeaderStatus.equals("1"), which is true, resulting in logic of
(true || (false && false) || (false && true/false && true)) || false
which, in total, is true, therefore entering the conditional

Improve my validation

When the user enters their ID I want it to be in a specific format, they are mostly explained within the comments. I was wondering if their was an easier more efficient way of doing this. Also whether or not there is a way to change the entered letters to capital the way I've done the code, or any other method.
private boolean setCustomerID(String id) {
//Validates the customerID contains 3 letters a hypthen then 4 numbers
if ((id.charAt(0) < 'A' || id.charAt(0) > 'Z')
|| (id.charAt(1) < 'A' || id.charAt(1) > 'Z')
|| (id.charAt(2) < 'A' || id.charAt(2) > 'Z')
|| (id.charAt(3) != '-')
|| !isDigit(id.charAt(4))
|| !isDigit(id.charAt(5))
|| !isDigit(id.charAt(6))
|| !isDigit(id.charAt(7))) {
return false;
//Checks the user enters P, B or C for first letter
} else if ((id.charAt(0) == 'P' || id.charAt(0) == 'B' || id.charAt(0) == 'E')
//Checks the second and third letter are in the correct region
&& ((id.charAt(1) == 'S' && id.charAt(2) == 'C')
|| (id.charAt(1) == 'S' && id.charAt(2) == 'C')
|| (id.charAt(1) == 'W' && id.charAt(2) == 'A')
|| (id.charAt(1) == 'N' && id.charAt(2) == 'I')
|| (id.charAt(1) == 'N' && id.charAt(2) == 'E')
|| (id.charAt(1) == 'N' && id.charAt(2) == 'W')
|| (id.charAt(1) == 'M' && id.charAt(2) == 'I')
|| (id.charAt(1) == 'E' && id.charAt(2) == 'A')
|| (id.charAt(1) == 'S' && id.charAt(2) == 'E')
|| (id.charAt(1) == 'S' && id.charAt(2) == 'W'))){
// SC (Scotland), WA (Wales), NI (Northern Ireland), NE (North-East), NW (North-West),
//MI (Midlands), EA (East Anglia), SE (South-East), SW (South-West).
return true;
}
return false;
}
Use regex.
private boolean matchCustomerID(String id) {
return id.matches("^[PBE](?:SC|WA|NI|NE|NW|MI|EA|SE|SW)-\\d{4}\\b");
}
Regular expressions are one way of solving the problem. You can compose the pattern in a way that makes maintenance easier. Building on rcorreia's pattern, you can do something like:
private boolean setCustomerID(String id) {
char[] validFirstLetters = { 'P', 'B', 'E' };
String[] validRegions = { "SC", "WA", "NI", "NE", "NW", "MI", "EA", "SE", "SW" };
String pattern =
String.format("^[%s](?:%s)-\\d{4}$", new String(validFirstLetters),
String.join("|", validRegions));
return id.matches(pattern);
}
Note that this uses String.join() from Java 8. If you don't use Java 8 yet, consider using StringUtils from Apache Commons Lang.
Regexp is a great feature, but not easy to write and understand..
In this case, I would follow your way, but I would define some testing method. In this manner the code will be readable and easy to write Unit tests for it.
If you need some change later, you will understand the code.
Example:
testForLength();
testForLetters();
testForFirstTwoLetters();

Incorrect logic comparing strings?

This program is supposed to compare "DNA" strings.
Input:
3
ATGC
TACG
ATGC
CGTA
AGQ
TCF
First line represents how many times the program will be run. Each time it runs, it compares the two strings. A matches with T and vice versa. G matches with C and vise versa. So if the first letter of string 1 is A, the first letter of string 2 should be T. If the next one is T, the next one on the other string should be A and etc. If a letter other than A, T, G, or C appear, it is a bad sample. If its bad, print out bad, if its good, print out good. I tried many different combinations to this and they all worked fine but according the the judge's test data (they have different input), it failed. Does anyone see anything wrong with this? I know it might not be the most efficient way of getting the job done but it did, at least to my understanding.
Output:
GOOD
BAD
BAD
public class DNA
{
public static void main(String[] args) throws IOException
{
Scanner scan = new Scanner (new File ("dna.dat"));
int T = scan.nextInt();
scan.nextLine();
boolean valid = true;
for (int i = 0; i < T; i++)
{
String strand1 = scan.nextLine();
strand1 = strand1.toUpperCase();
String strand2 = scan.nextLine();
strand2 = strand2.toUpperCase();
for (int p = 0; p < strand1.length(); p++)
{
if (strand1.charAt(p) != 'A' && strand1.charAt(p) != 'T' && strand1.charAt(p) != 'G' && strand1.charAt(p) != 'C'
&& strand2.charAt(p) != 'A' && strand2.charAt(p) != 'T' && strand2.charAt(p) != 'G' && strand2.charAt(p) != 'C')
{
valid = false;
break;
}
if (strand1.length() != strand2.length())
{
valid = false;
break;
}
}
if (valid)
{
for (int p = 0; p < strand1.length(); p++)
{
if ((strand1.charAt(p) == 'A' && strand2.charAt(p) == 'T') || (strand1.charAt(p) == 'T' && strand2.charAt(p) == 'A')
|| (strand1.charAt(p) == 'G' && strand2.charAt(p) == 'C') || (strand1.charAt(p) == 'C' && strand2.charAt(p) == 'G'))
valid = true;
else
valid = false;
}
}
if (valid)
out.println("GOOD");
else
out.println("BAD");
valid = true;
}
}
}
I added the toUpperCase and compared the strings for equal length just as a last attempt to see if their data maybe had some lowercase letters or different length strings though they SHOULD all be the same length and uppercase. Nevertheless, the program was still rejected for "failing the judges test data."
You need a break in the second for loop when valid = false. For example if characters 1,2,3 are wrong but #4 is a match you will still end up with valid.
I would convert the strings to arrays to make things easier:
for (int i = 0; i < T; i++)
{
boolean valid = true;
String strand1 = scan.nextLine();
strand1 = strand1.toUpperCase();
String strand2 = scan.nextLine();
strand2 = strand2.toUpperCase();
if ( strand1.length() != strand2.length())
{
valid = false;
}
if (valid) {
char[] c1 = strand1.toCharArray();
char[] c2 = strand2.toCharArray();
for (int p = 0; p < c1.length; p++)
{
if (-1 == "ACTG".indexOf(c1[p]) || -1 == "ACTG".indexOf(c2[p]))
{
valid = false;
break;
}
}
if (valid)
{
for (int p = 0; p < c1.length; p++)
{
if (('A' == c1[p] && 'T' != c2[p]) ||
('T' == c1[p] && 'A' != c2[p]) ||
('C' == c1[p] && 'G' != c2[p]) ||
('G' == c1[p] && 'C' != c2[p])) {
valid = false;
break;
}
}
}
}
if (valid)
System.out.println("GOOD");
else
System.out.println("BAD");
}
Change all
&&
in
if (strand1.charAt(p) != 'A' && strand1.charAt(p) != 'T' && strand1.charAt(p) != 'G' && strand1.charAt(p) != 'C' && strand2.charAt(p) != 'A' && strand2.charAt(p) != 'T' && strand2.charAt(p) != 'G' && strand2.charAt(p) != 'C')
to
||
if ANY, not ALL character is other than A, T, G, or C, then we exit the loop.

Checking string, regex issue?

Currently I am checking a string for the following:
if(parseCommand.contains("vlan1") || parseCommand.contains("Fa0/1i")
|| parseCommand.contains("Fa0/1o") || parseCommand.contains("Fa1/0")
|| parseCommand.contains("Fa1/1") || parseCommand.contains("Fa1/2")
|| parseCommand.contains("Fa1/3") || parseCommand.contains("Fa1/4")
|| parseCommand.contains("Fa1/5") || parseCommand.contains("Fa1/6")
|| parseCommand.contains("Fa1/7") || parseCommand.contains("Fa1/8")
|| parseCommand.contains("Fa1/9") || parseCommand.contains("Fa1/11")
|| parseCommand.contains("Gi0")) {
//do things here
}
However it may contain vlan1 up to vlan4094 and i have to check for these. What is the simplest way to do this?
I have tried this just to match a vlan 1-9 folowed by 0-3 digits but it doesn't find anything:
if(parseCommand.matches(".*vlan[1-9](\\d){0,3}") || parseCommand.contains("Fa0/1i")
|| parseCommand.contains("Fa0/1o")|| parseCommand.contains("Fa1/0")
|| parseCommand.contains("Fa1/1") || parseCommand.contains("Fa1/2")
|| parseCommand.contains("Fa1/3") || parseCommand.contains("Fa1/4")
|| parseCommand.contains("Fa1/5") || parseCommand.contains("Fa1/6")
|| parseCommand.contains("Fa1/7") || parseCommand.contains("Fa1/8")
|| parseCommand.contains("Fa1/9") || parseCommand.contains("Fa1/11")
|| parseCommand.contains("Gi0")) {
Even if I try this nothing is found, why?
if(parseCommand.matches(".*vlan.*")
Use .matches("(?s).*vlan.*") or so for new line characters being catched by .; See DOTALL.

Stacks, Queues and reading math from file.. odd output [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Hello again Stackoverflow,
I am in the process of creating an infix to postfix calculator. the calculator must read input from a file and then use stacks and queues to create postfix notation. i have all of my code to read the file and create the postfix notation in a queue. the file that i am reading from contains:
(4>3)+(3=4)+2
here is my code to put into postfix notation in a queue:
import java.io.*;
import java.util.ArrayList;
public class Proj1Main {
public static void main(String[] args) {
readMathFile();
q.printQueue();
}
public static void readMath(char c, myStack s, myQueue q) {
if (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9') {
System.out.println("NUMBER"); // <--for testing.
int o = (int)c;
q.enqueue(o);
} else if(c == '+' || c=='-') {
System.out.println("+ or -");
Object x = s.pop();
while( !s.isEmpty() ) {
q.enqueue(x);
x = s.pop();
}
} else if(c == '(' || c == ')' || c == '!' || c == '<' || c == '>' || c == '&' || c == '|' || c == '=') {
System.out.println("other operator"); // <--for testing.
Object x = s.pop();
char y = x.toString().charAt(0);
while( !s.isEmpty() && (y != '\\' || y != '*') ) {
q.enqueue(y);
y = (Character)s.pop();
if(y != '\\' || y != '*') {
q.enqueue(y);
s.push(x);
}
}
} else if(c=='\\' || c == '*') {
System.out.println("divide or multiply"); // <--for testing.
Object x = s.pop();
while( !s.isEmpty() ) {
q.enqueue(x);
x = s.pop();
}
} else if(c == ')') {
System.out.println("close paren"); // <--for testing.
Object x = s.pop();
while( !s.isEmpty() && x != "(" ) {
q.enqueue(x);
x = s.pop();
}
}
}
public static myStack s;
public static myQueue q;
// the file reading code was borrowed from:
// http://www.java2s.com/Code/Java/File-Input-Output/Readfilecharacterbycharacter.htm
public static void readMathFile() {
s = new myStack();
q = new myQueue();
File file = new File("test.txt");
if (!file.exists()) {
System.out.println(file + " does not exist.");
return;
}
if (!(file.isFile() && file.canRead())) {
System.out.println(file.getName() + " cannot be read from.");
return;
}
try {
FileInputStream fis = new FileInputStream(file);
char current;
// in this while loop is where all of the reading happens
while (fis.available() > 0) {
current = (char) fis.read();
readMath(current, s, q);
}
if(fis.available() == 0) {
Object x = s.pop();
while(!x.equals("empty stack"))
q.enqueue(s.pop());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
after i run the code, i print the output which turns out to be:
QUEUE:
52
51
51
52
50
I have no idea where 52, 51, etc are coming from. it should read "4>33=4+2+" (i think) i was wondering if anybody could identify my problem? or give me some tips on how to fix it?
52 51 51 52 50... are ASCII code for the characters '4', '3', '3', '4', '2' respectively.
When you are doing:
current = (char) fis.read();
you are getting the characters themselves.
Later in readMath():
int o = (int)c;
You are converting in an integer and putting it in a queue. Probably when you print the queue, it is still an integer and it comes out as the ascii code.
You can convert a digit char to the integer it represents by doing this:
Character.getNumericValue(c);

Categories