If i have the following input:
sometext 23,1 -54.2 42
sometext 42,6 32 -56
How do i read firstly only the string and then the numbers.
for(int i = 0 ; i < numLines ; i++){
name = scanner.nextLine() // Here i want to save "sometext"
for(int j = 0 ; j < numNumbers ; j++){
numbers.add(scanner.nextFloat());
}
cities.add(new City(name, numbers));
numbers.clear();
}
Generally, don't ever call nextLine. It doesn't do what you think it does, and what it does do, is almost entirely useless. Yes, it shows up in every tutorial under the sun.1
Just call .next() if you want a string.
Thus, here, you should be invoking next() to read strings, and nextDouble to read doubles. Except you have utterly bizarre input, where sometimes commas show up and sometimes dots, to separate inputs. Did you make a typo when copying this over? If this is indeed your input, you can only use next(), and then you ahve to massage this broken crazy input first before turning it into numbers.
Also, you don't ever want to use float either. Just use double2. For everything. No it is not 'less efficient' or 'takes more memory'. It's just better, for free.
That was a typo, the input is consistent.
Ensure the scanner has the proper locale set, otherwise it will be expecting a , as separator instead of a . or vice versa. Failure to set locale means that your app will randomly not work depending on the configuration of the host system you're on, you usually do not want that. Use scanner.useLocale(Locale.ENGLISH) for example to do this.
Then:
name = scanner.next(); // returns "sometext"
for (int j = 0; j < numNumbers; j++) {
numbers.add(scanner.nextDouble());
}
It really is that mixed crazy
Then instead of .nextDouble:
String raw = scanner.next();
raw = raw.replace(",", ".");
numbers.add(Double.parseDouble(raw));
You also have a bug
Java is pass-by-value, but numbers is a reference. It's like me handing you, on a note, an _address to a building, and then me driving over there and burning the place to cinders. It doesn't matter that the address I gave you was written on a copied piece of paper you drove off with. If you follow your personal copy of that address, you still find a burnt out house.
So, when you write numbers.clear(), you're removing the numbers from that newly created city. What you want instead of numbers.clear(), which is java-ese for: "Take the piece of paper that you named numbers, which has an address written on it. Drive over there. Burn the house down.", and replace it with: numbers = new ArrayList<Double>() which is java-ese for: "Build a new house on a free spit of land. Take your piece of paper called numbers, and erase whatever is written on there. Now jot down the address to this newly built house.".
You want the second thing. Remember, . is java-ese for: Drive to the address written on here, and = is: Mess with the address itself, do not drive anywhere.
1] You don't need to follow this reasoning to use Scanner, but for those who'd like to know why I say this: Mixing nextLine and nextAnythingElse causes the dreaded problem where you generally just get an empty string back with nextLine. You can invoke a 'blank' nextLine (don't assign it to anything), but then your input processing is broken if the user ever hits that really big, centrally placed key on their keyboard, so that seems like a bad move, even if it is common advice. The real solution is to update the delimiter to \\R, but once you've done that, you don't need nextLine to read lines, just next will do it. Using only nextLine does work fine, but if that's what you want, just.. make a BufferedReader instead, Scanner is overkill. Conclusion: There are no scenarios where nextLine ever makes sense.
2] If some protocol explicitly says to use float, or you know all about IEEE style floating point numbers, you know enough to know when you can ignore this advice. Until you do, heed it.
This code will do the trick:
for(int i = 0 ; i < numLines ; i++){
name = scanner.next();
for(int j = 0 ; j < numNumbers ; j++){
numbers.add(scanner.nextFloat());
}
cities.add(new City(name, numbers));
numbers.clear();
}
Related
I have a method that loops through a file to find the number of lines.
static int findFileSize(Scanner f){
System.out.println("Got to counter:");
String str;
int line_count = 0;
while(f.hasNextLine()) {
line_count++;System.out.println(line_count);
//str = f.nextLine();
}System.out.println("File size: " + line_count);
return line_count;
}//end findFileSize
When i don't include the str = f.nextLine();, i can see it indexing indefinitely. What causes this to happen? And is there a way of finding the number of lines in a .txt file without needing to unnecessarily store a data into a string?
What causes this to happen?
You aren't reading anything from the Scanner, you're just asking it if you will be able to read something.
If you walk into a shop and ask if they have, say, carrots, if the answer is "yes", but you don't buy any carrots, the shop still has carrots. So, if you walk out and walk in to ask again, they will still have the carrots, so they will again answer "yes" (unless somebody else has bought them).
You have to "buy the carrots" by using f.nextLine().
without needing to unnecessarily store a data into a string?
You don't have to store it in a variable:
f.nextLine();
will read the String and immediately discard it. But there isn't really a huge difference between this and storing it in a variable: the variable only keeps the contents of the last-read line anyway. (But since you don't give str an initial value, it's not definitely assigned after the loop, so you can't read its value after the loop in any case).
I have written a code in JESS. I am now running the code from Java. I have run to this problem that I want to have the engine.execute("") command in a for loop.
My example code is :
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
r.executeCommand("(answer(ident headers.get(i)(text patientData.get(j).get(i))");
}
}
where answer is a deftemplate in JESS with two slots. I am reading a text file in Java and inserting the values in the slots of the deftemplate.
Thanks,
Ali
If answer is a deftemplate with slots ident and text, the following snippet looks like the construction of a fact:
(answer(ident headers.get(i)(text patientData.get(j).get(i))
A bare fact does not represent a Jess command that can be executed via Rete.executeCommand.
You shouldn't use the deprecated method executeCommand; use eval.
Your parentheses aren't balanced properly, 6 opening parentheses against 4 closing ones.
Assuming that headers is a List<String> in your Java application, you cannot simply throw a Java method call at Jess, which doesn't understand Java syntax in the first place and (presumably) doesn't know about the pojo header at all.
The same is true for the pojo patientData.
While you might pass objects from your Java program to the Jess engine, this is absolutely impossible for simple variables like i and j.
Considering all of this (most of which is easy to learn from the excellent Jess manual), using
r.eval( "(assert (answer (ident \"" +
headers.get(i) +
"\")(text \"" +
patientData.get(j).get(i) +
"\")))" );
might have a chance of succeeding and indeed insert a new fact into working memory.
My roommate's teacher gave them a assignment to implement string length method in JAVA?
we have thought out two ways.
Check the element,and when get the out of bounds exception,it means the end of string,we catch this exception,then we can get the length.
Every time a string is pass to calculate the length,we add the special character to the end of it,it can be '\0',or "A",etc..
But we all think this two way may can finish the assignment,but they are bad(or bad habit to do with exception),it's not cool.
And we have googled it,but don't get what we want.
Something like this?
int i = 0;
for (char ch : string.toCharArray()) {
i++;
}
The pseudo-code you probably want is:
counter = 0
for(Character c in string) {
counter = counter + 1
}
This requires you to find a way to turn a Java String into an array of characters.
Likely the teacher is trying to make his or her students think, and will be satisfied with creative solutions that solve the problem.
None of these solutions would be used in the real world, because we have the String.length() method. But the creative, problem-solving process you're learning would be used in real development.
"1. Check the element,and when get the out of bounds exception,it means the end of string,we catch this exception,then we can get the length."
Here, you're causing an exception to be thrown in the normal case. A common style guideline is for exceptions to be thrown only in exceptional cases. Compared to normal flow of control, throwing an exception can be more expensive and more difficult to follow by humans.
That said, this one of your ideas has a potential advantage for very long strings. All of the posted answers so far run in linear time and space. The time and/or additional space they take to execute is proportional to the length of the string. With this approach, you could implement an O(log n) search for the length of the string.
Linear or not, it's possible that the teacher would find this approach acceptable for its creativity. Avoid if the teacher has communicated the idea that exceptions are only for exceptional cases.
"2. Every time a string is pass to calculate the length,we add the special character to the end of it,it can be '\0',or "A",etc.."
This idea has a flaw. What happens if the string contains your special character?
EDIT
A simple implementation would be to get a copy of the underlying char array with String.toCharArray(), then simply take its length. Unlike your ideas, this is not an in-place approach - making the copy requires additional space in memory.
String s = "foo";
int length = s.toCharArray().length;
Try this
public static int Length(String str) {
str = str + '\0';
int count = 0;
for (int i = 0; str.charAt(i) != '\0'; i++) {
count++;
}
return count;
}
What about:
"your string".toCharArray().length
I have the following code, please keep in mind I'm just starting to learn a language and a such have been looking for fairly simple exercises. Coding etiquette and critics welcome.
import java.util.*;
import java.io.*;
public class Tron
{
public static void main(String[] args) throws Exception
{
int x,z,y = 0;
File Tron= new File("C:\\Java\\wordtest.txt");
Scanner word = new Scanner(Tron);
HashMap<String, Integer> Collection = new HashMap<String, Integer>();
//noticed that hasNextLine and hasNext both work.....why one over the other?
while (word.hasNext())
{
String s = word.next();
Collection.get(s);
if (Collection.containsKey(s))
{
Integer n = Collection.get(s);
n = n+1;
Collection.put(s,n);
//why does n++ and n+1 give you different results
}else
{
Collection.put(s,1);
}
}
System.out.println(Collection);
}
}
Without the use of useDelimiter() I get my desired output based on the file I have:
Far = 2, ran = 4, Frog = 2, Far = 7, fast = 1, etc...
Inserting the useDelimiter method as follows
Scanner word = new Scanner(Bible);
word.useDelimiter("\\p{Punct} \\p{Space}");
provides the following output as it appears in the text file shown below.
the the the the the
frog frog
ran
ran ran ran
fast, fast fast
far, far, far far far far far
Why such a difference in output if useDelimiter was supposed to account for punctuation new lines etc? Probably pretty simple but again first shot at a program. Thanks in advance for any advice.
With word.useDelimiter("\\p{Punct} \\p{Space}") you are actually telling the scanner to look for delimiters consisting of a punctuation character followed by a space followed by another whitespace character. You probably wanted to have one (and only one) of these instead, which would be achieved by something like
word.useDelimiter("\\p{Punct}|\\p{Space}");
or at least one of these, which would look like
word.useDelimiter("[\\p{Punct}\\p{Space}]+");
Update
#Andrzej nicely answered the questions in your code comments (which I forgot about), however he missed one little detail which I would like to expand / put straight here.
why does n++ and n+1 give you different results
This obviously relates to the line
n = n+1;
and my hunch is that the alternative you tried was
n = n++;
which indeed gives confusing results (namely the end result is that n is not incremented).
The reason is that n++ (the postfix increment operator by its canonical name) increments the value of n but the result of the expression is the original value of n! So the correct way to use it is simply
n++;
the result of which is equivalent to n = n+1.
Here is a thread with code example which hopefully helps you understand better how these operators work.
Péter is right about the regex, you're matching a very specific sequence rather than a class of characters.
I can answer the questions from your source comments:
noticed that hasNextLine and hasNext both work.....why one over the other?
The Scanner class is declared to implement Iterator<String> (so that it can be used in any situation where you want some arbitrary thing that provides Strings). As such, since the Iterator interface declares a hasNext method, the Scanner needs to implement this with the exact same signature. On the other hand, hasNextLine is a method that the Scanner implements on its own volition.
It's not entirely unusual for a class which implements an interface to declare both a "generically-named" interface method and a more domain-specific method, which both do the same thing. (For example, you might want to implement a game-playing client as an Iterator<GameCommand> - in which case you'd have to declare hasNext, but might want to have a method called isGameUnfinished which did exactly the same thing.)
That said, the two methods aren't identical. hasNext returns true if the scanner has another token to return, whereas hasNextLine returns true if the scanner has another line of input to return.
I expect that if you run the scanner over a file which doesn't end in a newline, and consume all but one of the tokens, then hasNext would return true while hasNextLine would return false. (If the file ends in a newline then both methods will behave the same - as there are more tokens if and only if not all lines have been consumed - but they're not technically the same.)
why does n++ and n+1 give you different results
This is quite straightforward.
n + 1 simply returns a value that is one greater than the current value of n. Whereas n++ sets n to be one greater, and then returns that value.
So if n was currently 4, then both options would return 5; the difference is that the value of n would still be 4 if you called n + 1 but it would be 5 if you called n++.
In general, it's wise to avoid using the ++ operator except in situations where it's used as boilerplate (such as in for loops over an index). Taking two or three extra characters, or even an extra line, to express your intent more clearly and unambiguously is such a small price that it's almost always worth doing.
I've two types of input data
a b c d e...
Here a, b, and so on are values to be read. All are of same data types which may be short, int, long, double. All values are separated by one or more spaces. We've given these on a single line and we don't know how many are there. Input ends with newline. In second case we're given count as a first variable "n" and then n variables follow. e.g. for n=5, it looks like this.
n a b c d e
This could be done with Scanner but I've heard reading input with scanner is slower than bufferedReader method. I'm looking for any possible way for doing this other than using Scanner class. I'm new to Java. Please help.
I would get something which works first. Once you have an understanding of the bottleneck, only then is it worth trying to optimise it.
To answer your question, IMHO, the fastest way to read the data is to use a memory mapped file and parse the ByteBuffer assuming you have ASCII 8-bit byte data (a reasonable assumption for numbers) avoiding using the built in parsers altogether. This will be much faster but also a lot for more complicated and complete overkill. ;)
If you want examples of how to parse numbers straight from a ByteBuffer Java low level: Converting between integers and text (part 1) To go faster you can use the Unsafe class, but that is not standard Java.
Especially when you're new to a language or environment I would suggest to start out with something easily understood yet functional like
String inputline = "n a b c d e";
// Obtain real inputline eg by reading it from a file via a reader
inputline = someBufferedReaderDefinedElsewhere.readLine();
String[] parts = inputline.split(" ");
// easiest for case 1
for (String part : parts) {
...
}
// easiest for case 2
int numberToRead = Integer.parseInt(parts[0]);
// not < but <= because you start reading at element 1
for (int ii=1;ii<=numberToRead;ii++) {
...
}
Of course to be completed with a healthy dose of error checking!
Afterwards, if you determine (with proof, eg the output of the profiling of your app) that that part of the code is in fact responsible for an unreasonable amount of CPU consumption you can start thinking about faster, more custom ways of reading the data. Not the other way around.