I have been building an app that simulates the way a printer works. While designing the app, I have created the method below that splits a String content depending on the number of pages required. All the function seems to process the data correctly but I don't know why the method keeps doubling the content of an array it's supposed to return. Here's the method.
public ArrayList<String> splitContentIntoPages(){
int startPosition = 0;
int endIndexCalc = 0;
for(int i=0; i<getPages(); i++){
if((getContent().length() - endIndexCalc) >= getSize().getCapacity()){
System.out.println("Start " + startPosition);
endIndexCalc = startPosition + (getSize().getCapacity());
this.pagesContent.add(getContent().substring(startPosition, endIndexCalc));
startPosition += getSize().getCapacity();
System.out.println("End " + endIndexCalc);
}else{
this.pagesContent.add(getContent().substring(startPosition));
}
}
System.out.println("Size of the array " + this.pagesContent.size() + " getPages() " + getPages() + "");
for(int i=0; i<this.pagesContent.size(); i++){
System.out.println("The content :" + this.pagesContent.get(i));
}
return this.pagesContent;
}
I need some fresher eye on the issue. I have spent too much time on that trying to understand what's wrong. Thanks a lot guys!
Here's the version without debugs
public ArrayList<String> splitContentIntoPages(){
int startPosition = 0;
int endIndexCalc = 0;
for(int i=0; i<getPages(); i++){
if((getContent().length() - endIndexCalc) >= getSize().getCapacity()){
endIndexCalc = startPosition + (getSize().getCapacity());
this.pagesContent.add(getContent().substring(startPosition, endIndexCalc));
startPosition += getSize().getCapacity();
}else{
this.pagesContent.add(getContent().substring(startPosition));
}
}
return this.pagesContent;
}
this is the test entry extraxt. Basically the method aboe is processing the string of chars
that's the outcome. Basically, the string is supposed to be split into the number of pages - in this case 2. However, the array that is holding the split element of the strings holds 4 pieces of strings instead of two. It's all doubled. And I have no idea why
Either clear this.pagesContent at the beginning of splitContentIntoPages() or create new ArrayList<String> newA = new ArrayList<String>() at the beginning, add everythig to this new arrayList and at the end of splitContentIntoPages() do this.pagesContent = newA
Related
I'm encountering some confusing behavior when trying to create an array of certain length. The length is obtained by a file read in the function getTermNums. When I try to create an array of this size, my code runs in a strange order, my i values are skewed, and the code generally doesn't run as intended. When I instead create an array of a set integer amount, the code runs as intended without error.
double[] terms;
int numTerms = getNumTerms(lines[0]);
terms = new double[numTerms];
int i = 1;
for (i = 1; i<terms.length; i++){
//terms[i] = calculateTerm(T, lines[i]);
}
the above code runs incorrectly.
double[] terms;
int numTerms = getNumTerms(lines[0]);
int myNum = 200;
terms = new double[myNum];
int i = 1;
for (i = 1; i<terms.length; i++){
//terms[i] = calculateTerm(T, lines[i]);
the above code runs correctly
int getNumTerms(String line){
int i = 60;
int j = 0;
char[] word;
word = new char[4];
int numTerms;
int numTermLen = 0;
while(new String(word).compareTo("TERM") != 0){
for (j=0; j<4; j++){
word[j] = line.charAt(i + j);
}
i++;
}
j = i - 3;
while( new Character(line.charAt(j)).equals(' ') == false){
numTermLen++;
j--;
}
j++;
println("i in here: ", i);
numTerms = Integer.parseInt(line.substring(j, j + numTermLen));
return numTerms;
}
this is the function that I'm calling to read the numterms for the size of the array in the first example that doesn't work correctly.
When I use the function call to set the size of array terms[], i starts at some value like 380, and the iteration through array lines[] begins somewhere in the middle of the array.
When I use the integer myNum to set the size of array terms[], i starts at 1, and the iteration through array lines[] begins at the first line, as intended.
Any explanation is appreciated! I'm new to coding in java and am confused by the source of this error.
Thanks in advance.
Without seeing the text it's tiresome to deduct where in your getNumTerms the error occurs.
You can make use of String's indexOf() to find the index of "TERM" and substring() to extract the String containing the integer value.
As far as I understand the ideal string would have "TERM" followed by an integer then a space character. If these items are found and the value fits within 32 bits you should be able to use something like this:
String line = "LINE START TERM-1238847 LINE END";
int getTerm(String line){
int result = Integer.MAX_VALUE;
final String SEARCH_TOKEN = "TERM";
// look for TERM token and remember index
int termIndex = line.indexOf(SEARCH_TOKEN);
// handle not found
if(termIndex < 0){
System.err.println("error: " + SEARCH_TOKEN + " not found in line");
return result;
}
// move index by the size of the token
termIndex += SEARCH_TOKEN.length();
int spaceIndex = line.indexOf(' ',termIndex);
if(spaceIndex < 0){
System.err.println("error: no SPACE found after " + SEARCH_TOKEN);
return result;
}
// chop string extracing between token end and first space encountered
String intString = line.substring(termIndex,spaceIndex);
// try to parse int handling error
try{
result = Integer.parseInt(intString);
}catch(Exception e){
System.err.println("error parsing integer from string " + intString);
e.printStackTrace();
}
return result;
}
System.out.println("parsed integer: " + getTerm(line));
Does anyone why when the search value matches a value stored in array it doesn't remove that item?
String titles = "";
String lengths = "";
for (int i = 0; i < numOfSongs; i++) {
titles += songTitles[i] + " ";
lengths += songLengths[i] + " ";
}
String search = JOptionPane.showInputDialog("Enter a song title to remove it or -1 to end:");
while (!search.equals("-1")) {
for (int i = 0; i < numOfSongs; i++) {
if (search.equalsIgnoreCase(songTitles[i])) {
songTitles[i] = songTitles[i + 1];
}
}
numOfSongs--;
JOptionPane.showMessageDialog(null, "**Current Playlist**" + "\nSong titles: " + titles + "\nSong lengths: " + lengths);
search = JOptionPane.showInputDialog("Enter a song title to remove it or -1 to end:");
}
Many things are wrong with this code:
You never update titles and lengths inside your while loop, so whatever happens inside has no effect on what's printed in the dialog
When you find song title to remove, you copy the next song title to the current one, but don't copy anything else, so [a, b, c, d] will after removing b change to [a, c, c, d] - you need to shift everything behind the deleted element left by one position
When you find song title to remove, you assume the i+1th position is valid - this isn't true if you remove the last song on the list, that would either fail with ArrayIndexOutOfBounds exception or copy some garbage from behind the currently valid playlist
You're never updating songLengths array
Concatenating strings in a loop using += is very ineffective - use StringBuilder instead
Sorry this took a while, but hopefully it's pretty comprehensive.
I am assuming that song title and song length are supposed to correspond with one another, so that if you remove the title you also remove the length? It may be good to create a class, e.g. Song, which has a field for both title and length. There are more methods you can add, e.g. setters, default constructor, etc. You can also include more fields like Song Artist, year, etc. I'm just including those required for your program to run.
I'll use red's suggestion of an ArrayList, so you can see what they meant (in case you haven't learned what that is)
public class Song {
String title; //these are known as fields, or instance variables
String length;
public Song(String title, String length) {
this.title = title;
this.length = length;
}
public String getTitle() {
return title;
}
public String getLength() {
return length;
}
//you can format this differently. Just keeping it simple though. If you don't include toString() method in this class, you will run into some problems if you try to print the object itself.
public String toString() {
return "title = " + title + " length = " + length + "\n";
}
From here, in your main method you can do...
ArrayList<Song> playlist = new ArrayList<>();
//here, inside a do-while loop, get input for each song, then store into strings, let's call them songTitle and songLength. I'm not showing this step since I don't know where you want the input to come from, but I'm sure you can figure this bit out. ;)
Then we create objects and add them to your list like so:
Song song = new Song(songTitle, songLength); //creates a new object with arguments songTitle and songLength
playlist.add(song); //adds object to array list.
Once you have your playlist set up, we return to your question regarding song removal, and here is where Lists(there are different ones you can use)/Objects really make things far simpler.
Iterator<Song> songIt = playlist.iterator();
while (!search.equals("-1") && songIt.hasNext()) {
if (search.equalsIgnoreCase(songIt.next().getTitle())) {
songIt.remove();
}
}
And printing is simple too.
for (int i = 0; i < playlist.size(); i++) {
System.out.println(playlist.get(i);
}
-EDIT-
To put into perspective, here is what you would have to do for removal in your program using array and without objects.
int removeCount = 0;
while (!search.equals("-1")) {
for (int i = 0; i < songTitles.length; i++) {
if (search.equalsIgnoreCase(songTitles[i])) {
for (int j = i; j < songTitles.length - 1; j++) {
songTitles[j] = songTitles[j + 1];
songLengths[j] = songLengths[j + 1];
removeCount ++;
}
}
}
}
String remainingTitles[] = new String[songTitles.length - removeCount];
String remainingLengths[] = new String[songTitles.length - removeCount];
for (int i = 0; i < temp.length; i++) {
remainingTitles[i] = songTitles[i];
remainingLengths[i] = songLengths[i];
}
Suffice it to say, this is much more ugly, and there's many more places where you can make a stupid mistake that may or may not throw an exception.
I first created an arraylist in another part of the program, then used for loops to put it in the text area. Now, I want to take input from the text field, add that to the arraylist, and display the entire array, including the new element added. I tried using a for loop again, but when i click "add" while running, the program just freezes and nothing happens. Any suggestions?
Thanks.
private void btnDisplayActionPerformed(java.awt.event.ActionEvent evt) {
// Using a for loop to display unsorted list, sorting the list, then using a for loop again to display the sorted list
String strUnsortedList = "";
for(int i = 0; i < strCDNames.size(); i++) {
strUnsortedList += strCDNames.get(i) + "\n";
}
Collections.sort(strCDNames);
String strSortedList = "";
for(int i = 0; i < strCDNames.size(); i++) {
strSortedList += strCDNames.get(i) + "\n";
}
txtOutput.setText("Unsorted Order: \n" + strUnsortedList + "\nSorted Order: \n" + strSortedList);
}
private void btnAddActionPerformed(java.awt.event.ActionEvent evt) {
String strAddedList = "";
for (int i = 0; i < strCDNames.size(); i++) {
strAddedList += strCDNames.add(txtInputTitleArtist.getText());
}
txtOutput.setText(" " + strAddedList);
}
for (int i = 0; i < strCDNames.size(); i++) {
strAddedList += strCDNames.add(txtInputTitleArtist.getText());
}
This is an infinite loop. You keep adding to the list, which means that the list size will keep increasing. Hence i will always be lesser than strCDNames.size().
Instead you can do something like this:
strCDNames.add(txtInputTitleArtist.getText());
String strAddedList = String.join(" ", strCDNames);
Vivin is right. I just want to add that the arraylist add method returns a boolean (https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#add-E-). So, in this case strAddedList wouldn't even be properly updated.
I need to implement a delete method WITHOUT USING AN ARRAY LIST. I need to use a set of loops to do it. Here is my delete method and add method as well as any other important variables used. Any advice on what is wrong with my code would be great.
EDITED: Changed the comparing of references to values. Seems to work repeatedly.
final int MAX_DEVICES = 5;
// Array of devices
private Device list[] = new Device[MAX_DEVICES];
// Number of Devices currently in the list
// "Valid" Devices are stored in cells 0 - (numDevices - 1)
private int numDevices = 0;
Scanner stdin; // read from stdin
private void Add()
{
String thisName;
int numThisRead;
float thisInitVal;
thisName = stdin.next();
numThisRead = stdin.nextInt();
thisInitVal = stdin.nextFloat();
if(numDevices > MAX_DEVICES)
System.out.println("The List was full. " + thisName +
" was not added to the list.");
else
{
Device myDevice = new Device(thisName, numThisRead, thisInitVal);
list[numDevices] = myDevice;
numDevices ++;
System.out.println(thisName + " device has been added to the list.");
}
}
private void Delete() //ASK QUESTION
{
String thisDelete;
thisDelete = stdin.next();
for(int i = 0; i < MAX_DEVICES; ++i)
{
if(list[i].getName().equals(thisDelete)) //if you find the name
{
System.out.println(list[i].getName() + " was deleted from the "
+ "list.");
for(int j = i; j < numDevices - 1; j++)
list[j] = list[j + 1];
numDevices--;
return;
}
}
System.out.println(thisDelete + " not deleted. It is not in the list.");
}
If you need to avoid using data type List, you can place the objects in the array. Then you can declare an array one element smaller than the current array and copy all the elements, except for the one you want deleted, over into the new array. Then return the new array.
I did a lot of searching on this subject, but I couldn't find anything usable for my problem: I'm making a simple memory game in Java based on an integer array. I want the array to contain only duplicate entries and no unique ones. Unfortunately most of the questions here are dealing with avoiding or removing duplicate entries, but what about enforcing them?
My code so far looks like this.
public Field[] getField(){
Random r = new Random();
int pool = 16;
ArrayList<Integer> used = new ArrayList<Integer>();
int rand = r.nextInt(pool);
System.out.println("First random: " + rand);
for(int i = 0; i < fields.length; i++){
System.out.println("ITERATION " + i + " STARTED");
while(used.contains(rand)){
System.out.println(rand + " is used, recalculating...");
rand = r.nextInt(pool);
System.out.println("New random is " + rand);
}
fields[i] = new Field(rand);
System.out.println(rand + " added in Field " + i);
int tmp = r.nextInt(fields.length - 1);
System.out.println("First tmp calculated: " + tmp);
while(fields[tmp] != null && i <= fields.length / 2){
tmp = r.nextInt(fields.length - 1);
System.out.println("Field " + tmp + " is used, looking for another...");
}
fields[tmp] = new Field(rand);
System.out.println(rand + " added in temp Field " + tmp);
used.add(rand);
System.out.println("ITERATION " + i + " ENDED");
System.out.println();
}
return fields;
}
fields[] is an array of the type Field (basically has just one member (int id).
If I'm understanding what you're after correctly, I think you're probably making this a lot harder than it has to be.
It is much easier to iterate over your fields array in order and add two Fields of the same value each iteration, then shuffle the array. Something like the following code:
{
...
for (int i = 0; i < fields.length; i += 2)
fields[i] = fields[i + 1] = new Field(r.nextInt(pool));
shuffleFields(fields);
return fields;
}
You can take your pick of shuffling algorithms. The Fisher-Yates shuffle is popular. E.g.:
void shuffleFields (Field[] fields)
{
Random r = new Random();
for (int i = fields.length - 1; i >= 1; --i)
{
int j = r.nextInt(i + 1);
Field t = fields[i];
fields[i] = fields[j];
fields[j] = temp;
}
}