Method never reaching an if statement despite, its conditions being met - java

I'm trying to scan through a txt.file with name and gender and my code is supposed to take the user input of a name and gender, read through the txt file to see if that combination exists, and then either return the information (if there is a match) or say there was no match.
I put place holder S.O.P statements just to help debug and it shows that it reaches the return statement where it's supposed to return the info from the txt file because it's found that match, but the method fails to pass the if statement where it returns the user info once there is a match, even if the info the user puts in is one that is supposed to have a match.
The code is here :
public class Draft {
public static void main(String[] args) throws FileNotFoundException {
Scanner console = new Scanner(System.in);
Scanner input = new Scanner(new File("names.txt"));
ProgramIntro();
System.out.print("name? ");
String userName = console.nextLine();
System.out.print("sex (M or F)? ");
String userGender = console.nextLine();
System.out.print(searchInfo (input, userName, userGender));
}
//searches file for user input match and returns value depending on whether a match exists
public static String searchInfo (Scanner input, String userName, String userGender) {
//goes through the file until there are no more entries
while (input.hasNextLine()) {
System.out.print("blach");
//concatenates one line of file into one string
String line = input.nextLine();
//turns the focus into just one line
Scanner lineScan = new Scanner(line);
//runs loop just on one single line
while (!lineScan.hasNextInt()) {
System.out.print("bafdjkf");
//sets the first thing in a line (the name) as String babyName
String babyName = lineScan.next();
System.out.print(babyName);
//sets the first thing in a line (the name) as String gender
String gender = lineScan.next();
System.out.println(gender);
if (userName.equalsIgnoreCase(babyName) && userGender.equalsIgnoreCase(gender)) { //THE PROBLEM LINE
System.out.print("jgfgfgfgfgfg");
System.out.println(line);
return line;
}
}
}
return "name/sex combination not found";
}
And it never reaches the if statement because the placeholder S.O.P in the if statement never prints.
blachbafdjkfCaleighF //Caleigh is the name we tested
blachbafdjkfRisaF
blachbafdjkfRoninM
blachbafdjkfFronaF
blachbafdjkfDanaF
blachbafdjkfJesusM
blachbafdjkfHarleyM
blachbafdjkfJadaF
Where is the logic error in this program?

How come the program goes back to the first while loop and starts scanning through the rest of the names in the list despite finding a match?
Because you call that method twice:
searchInfo (input, userName, userGender);
System.out.print(searchInfo (input, userName, userGender));
You have to either skip the first call or store the result of the first call in a variable and instead of calling the method a second time print that variable.

Related

What does hasNext() in a While do?

I'm new to Java and I'm trying to read data from a .txt file. I've implemented a Scanner object 'in' Scanner in=new Scanner("file.txt"); and then down the code a while loop to traverse through the content of the file.There are multiple rows of data in the file and in each row there are three strings (security number ,First name ,Last name : 01 Thomas Anderson)
while(in.hasNext()){
String ss = in.next();
String FName=in.next();
String LName=in.next();
System.out.printf("SSN: %s, FirstName: %s, LastName: %s \n",ss,FName,LName);
}
So, what does the hasNext() method do? Does it look for end of the row or for the last row in the file or.... ?
Please elaborate on the working of the above snippet (mentioning the next() method too).
I do recommend looking at the Javadoc, but I'll explain it for you as simple as I can.
Basically, the hasNext() method returns true if the given document contains another string. Hence why the snippet will loop if said document has another string. Once there are no more Strings in the entire document, hasNext() returnsfalse.
Here's an example of the next() method:
String myString = myScanner.next();
This makes myString equal to the next string in the given document.
Javadoc says:
hasNext
public boolean hasNext()
Returns true if this scanner has another token in its input. This
method may block while waiting for input to scan. The scanner does not
advance past any input.
next
public String next()
Finds and returns the next complete token from this scanner. A
complete token is preceded and followed by input that matches the
delimiter pattern. This method may block while waiting for input to
scan, even if a previous invocation of hasNext() returned true.
To read all your file rows you'll have to check if there are tokens every line. Then you call 3 times the next method since you know there will be 3 tokens per line:
import java.io.File;
import java.util.Scanner;
public class FLoader {
public void load(String path) {
Scanner in = null;
try {
in = new Scanner(new File(path));
while (in.hasNext()) {
String ss = in.next();
String FName = in.next();
String LName = in.next();
System.out.printf("SSN: %s, FirstName: %s, LastName: %s \n", ss, FName, LName);
}
} catch (Exception e) {
System.err.println("Loading file failed");
e.printStackTrace();
System.exit(-1);
}
}
}

Try-Catch While loop getting stuck on No Such Element Exception

public static ArrayList<Student> readStudentRecords(String fileName) throws FileNotFoundException {
Scanner input = new Scanner(new FileInputStream(fileName));
ArrayList<Student> students = new ArrayList<Student>();
input.useDelimiter(",");
String firstName, lastName, id, email, hashPW;
int maxCredits = 0;
while (input.hasNextLine()) {
try {
input.nextLine();
firstName = input.next();
lastName = input.next();
id = input.next();
email = input.next();
hashPW = input.next();
maxCredits = input.nextInt();
Student student = new Student(firstName, lastName, id, email, hashPW, maxCredits);
students.add(student);
} catch (IllegalArgumentException e) {
System.out.println("Illegal Argument Exception");
input.next();
} catch (NoSuchElementException e) {
System.out.println("No Such Element Exception");
input.next();
}
}
input.close();
return students;
}
I am creating a program that reads a text file that lists a students first name, last name, id, email, hashed password, and max credits. Each line of the text file has a full suite of each element seperated by commas. I want the program to read the file, create a student object from each line (I have created and tested the Student class, including all getters and setters), and arrange the student objects in an array list. The program is getting looped at NoSuchElementException, and is only reading the first line of the text file, and ignoring the next 9. I'm not sure what exact format my try-catch statement should be in to ensure that it will not infinitely loop.
The first line in your try block reads the available line and then throws it away:
while (input.hasNextLine()) {
try {
input.nextLine();
...
The reason you are getting the exception is that you throw away the line you just checked is there and then continue trying to read from input, whether or not there is anything after the line you just trashed.
You should do one of these:
Capture that line and parse it (rather than calling input.next() or input.nextInt() in the following lines); or
Eliminate the call to input.nextLine() and hope that each line properly conforms to the layout you expect; or
Replace your entire while loop with calls to a csv parsing utility (as #Scary Wombat suggests in a comment).
with Scanner you need to check if there is a next line with hasNextLine()
so the loop becomes
while(sc.hasNextLine()){
str=sc.nextline();
//...
}
this code this depends on whether the input is properly formatted
You're calling nextLine() and it's throwing an exception when there's no line, exactly as the javadoc describes. It will never return null
The other answers look right to me. Just to add some more that hasn't already been said:
When catching an exception, make sure not to swallow it (that is ignore it) by just printing out that information. If anything, you're losing information that the e.printStackTrace() would have exposed, that is tell you exactly on which line it's failing on.
The actual error that you have is because the scanner is using , as the delimiter, and so that means the last value will be something like 10\n (if 10 is the max credits for a row). You could get around this by doing something like: String[] words = scanner.nextLine().split(","); instead of processing it word by word with the scanner.

String array name search

So I have a file which has all presidents in it - their first name, middle initial (if any), and last name.
The file needs to be read in, and a user can enter a president's name to search for it, and that president should be displayed.
I have it displaying the president if a user searches by first name or by last name, but not by both.
For example, the external file contains:
George,Washington,(1789-1797)
Franklin,D.,Roosevelt,(1933-1945)
... and so on with all the presidents
I need the user to be able to either type in the first name, the last name, or both first and last name and get the desired result (the date is irrelevant for the most part).
Tried lots of different things, but not getting there as far as displaying the president if user searches by first and last name.
Here is what I got so far:
public class NameSearch {
public static void main(String[] args) throws IOException {
try {
// read from presidents file
Scanner presidentsFile = new Scanner(new File("Presidents.txt"));
// scanner for user input
Scanner keyboard = new Scanner(System.in);
// create array list of each line in presidents file
ArrayList<String> presidentsArrayList = new ArrayList<String>();
// prompt user to enter a string to see if it matches with a president's name
System.out.println("Enter a search string of letters to find a president match: ");
// store user input
String userInput = keyboard.nextLine();
// add president file info to array list linesInPresidentFile
while (presidentsFile.hasNextLine()) {
presidentsArrayList.add(presidentsFile.nextLine());
} // end while loop
String presidentNamesArray[] = presidentsArrayList.toArray(new String[presidentsArrayList.size()]);
String results = searchArray(presidentNamesArray, userInput);
//System.out.println("\nThe presidents who have \"" + userInput + "\" as part of their name are: ");
} catch (FileNotFoundException ex) {
// print out error (if any) to screen
System.out.println(ex.toString());
} // end catch block
} // end main
// method to search for a specific value in an array
public static String searchArray(String array[], String value) {
for (int i = 0; i < array.length; i++) {
if (array[i].toLowerCase().contains(value.toLowerCase())) {
String splitter[] = array[i].split(" ,");
System.out.println(Arrays.toString(splitter));
}
}
return Arrays.toString(array);
}
}
There is another way in which I might have implemented this.Read the file inputs and stored them as objects (class with lname, fname and year perhaps). In this way you can search for lname from user input, match it up with its corresponding fname (as same objects). The creation can be done once and searching can be done in a while loop implementing users consent of continuing the search.
//define your class like this:
static int i; //to keep a track of number of objects
public class dummy{
string fname;
string lname;
string year;
};
while the file content exists:
read the line
dummy dobj[i++] = new dummy();//allocate memory for the object
split the different parameters (fname, lname, year) from the read line
put these read parameters into the object
dobj[i].fname = first;
dobj[i].lname = second;
dobj[i].year = y;
//ask your user to enter the query in a specified format
//if he enters lname, compare your input to all the object's lname, and so on
//in case of lname && fname, compare your input to the lname first and then check for the corresponding objects fname, if they match.. display
Actually, there are many ways in which you can achieve what you wish to program. You can ask use the array list indices to solve it. If you take in the input from the user in a particular format, you can map it to the index in that list. Further, if you want to use first name and last name together, you may use these index representing the first and last name to come from same list.
The reason you may have problems searching by both first and last names is because you have to match your input exactly (ignoring case of course). What I mean is if you use George Washington as input, your program will not find a match for the George,Washington,(1789-1797) line. This is because your program treats George Washington as one string. Note: the input is missing the comma, so it will not be considered a substring of George,Washington,(1789-1797). If you used George,Washington as your input string, then your program would print the George Washington line. Your program just searches if the input string is a substring of any of the lines in your file. It does not search for a first name or last name specifically. If you used in as your input string, then you would get a match for both George Washington and Franklin D. Roosevelt.What you could do is take your input data and split it and search for each of the terms. You can either accept lines that match all of the terms provided, or at least one of the terms provided.
public static String searchArray(String array[], String value) {
// Uses both blank spaces and commas as delimiters
String[] terms = value.toLowerCase().Split("[ ,]");
for (int i = 0; i < array.length; i++) {
String line = array[i].toLowerCase();
boolean printIfAllMatch = true;
boolean printIfAtLeastOneMatches = false;
for(int j = 0 ; j < terms.length; j++) {
// Check that all terms are contained in the line
printIfAllMatch &= line.Contains(terms[j]);
// Check that at least one term is in the line
printIfAtLeastOneMatches |= line.Contains(terms[j]);
}
String splitter[] = array[i].split(" ,");
if (printIfAllMatch) {
System.out.println(Arrays.toString(splitter));
}
if(printIfAtLeastOneMatches) {
System.out.println(Arrays.toString(splitter));
}
}
//I'm not sure why you're returning the original array as a string
//I would think it would make more sense to return an Array of filtered data.
return Arrays.toString(array);
}
This does not take name ordering into account. If that's what you're going for, then I would suggest making a class and parsing each line in the file as an new object and trying to match the first term provided with the first name and second term provided with the last name, or something to that effect.

Why is indexOf() not recognizing spaces?

For this program it asks for the user to input their full name. It then sorts out the first name and last name by separating them at the space the put between the first and last name. However, indexOf() is not recognizing the space and only returns -1. Why is that? Thanks.
Here is the prompt off of PracticeIt:
Write a method called processName that accepts a Scanner for the console as a parameter and that prompts the user to enter his or her full name, then prints the name in reverse order (i.e., last name, first name). You may assume that only a first and last name will be given. You should read the entire line of input at once with the Scanner and then break it apart as necessary. Here is a sample dialogue with the user:
Please enter your full name: Sammy Jankis
Your name in reverse order is Jankis, Sammy
import java.util.*;
public class Exercise15 {
public static void main(String[] args) {
Scanner inputScanner = new Scanner(System.in);
processName(inputScanner);
}
public static void processName(Scanner inputScanner) {
System.out.print("Please enter your full name: ");
String fullName = inputScanner.next();
int space = fullName.indexOf(" "); // always return -1 for spaces
int length = fullName.length();
String lastName = fullName.substring(space+1,length+1);
String firstname = fullName.substring(0, space);
System.out.print("Your name in reverse order is " + lastName + ", " + firstname);
}
}
As next will return the next token use nextLine not next to get the whole line
see http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#next()
When you do String fullName = inputScanner.next() you only read till the next whitespace so obviously there is no whitespace in fullName since it is only the first name.
If you want to read the whole line use String fullName = inputScanner.nextLine();

Displaying specific words in a .txt file using a scanner

I'm stuck and need your help (yes, it's homework), what I'm trying to do is get my code to read the contents in the text file and output the words by specific words. For example I want it to output all words that start with letter "g".
Here's a pseudocode code if I didn't explain that well:
BEGIN
Get the initial letter from the user
While there are more entries in the file
Get the next personal name
Get the next surname
Get the next year info
If the surname starts with the initial letter
Output the person name, surname and year info
End while
END
So far I've managed to get this done, and now I'm stuck where you output the names correctly. Any help or tutorials will be appreciated.
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class PrimeMinisters
{
public static void main(String[] args) throws FileNotFoundException
{
// ask the user for the first letter
Scanner keyboard = new Scanner(System.in);
System.out.print("What is the first letter? ");
String input = keyboard.next().toLowerCase();
char firstLetter = input.charAt(0);
// open the data file
File pmFile = new File ("OZPMS.txt");
// create a scanner from the file
Scanner pmInput = new Scanner (pmFile);
// read one line of data at a time, processing each line
while(pmInput.hasNext())
{
String names = pmInput.next();
System.out.println(names);
}
// be polite and close the file
pmInput.close();
}
}
I'd recommend using nextLine() over next(). From this you would then use the String's startsWith(String stringsequence) method which returns a boolean to get all the values beginning with the letter of your choice:
while(pmInput.hasNextLine())
{
String names = pmInput.nextLine();
System.out.println(names);
if(names.startsWith("g")) {
//the name begins with letter g do whatever
}
}
You can have a look at more methods for String here: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html
Since your requirements state to look at the surname's first letter, it will be easier to tokenize each line while you read it (while checking to see if the user input is the first letter of the surname). Assuming that the line is in the order that you stated above, the surname will be token #2 (index 1 of the array).
public class PrimeMinisters
{
public static void main(String[] args) throws FileNotFoundException
{
// ask the user for the first letter
Scanner keyboard = new Scanner(System.in);
System.out.print("What is the first letter? ");
String input = keyboard.next().toLowerCase();
char firstLetter = input.charAt(0);
// open the data file
File pmFile = new File ("OZPMS.txt");
// create a scanner from the file
Scanner pmInput = new Scanner (pmFile);
// read one line of data at a time, processing each line
while(pmInput.hasNextLine())
{
String names = pmInput.nextLine();
// Break line into tokens. This is assuming that there are only
// 3 strings per line in the following order (personal name, surname, yearinfo)
//
String[] info = names.split("\\s");
// Check 2nd string in line (since you are looking for the first character in
// the surname and not the personal name.
//
if(info[1].startsWith(input))
{
System.out.println(info[0] + "\t" + info[1] + "\t" + info[2]);
}
}
// be polite and close the file
pmInput.close();
}
}

Categories