How to move up lines in a .txt file with BufferedReader? - java

Making an "assembler" program for a CS course I am enrolled in. It has functions like ADD, SET, INC (increment), and JIG. Now, we are inputing a .txt file with the following layout (as example):
Keep note: A and B are just integer's that store the value throughout the program, and print out the value once it reaches the end of the text file.
INC A (increments A by 1)
SET B 5 (set's B's value to 5)
INC B
ADD A 3 (add's 3 to A's current value)
JIG B -4 (move's backward 4 lines, so back to INC A)
So what I am confused how to do is move my BufferedReader back 4 lines? Is there a method in BufferedReader that lets you move it to a certain index/position? Otherwise, how else can I accomplish this?

The simplest thing to do is store the lines in an array or List.
List<String> lines = Files.readAllLines(Paths.get("myfile.txt"));
This will allow you to progress to any line at random.
To get any line you can use lines.get(n) For example you can do
int pointer = 0;
for(boolean running = true; running && pointer < lines.size(); ) {
String line = lines.get(pointer);
String[] parts = line.split(" +");
switch(part[0]) {
case "JMP":
pointer += Integer.parseInt(parts[1]); // jump back or forth.
continue;
case "HALT":
running = false;
break;
// other instructions
}
pointer++;
}

Related

How to add a variable to another variable that's already set

My homework is to create a program that takes a list of numbers and prints out the highest number divisible by four.
List would look like this:
12
16
87
58
25
73
86
36
79
40
12
89
32
Input should be:
40 because it is the highest number there divisible by four.
Here is my code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int saved = 0;
int saved2 = 0;
for (int i = scanner.nextInt(); i % 4 == 0; i = scanner.nextInt()) {
for (boolean bull = true; bull == true; bull ^= true) {
if (i > saved) {
saved -= saved2;
saved += i;
saved2 += i;
}
}
System.out.println(saved);
}
}
}
The input of my code is
12
16
I don't really understand why this is doing it, but it seems to me that I'm adding the variables wrong. The homework page on adding variables does not specify how to add variables to each other.
Does anyone have a tip to improve the code in anyway, or find a way to make a fix my code? Thank you.
welcome to Java.
First you are saying you got input, but that is output. Input is what you enter, and output is what you get printed.
Then there is a mistake in your for loops. You have too much going on in one place. By the logic which is implemented, your program will exit first level for loop whenever your entered value is not divisable by 4.
Read on for loops if you want to learn more https://www.learnjavaonline.org/en/Loops.
I recommend to start from while loops instead. The logic whould be this:
1. create variable to hold the correct answer saved
2. create another one to hold the value read from console i
3. start the while loop with condition i = scanner.nextInt()
3.1 check if the value just entered i is divisable by 4
3.2 if it is, then compare if it's larger than the one was saved before (initially saved value will be 0)
3.3 if it is larger, then assign the read value i to the saved
4. At the end of the loop, you will have the highest number divisable by four in your saved variable. Print it.
I will provide some help, according to
How do I ask and answer homework questions?
for (int i = scanner.nextInt(); i % 4 == 0;i = scanner.nextInt())
This only reads as long as ALL inputs are divisible by 4, that is why it ends at 16, because 87 is not divisible by 4.
for (boolean bull = true; bull == true ;bull ^= true)
This needs explanation by you, but I am pretty sure that it unconditionally executes the body of the inner loop exactly once. (Not 100% sure, because the representation of true and false could be weird in your machine. Should 0 be the representation of true, i.e. really weird, then it is an endless loop, which does not match the output you describe...)
System.out.println(saved);
This executes exactly once per input, except the last one, which is not a multiple of 4.
The value of saved is identical to input, as long as it is increasing.
These hints explain the unexpected output.
If you inspect the details of what the problem is, you should be able to improve your coding attempt.
This is how I super-quickly fixed in your code.
Note that there are no statements about the possible minimum value and about how do you stop the input. Therefore the solution is pretty-straightforward, it just reads the input until integers are present there.
This article may be useful about handling the input from the Scanner.
I hope the comments in the code will help. Add comments if there are any questions. Good luck!
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int currentMax = Integer.MIN_VALUE; // you may set negative or 0 if you know that all the input is positive
// int saved2 = 0; // no need for this variable
while (scanner.hasNextInt()) { // you can make a better input handling, especially if you know when it should end the input. Now it will end on any non-integer input line
int i = scanner.nextInt();
// for (int i = scanner.nextInt(); i % 4 == 0; i = scanner.nextInt()) {
// for (boolean bull = true; bull == true; bull ^= true) {
if (((i % 4) == 0) && (i > currentMax)) {
currentMax = i;
// saved -= saved2;
// saved += i;
// saved2 += i;
// }
}
}
System.out.println(currentMax); // moved out of "for" or "while" cycles. Print the value after the input has ended.
}
}

Subtraction in Java value shortage

I encounter a difficult problem. I am looking for a suggestion how to approach in this problem. I have three field in my dataset. I want to perform a subtraction.The problem is like that.
Time(s) a x
1 0.1 0.2
2 0.4
3 0.6
4 0.7
5 0.2 0.9
I need to perform a subtraction from (a-x). But the method of subtraction is like that at time 1s a has value 0.1. The operation will be (0.1-0.2) 1st iteration. 2nd iteration (0.1-0.4). 3rd iteration (0.1-0.6).4th iteration (0.1-0.7) But in 2nd iteration it will be (0.2-0.9).
This is my problem statement. I want to write down this code in Java. I don't need Java code. I can write it down myself. I need a suggestion how to proceed in this approach?. One thought is that creating array for each variable. But then stuck on loop. How the loop iterated? It is clear array a is static until it get next value, which is available at Time 5s.
This will depend on how large is your input file:
If the dataset fits into memory load it as either 2 separate array or as one array of Row objects with a and x as fields. After that it's simple iteration remembering what was the last row that contained a to use it when a is missing.
If the dataset is large it's better to read it using BufferedReader and only remember the last encountered a and x. This will greatly reduce the memory consumption and would be the preferred approach.
If a changes every 4 numbers you can use time's / 4 + 1 to get value from small array of a.
If a changes not every 4 numbers, then I suggest to use full array filled with same values.
Now that I see you're not using a database and just reading from a file, maybe try this
Just keep the old value of a until a new value can overwrite it.
This is memory efficient since it parses line by line.
public static List<Double> parseFile(String myFile) throws IOException {
List<Double> results = new ArrayList<>();
try (BufferedReader b = new BufferedReader(new FileReader(myFile));) {
b.readLine(); // ** skip header?
String line;
Integer time = null;
Double a = null;
Double x = null;
for (int lineNum = 0; (line = b.readLine()) != null; lineNum++) {
// ** split the data on any-and-all-whitespace
final String[] data = line.split("\\s+");
if (data.length != 3)
throw new RuntimeException("Invalid data format on line " + lineNum);
try {
time = Integer.valueOf(data[0]);
if (!data[1].trim().isEmpty()) {
a = Double.valueOf(data[1]);
}
if (!data[2].trim().isEmpty()) {
x = Double.valueOf(data[2]);
}
} catch (Exception e) {
throw new RuntimeException("Couldn't parse line " + lineNum, e);
}
if (a == null || x == null) {
throw new RuntimeException("Values not initialized at line " + lineNum);
}
results.add(Double.valueOf(a.doubleValue() - x.doubleValue()));
}
}
// ** finished parsing file, return results
return results;
}

Why is there no output from the While loop in my code, despite everything else working?

I made this program in java, on the BlueJ IDE. It is meant to take a number in the decimal base and convert it into a base of the users choice, up till base 9. It does this by taking the modulus between two numbers and inserting it into a string. The code works till the input stage, after which there is no output. I am sure my maths is right, but the syntax may have a problem.
My code is as follows:
import java.util.*;
public class Octal
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int danum = 0;
int base = 0;
System.out.println("Please enter the base you want the number in (till decimal). Enter as a whole number");
base=in.nextInt(); //This is the base the user wants the number converted in//
System.out.println("Enter the number you want converted (enter in decimal)");
danum=in.nextInt(); //This is the number the user wants converted//
while ( danum/base >= base-1 && base < danum) {
int rem = danum/base; //The number by the base//
int modu = danum % base;//the modulus//
String summat = Integer.toString(modu);//this is to convert the integer to the string//
String strConverted = new String();//Making a new string??//
StringBuffer buff = new StringBuffer(strConverted);//StringBuffer command//
buff.insert(0, summat); //inserting the modulus into the first position (0 index)//
danum = rem;
if ( rem <= base-1 || base>danum) {//does the || work guys?//
System.out.println(rem + strConverted);
}
else {
System.out.println(strConverted);
}
}
}
}
I am very new to Java, so I am not fully aware of the syntax. I have done my best to research so that I don't waste your time. Please give me suggestions on how to improve my code and my skill as a programmer. Thanks.
Edit (previous answer what obviously a too quick response...)
String summat = Integer.toString(modu);
String strConverted = new String();
StringBuffer buff = new StringBuffer(strConverted);
buff.insert(0, summat);
...
System.out.println(strConverted);
Actually, strConverted is still an empty string, maybe you would rather than display buff.toString()
But I don't really understand why making all of this to just display the value of modu. You could just right System.out.println(modu).
I assume that you want to "save" your value and display your whole number in one time and not each digit a time by line.
So you need to store your number outside of while loop else your string would be init at each call of the loop. (and print outside)
So, init your StringBuffer outside of the loop. you don't need to convert your int to String since StringBuffer accept int
http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#insert-int-int-
(You could even use StringBuilder instead of StringBuffer. It work the same except StringBuffer work synchronized
https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
Your if inside the loop is a specific case (number lower than base) is prevent before the loop since it's the opposite condition of your loop. (BTW : rem <= base-1 and base>danum are actually only one test since rem == danum at this place)
so :
StringBuffer buff = new StringBuffer();
if(base > danum) {
buff.append(danum);
} else {
while (danum / base >= base - 1 && base < danum) {
int rem = danum / base;
int modu = danum % base;
buff.insert(0, modu);
danum = rem;
}
if(danum > 0) {
buff.insert(0, danum);
}
}
System.out.println(buff.toString());
I would also strongly recommand to test your input before running your code. (No Zero for base, no letters etc...)
2 Things
do a lot more error checking after getting user input. It avoids weird 'errors' down the path
Your conversion from int to String inside the loop is wrong. Whats the whole deal summat and buff.... :: modifying the buffer doesnt affect the strConverted (so thats always empty which is what you see)
try to get rid of this. :)
error is logic related
error is java related
Your code has the following problems:
Firstly, you have declared and initialized your strConverted variable (in which you store your result) inside your while loop. Hence whenever the loop repeats, it creates a new string strConverted with a value "". Hence your answer will never be correct.
Secondly, the StringBuffer buff never changes the string strConverted. You have to change your string by actually calling it.
You print your result inside your while loop which prints your step-by-step result after every repetition. You must change the value of strConverted within the loop, nut the end result has to be printed outside it.

Line Not Found on while loop?

I've been trying to get this to work for a while. I'm putting in three parallel empty arrays and it errors out saying that there is no line found. It ONLY works when I change the while statement to the number of elements. I am trying to make arrays that are the size of 15, but only fill the first ten array portions.
Sorry if it sounds complicated, but basically I'm trying to say that the size of the array is 15, I only have 10 things to enter in the array, and the rest of them should be blank.
while (text.hasNext() && c < nameArray.length) {
nameArray[count] = text.nextLine();
intArray[count] = text.nextDouble();
doubleArray[count] = text.nextInt();
text.nextLine();
c++;
}
This does not work.
while (text.hasNext() && c < 9) {
nameArray[count] = text.nextLine();
intArray[count] = text.nextDouble();
doubleArray[count] = text.nextInt();
text.nextLine();
c++;
}
This does.
Your read the file TWICE within a single loop. Remove the 2nd read:
fileText.nextLine();
Of course it doesn't work. If you need to cycle to the max between fileText length and gameArray length, you should use or instead of and and use an if in the loop.
Try something like this:
while (fileText.hasNext() || count < gameArray.length) {
if (!fileText.hasNext()) {
gameArray[count] = "";
priceArray[count] = 0;
stockArray[count] = 0;
} else {
gameArray[count] = fileText.nextLine();
priceArray[count] = fileText.nextDouble();
stockArray[count] = fileText.nextInt();
fileText.nextLine();
}
count++;
}
Your issue is not with the length of the array but with fileTest.nextLine(). After a certain point there is no nextLine() available. It works for the 1st 9 times but I guess all the lines are exhausted before you reach array.length. I would suggest just one condition in your while loop:
while(fileText.hasNext()) {
}
This way you would fill in only the amount actually present.
Add another check with the second fileText.nextLine() to ensure that there is a line to read.
while (fileText.hasNext() && count < gameArray.length) {
gameArray[count] = fileText.nextLine();
priceArray[count] = fileText.nextDouble();
stockArray[count] = fileText.nextInt();
if ( fileText.hasNext() )
fileText.nextLine();
count++;
}
In the first version of your code, your try to read input 15 times, but it is entered only 10 times. So the scanner tries to read a new line but it doesn't exist.

Java add line to specific part of text file

COMMENTS BELOW ARE ANSWERING ANOTHER QUESTION, THIS IS THE ONLY WAY FOR ME TO ASK NEW QUESTION...
Okay. My program is like writing info on a .txt file. Currently it is writing info to end of the text file like so:
t/1/15/12
o/1/12/3
o/2/15/8
... (lots of lines like this.. all with different numbers)
o/1/16/4
Then.. when I add line using:
BufferedWriter fw = new BufferedWriter(new FileWriter(new File("C://Users/Mini/Desktop/Eclipse/Japda/map/" +Numbers.map +".txt"), true));
fw.newLine();
fw.write(RightPanel.mode.charAt(0) +"/" +ID +"/" +Numbers.middlex +"/" +Numbers.middley);
fw.close();
It adds the line I want to but currently to the end of the text file.. However I would like it to write that line to a specific part of the text files.. I already do know the number of the line I want to write it.. (It is calculated depending on other lines..) :D Is there any way to do it? Or what would be the best way to edit one specific line in the middle of that text file?
To achieve what you require, you would need to use a RandomAccessFile. Steps:
First create a RandomAccessFile then:
Create a variable called lineStart which is initially set to 0
(beginning of the file)
Read in the file line by line using readline
Check whether it is the required line that you wish to insert before
If it is the correct place, then lineStart will hold the position
just before the line you wish to insert before. Use seek to
position you at the correct place by initially using seek(0) to
position you at the start of the file, then seek(lineStart) to get
the required position. You then use writeChars to write to the file.
Remember that you have to explicitly write the newline.
If it is not where you wish to insert then call getFilePointer, and
store value in lineStart
REPEAT STEPS 2-5 UNTIL YOU ARRIVE AT THE DESIRED PLACE FOR INSERTION
You want a do-while loop:
do {
//code
} while (expression);
Source:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html
You probably want something like this:
int[] done = new int[100];
int randomquestion;
do{
randomquestion = (int)(Math.random() * 83 + 1);
if(done[randomquestion] != 1)
{
//ask random question
//if answer is correct, set done[randomquestion] = 1
//else just let do-while loop run
}
//check if all questions are answered
} while (!areAllQuestionsComplete(done));
Here is the method areAllQuestionsComplete(int[]):
private boolean areAllQuestionsComplete(int[] list)
{
for(int i = 0; i<list.length; i++)
{
if(list[i] != 1)
{
return false;//found one false, then all false
}
}
return true;//if it makes it here, then you know its all done
}
Looking at your latest code:
for(int i = 0; i<done.length; i++)
{
done[i] = 0;//need default values else wise itll just be NULL!!!
}
do{
ran = (int)(Math.random() * 83 + 1);
//before entering the do-while loop, you must set default values in the entire done[] array
if(done[ran] != 1)
{
//ask random question
//if answer is correct, set done[ran] = 1
//else just let do-while loop run
if (ran == 1) { //1
question = "kala";
rightanswer = "fish";}
if (ran == 2) { //2
question = "peruna";
rightanswer = "potato";}
if (ran == 3) { //3
question = "salaatti";
rightanswer = "cabbage";}
if (ran == 4) { //4
question = "kalkkuna";
rightanswer = "turkey";}
if (ran == 5) { //5
question = "kia";
rightanswer = "tikku";}
//YOU MUST HAVE EVERY CONDITION COVERED
//say your random number makes the number 10
//you dont set question to anything at all (hence getting null!)
System.out.println(question);
System.out.print("Vastaus?: ");
answer = in.readLine();
//if (answer == rightanswer){
//must use .equals with Strings...not ==
if (answer.equals(rightanswer)){
right++;
done[ran] = 1;}
else{wrong++;}
}
//check if all questions are answered
} while (!areAllQuestionsComplete(done));//use the method I wrote!
EDIT:
You must put default values in the array. When you create an array, the default value is null.
int[] done = new int[100];//create array but everything is null
for(int i = 0; i<done.length; i++)
{
done[i] = 0;//need default values else wise it'll just be NULL!!!
}
//must be done before the do-while loop starts
Finally, make sure your random number generator picks the correct range in numbers. If you have an array that is size 100, then it's indexes will be 0-99. This means there is no done[100]. It goes from done[0] to done[99].
If you have done[] be a size of 5, then it will range from done[0] to done[4]. That means you should randomly generate like this:
randomquestion = (int)(Math.random() * 5 );

Categories

Resources