String.substring(i,j) method gets blank spaces rather than actual characters - java

The code below is the entire program so far (just to avoid any missing pieces.
The issue I'm having is that I'm trying use the .substring(int,int) method to pull two characters from the given string and write the two characters pulled into a separate array. The problem is that every character pulled from the string using .substring() is a blank space. There are no letters pulled at all. I tested the function using a simple print method and it went to show that printing sentences.get(i).substring(j,j++) only prints blank spaces. It's populating my arrays with those empty spaces.
Any clue as to what could be causing this? My compiler isn't giving me any errors or warnings whatsoever.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class JacSim {
public static void main(String [] args) throws FileNotFoundException {
Scanner userScanner = new Scanner(System.in);
System.out.println("Please enter the filename for your input file (with extension).");
String fileName = userScanner.nextLine();
File file = new File(fileName);
Scanner scanner = new Scanner( new FileInputStream(file));
List<String> sentences = new ArrayList();
while (scanner.hasNextLine()) {
String sentence = scanner.nextLine();
sentences.add(sentence);
}
System.out.println("Input Sentences:\n");
for(int i=0;i<sentences.size();i++) {
System.out.println(i + " : " + sentences.get(i));
}
List<List<String>> shingles = new ArrayList();
sentences.stream().forEach((String _item) -> {
shingles.add(new ArrayList());
});
System.out.println("\nSorted Shingle Arrays:\n");
shinglesMethod(shingles, sentences);
}
private static List shinglesMethod(List<List<String>> shingles, List<String> sentences) {
for (int i=0;i<sentences.size();i++) {
for(int j=0;j++<sentences.get(i).length();j++) {
shingles.get(i).add(sentences.get(i).substring(j,j++));
}
showList( i, shingles.get(i) );
}
return shingles;
}
private static void showList( int n, List List ) {
System.out.print(n + " : ");
List.stream().forEach((o) -> {
System.out.print( o + " " );
});
System.out.println();
}
The chunk of code to pay attention to is
for (int i=0;i<sentences.size();i++) {
for(int j=0;j++<sentences.get(i).length();j++) {
shingles.get(i).add(sentences.get(i).substring(j,j++));
}
showList( i, shingles.get(i) );
}
Forgot to clarify that the scanner is reading in the words properly and that each string is read as expected. The only issue I'm finding is with the .substring() method.

This seems to be rooted in confusion about what ++ does. j++ returns the value of j and afterwards increments j.
.substring(j,j++) will always return the empty string, because it increments j after getting a substring between j inclusive and j exclusive. substring(j, j + 1) would probably be more what you want.
You also need to use j + 1 < sentences.get(i).length(), instead of j++, because you're changing the value of j as you're trying to check it, which is almost certainly not what you want. The only place j++ should be mentioned would be in the update statement in the for loop.

j++ uses the value of j and then increments the value of j. So your code is equivalent to substring(j,j). Also, when you write x.substring(i,j), the substring begins at i and extends to the character at j - 1.
Use substring(j,j+2) instead and change the condition of your inner while loop to j<sentences.get(i).length() - 2.

Related

Accessing index values before and after symbol from input

I am trying to take the input and if there is an # symbol in the input then it finds the maximum of the integers before and after the # symbol. The maximum part I have no problem with but I do not know how to access and find the values before and after the # symbol.
import java.util.Scanner;
public class Max_Min {
public static void main(String[] args) {
//gets keyboard
Scanner keyboard = new Scanner(System.in);
//puts input into string
String inputString = keyboard.nextLine();
//splits string between characters
String[] splitInput = inputString.split("");
for (String s : splitInput) {
if(s.equals("#")){
//computes the maximum of the two integers before and after the #
}
}
//close keyboard
keyboard.close();
I did do a search to find something simliar (and im sure there is something) but could not find anything. If someone could help that would be great!
Try with this:
for (int i = 0; i < splitInput.length; i++){
if (splitInput[i].equals("#") && i != 0 && i != splitInput.length -1){
int max = Math.max(Integer.parseInt(splitInput[i - 1]), Integer.parseInt(splitInput[i + 1]));
}
//...
}
You could try:
String[] splitInput = inputString.split("#");
which would split your string at the #s.
Then you can do a iteration over your splitInput array and do a .length on each index.
You have written the simple for loop, with which you can only access the string, but not its index in the array. If you had the index, you could write:
int possibleMax = Integer.parseInt(splitInput[i - 1]) + Integer.parseInt(splitInput[i + 1]);
To get the index, there are two ways:
for (int i = 0; i < splitInput.length; i++) {
String s = splitInput[i];
...
}
Or:
int i = 0;
for (String s : splitInput) {
…
i++;
}
I don't like either version because both are more complicated than absolutely necessary, in terms of written code. If you would use Kotlin instead of Java, it would be:
splitInput.forEachIndexed { i, s ->
…
}
In Java this could be written:
forEachIndexed(
splitInput,
(i, s) -> …
);
The problem in Java is that the code inside the … cannot update the variables of the enclosing method. I'm not sure whether this will ever change. It would be possible but needs a lot of work by the language committee.
A simple way to do this would be
String input = "12#23";
String [] arr = input.split("#");
if (arr.length == 2) {
System.out.println("Max is "+Math.max(Integer.valueOf(arr[0]),Integer.valueOf(arr[1])));
}

java.lang.ArrayIndexOutOfBoundsException error in if statement

I am getting the error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 28
at assignment.assgn1.main(assgn1.java:44)
I would be very grateful if someone could point out the error
package assignment;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.opencsv.CSVReader;
import java.io.FileNotFoundException;
public class assgn1 {
public static void main(String[] args) throws IOException
{
try{
CSVReader csvReader = new CSVReader(new FileReader("E:/AviationData.txt"),'\t','\n');
PrintWriter NYreports = new PrintWriter("E:/NYReports.txt");
String [] nextLine;
int x;
int sum=0;
double totalFatal=0;
Integer largest = 0;
Integer smallest = 0;
String [] token = null;
//read first line, but it will not be counted with the rest of the records
nextLine = csvReader.readNext();
//create a map for unique Broad Phase in flight fields
Map<String, Integer> broadPhase = new HashMap <String, Integer>();
//create an array list that will take in integer values of Fatal Injuries
ArrayList <Integer> intList = new ArrayList<Integer>();
while ((nextLine = csvReader.readNext()) !=null){
sum++;
String field = nextLine[0];
//using regex values!
token = field.split("\\s\\|\\s");
//for (String s: token){
//System.out.println(s);
//}
if(token[28].equals(" ")){
broadPhase.put(token[28],0);
}
if(!token[28].equals(" ") && !token[28].equals("")){
broadPhase.put(token[28], 1);
}
//search for Fatal Injury values
if(!token[23].isEmpty()){
x=Integer.parseInt(token[23]);
//add to ArrayList
intList.add(x);
totalFatal = x + totalFatal;
}
if(token[4].contains(", NY") && token[5].contains("/2015")){
NYreports.println(nextLine[0]);
}
}
for(int i =0; i<intList.size()-1; i++){
if (intList.get(i) > largest);
largest = intList.get(i);
if (intList.get(i)< smallest)
smallest = intList.get(i);
}
System.out.println("There are " + sum + " records");
System.out.println("There are " + (broadPhase.size())+" unique values in Broad Phase of Flight");
totalFatal = (totalFatal/sum);
System.out.println(largest + " is the largest number of Fatal injuries");
System.out.println("The average of Fatal injuries is " + totalFatal);
NYreports.close();
csvReader.close();
}
catch (FileNotFoundException ex){
System.out.println("File not Found");
}
}
}
the error is on the line where if(token[28].equals(" ")){. is written.
what can i change to avoid it. also if any change in method used by me can be done.
ArrayIndexOutOfBoundsException generally occurs when you try to access
an index which is not present on the array
, ie.. index > length - 1 (since arrays in java are 0 based).
To avoid this error make sure that you use only valid indexes , which are
0 =< idx < length.
In the current context you may want to add an additional check to ensure that array contains that index along with the normal if conditions.
something like
if(token.length > 28 && token[28].equals(" ")){
broadPhase.put(token[28],0);
}
The error is because token[28] doesn't exist. In other words, your split() call is returning an array that isn't as long as you think it is. I would check your input to see whether or not your input is correct.
On a side note, your method seems to be very... rough and hard coded. Assuming that you know the exact order the tokens are stored in, a better way to do this that would avoid the ArrayIndexOutOfBounds Exception is to loop through your tokens array using a either a for each loop or a normal for loop.
You can then parse each section while you're looping through it.
For example:
for (int i = 0; i < tokens.length; i++) {
// based on the i value, parse a different way
}

How to use portion of an array

Sorry if everyone sees me post a lot of silly questions today (just a preface). However this is the final for a summer class and my teacher stopped caring/explaining how to do things for my first coding class.
For this project I have to print a list of integers from a .dat file into a program in reverse order with a max of 40 possible values in the array (Did all that) The problem I am encountering is that he said the program should also be flexible enough to deal with less than 40 values. However given my current code I always encounter an error saying "nosuchelementexception". Any help would be greatly appreciate. Below is a copy of what I have:
import java.io.*; //Imports any file operation (ie Reading or Writing)
import java.util.Scanner; //Imports scanner class
public class program3
{
public static void main(String [] ars) throws IOException
{
double [] Values; // creating array called value
Values = new double [40]; // establishing array with 40 cells
int k; // creating counter integer
Scanner InputFile = new Scanner( new FileReader("temp.dat")); // input file you wish to open.
for (k = 0 ; k < Values.length ; k++)
Values[k] = InputFile.nextDouble();
for (k = Values.length - 1 ; k >= 0 ; k--)
System.out.println("Cell " + k + " contains the value " + Values[k]);
InputFile.close();
}
}
The problem you are having is that the length attribute of an array refers to the declared length, not the amount of data in it.
When you try to use the length (in this case 40) to control the loop you use for reading data, you will get an error if there are fewer elements to read.
What you want to do is read more input only while there exists more input to get:
int k = 0;
while (inputFile.hasNextDouble()) {
Values[k++] = inputFile.nextDouble();
}
Also, consider using an ArrayList instead of an array. The ArrayList class allows you to store a dynamic amount of data, so you don't have to worry about pre-allocating storage space:
ArrayList<Double> values = new ArrayList<>();
while (inputFile.hasNextDouble()) {
values.add(inputFile.nextDouble());
}
You can use a while loop and a counter
import java.io.*; // Imports any file operation (ie Reading or Writing)
import java.util.Scanner; // Imports scanner class
public class program3
{
public static void main(String [] ars) throws IOException
{
double [] Values; // creating array called Values
Values = new double [40]; // establishing array has 40 cells
int counter = 0; // creating counter integer
Scanner inputFile = new Scanner( new FileReader("temp.dat")); //input file you with to open.
while(inputFile.hasNextDouble()){
Values[counter] = InputFile.nextDouble();
counter++;
}
for (i = counter - 1 ; i >= 0 ; i--)
System.out.println("Cell " + i + " contains the value " + Values[i]);
InputFile.close();
}
}
If you do not have to use an Array, use an ArrayList<Double>. This allows you to call values.add(value) to add to the list. The length is variable and you can use your same code (just replace values[i] with values.get(i))
However, if you do have to use arrays, created a method that adds to the array. Start with a 0 length array, and when an element is added, create a new array of length+1, then copy the old elements in, and add the new element at the end.
There are many other ways to go about this, but these two allow you to use your existing working code.
Array approach:
values = new double[0];
public void add(double x){
double[] temp = new double[values.length +1];
for(int i =0; i< values.lenght; i++){
temp[i] = values[i];
}
temp[temp.length-1] = x;
values = temp;
}
you should use an arrayList instead so you don't have to initially set the size of the array. This would make it so that you never have empty elements in the array.
Another option would be to initialize the array with placeholder values like -1, and then only perform the switch if the value is not -1.
Add a counter that keeps track of how many item you put into the array and use that to determine where to stop when you go to print them out.
Is there 40 elements in your .dat file. If there isnt your code probably gave the exception.
for (k = 0 ; k < Values.length ; k++)
Values[k] = InputFile.nextDouble();
If your .dat file doesn't contain 40 elemennts then value[39] can't be filled in.
An Array has a fixed size after initialising it, so you may want to use dynamic datastructure or instead use a while loop as posted below. I personally would recommend an ArrayList in this case.
You should also use the method
Scanner.hasNext() or in your particular case Scanner.hasNextDouble() Docs
to get any new elements.
So your program would then look like this:
import java.io.*; //Imports any file operation (ie Reading or Writing)
import java.util.Scanner; //Imports scanner class
import java.util.ArrayList;
public class program3
{
public static void main(String [] ars) throws IOException
{
ArrayList<Double> doubles = new ArrayList<Double>();
Scanner inputFile = new Scanner( new FileReader("temp.dat"));
while (inputFile.hasNextDouble()) {
doubles.add(inputFile.nextDouble());
}
inputFile.close();
for (Double value : doubles) {
System.out.println(value);
}
}
}
Java has convenient methods in it's Collections class to allow sorting. You may want to check this out if you haven't already.
I admire your grit getting on Stack Overflow.
To reward you here's your answer.
The first for loop you have iterates over your new, empty array. That would be find except you are RETRIEVING information from the Scanner object, InputFile.
So you should in fact be iterating over that object! Not your array. No shame though. Classic mistake.
Here's my version of your code:
import java.io.FileReader;
import java.io.IOException; //Imports any file operation (ie Reading or Writing)
import java.util.Scanner; //Imports scanner class
public class program3
{
public static void main( String [] ars ) throws IOException
{
double [] Values; // creating array called value
Values = new double [40]; // establishing array has 20 cells
int k; // creating counter integer
//input file you with to open.
Scanner InputFile = new Scanner( new FileReader( "temp.dat" ) );
for ( k = 0; InputFile.hasNextDouble(); k ++ )
Values[k] = InputFile.nextDouble();
for ( k = Values.length - 1; k >= 0; k-- )
System.out.println( "Cell " + k + " contains the value " + Values[k] );
InputFile.close();
}
}
Hope this helps!

Reading a sequence until the empty line

I am writing a Java program. I need help with the input of the program, that is a sequence of lines containing two tokens separated by one or more spaces.
import java.util.Scanner;
class ArrayCustomer {
public static void main(String[] args) {
Customer[] array = new Customer[5];
Scanner aScanner = new Scanner(System.in);
int index = readInput(aScanner, array);
}
}
It is better to use value.trim().length()
The trim() method will remove extra spaces if any.
Also String is assigned to Customer you will need to create a object out of the String of type Customer before assigning it.
Try this code... You can put the file you want to read from where "stuff.txt" currently is. This code uses the split() method from the String class to tokenize each line of text until the end of the file. In the code the split() method splits each line based on a space. This method takes a regex such as the empty space in this code to determine how to tokenize.
import java.io.*;
import java.util.ArrayList;
public class ReadFile {
static ArrayList<String> AL = new ArrayList<String>();
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new FileReader("stuff.txt"));
String datLine;
while((datLine = br.readLine()) != null) {
AL.add(datLine); // add line of text to ArrayList
System.out.println(datLine); //print line
}
System.out.println("tokenizing...");
//loop through String array
for(String x: AL) {
//split each line into 2 segments based on the space between them
String[] tokens = x.split(" ");
//loop through the tokens array
for(int j=0; j<tokens.length; j++) {
//only print if j is a multiple of two and j+1 is not greater or equal to the length of the tokens array to preven ArrayIndexOutOfBoundsException
if ( j % 2 ==0 && (j+1) < tokens.length) {
System.out.println(tokens[j] + " " + tokens[j+1]);
}
}
}
} catch(IOException ioe) {
System.out.println("this was thrown: " + ioe);
}
}
}

how to separate values in a string index that are char and int

okay basically im wanting to separate the elements in a string from int and char values while remaining in the array, but to be honest that last parts not a requirement, if i need to separate the values into two different arrays then so be it, id just like to keep them together for neatness. this is my input:
5,4,A
6,3,A
8,7,B
7,6,B
5,2,A
9,7,B
now the code i have so far does generally what i want it to do, but not completely
here is the output i have managed to produce with my code but here is where im stuck
54A
63A
87B
76B
52A
97B
here is where the fun part is, i need to take the numbers and the character values and separate them so i can use them in a comparison/math formula.
basically i need this
int 5, 4;
char 'A';
but of course stored in the array that they are in.
Here is the code i have come up with so far.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
public class dataminingp1
{
String[] data = new String[100];
String line;
public void readf() throws IOException
{
FileReader fr = new FileReader("C:\\input.txt");
BufferedReader br = new BufferedReader(fr);
int i = 0;
while ((line = br.readLine()) != null)
{
data[i] = line;
System.out.println(data[i]);
i++;
}
br.close();
System.out.println("Data length: "+data.length);
String[][] root;
List<String> lines = Files.readAllLines(Paths.get("input.txt"), StandardCharsets.UTF_8);
root = new String[lines.size()][];
lines.removeAll(Arrays.asList("", null)); // <- remove empty lines
for(int a =0; a<lines.size(); a++)
{
root[a] = lines.get(a).split(" ");
}
String changedlines;
for(int c = 0; c < lines.size(); c++)
{
changedlines = lines.get(c).replace(',', ' '); // remove all commas
lines.set(c, changedlines);// Set the 0th index in the lines with the changedLine
changedlines = lines.get(c).replaceAll(" ", ""); // remove all white/null spaces
lines.set(c, changedlines);
changedlines = lines.get(c).trim(); // remove all null spaces before and after the strings
lines.set(c, changedlines);
System.out.println(lines.get(c));
}
}
public static void main(String[] args) throws IOException
{
dataminingp1 sarray = new dataminingp1();
sarray.readf();
}
}
i would like to do this as easily as possible because im not to incredibly far along with java but i am learning so if need be i can manage with a difficult process. Thank you in advance for any at all help you may give. Really starting to love java as a language thanks to its simplicity.
This is an addition to my question to clear up any confusion.
what i want to do is take the values stored in the string array that i have in the code/ input.txt and parse those into different data types, like char for character and int for integer. but im not sure how to do that currently so what im asking is, is there a way to parse these values all at the same time with out having to split them into different arrays cause im not sure how id do that since it would be crazy to go through the input file and find exactly where every char starts and every int starts, i hope this cleared things up a bit.
Here is something you could do:
int i = 0;
for (i=0; i<list.get(0).size(); i++) {
try {
Integer.parseInt(list.get(0).substring(i, i+1));
// This is a number
numbers.add(list.get(0).substring(i, i+1));
} catch (NumberFormatException e) {
// This is not a number
letters.add(list.get(0).substring(i, i+1));
}
}
When the character is not a number, it will throw a NumberFormatException, so, you know it is a letter.
for(int c = 0; c < lines.size(); c++){
String[] chars = lines.get(c).split(",");
String changedLines = "int "+ chars[0] + ", " + chars[1] + ";\nchar '" + chars[0] + "';";
lines.set(c, changedlines);
System.out.println(lines.get(c));
}
It is very easy, if your input format is standartized like this. As long as you dont specify more (like can have more than 3 variables in one row, or char can be in any column, not only just third, the easiest approach is this :
String line = "5,4,A";
String[] array = line.split(",");
int a = Integer.valueOf(array[0]);
int b = Integer.valueOf(array[1]);
char c = array[2].charAt(0);
Maybe something like this will help?
List<Integer> getIntsFromArray(String[] tokens) {
List<Integer> ints = new ArrayList<Integer>();
for (String token : tokens) {
try {
ints.add(Integer.parseInt(token));
} catch (NumberFormatException nfe) {
// ...
}
}
return ints;
}
This will only grab the integers, but maybe you could hack it around a bit to do what you want :p
List<String> lines = Files.readAllLines(Paths.get("input.txt"), StandardCharsets.UTF_8);
String[][] root = new String[lines.size()][];
for (int a = 0; a < lines.size(); a++) {
root[a] = lines.get(a).split(","); // Just changed the split condition to split on comma
}
Your root array now has all the data in the 2d array format where each row represents the each record/line from the input and each column has the data required(look below).
5 4 A
6 3 A
8 7 B
7 6 B
5 2 A
9 7 B
You can now traverse the array where you know that first 2 columns of each row are the numbers you need and the last column is the character.
Try this way by using getNumericValue() and isDigit methods. This might also work,
String myStr = "54A";
boolean checkVal;
List<Integer> myInt = new ArrayList<Integer>();
List<Character> myChar = new ArrayList<Character>();
for (int i = 0; i < myStr.length(); i++) {
char c = myStr.charAt(i);
checkVal = Character.isDigit(c);
if(checkVal == true){
myInt.add(Character.getNumericValue(c));
}else{
myChar.add(c);
}
}
System.out.println(myInt);
System.out.println(myChar);
Also check, checking character properties

Categories