String array list using Scanner - java

Edit: added the braces {} and an Eclipse screenshot
I have a problem with a simple assignment to create a class that has an array list to store words from the command-line, with each word appended to the end of the array list, then search the list for a specific word ("the") and prints location of the word's occurences, plus another method to return a new array list with the words at the positions specified by a number.
I wrote the code below. In Eclipse IDE, it doesn't show any errors, but when I tried to run the code by Run Configurations and enter this dummy text: "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.", it doesn't work. I'm not sure why, could you give me advice? Thank you!
import java.util.ArrayList;
import java.util.Scanner;
class Search {
ArrayList<String> list;
public Search(){
list = new ArrayList<String>();
}
public void read(){
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()) {
list.add(scanner.next());
}
scanner.close();
}
public void find(String word){
for(int i = 0; i < list.size(); i++) {
if(list.get(i).equalsIgnoreCase(word)) {
System.out.println(i);
}
}
}
public ArrayList<String> subsequence(int[] positions){
ArrayList<String> result = new ArrayList<String>();
for(int i = 0; i < positions.length; i++) {
if(positions[i] >= 0 && positions[i] < list.size()) {
result.add(list.get(positions[i]));
}
}
return result;
}
// Testing method within class again
public static void main(String[] args){
Search search = new Search();
search.read();
search.find("the");
for(String s : search.subsequence(new int[]{0, 3, 4}))
System.out.println(s);
}
}

As dear #Chris commented kindly use the braces while coding. I run your code in two different ways and I got the output.
First Way
If you want to use scanner.hashNext() with while then you should change your main() and read() like this
public static void main(String[] args) {
Search search = new Search();
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
sc.close();
search.read(line);
search.find("the");
for (String s : search.subsequence(new int[] { 0, 3, 4 })) {
System.out.println(s);
}
}
public void read(String line) {
Scanner scanner = new Scanner(line).useDelimiter("\\s");
while (scanner.hasNext()) {
list.add(scanner.next());
}
scanner.close();
}
A simple text scanner which can parse primitive types and strings using regular expressions.
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods.
The next() and hasNext() methods and their primitive-type companion methods first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext() and next() may block waiting for further input. Whether a hasNext() block has no connection to whether or not its associated next method will block.
Second Way
If you want to use StringTokenizer then you should have to change just read() to your existing code.
public void read(String line) {
Scanner scanner = new Scanner(System.in);
StringTokenizer st = new StringTokenizer(scanner.nextLine(), " ");
while (st.hasMoreElements()) {
list.add(st.nextElement().toString());
}
scanner.close();
}
It is always better to use StringTokenizer for the string. The StringTokenizer class allows an application to break a string into tokens.
A StringTokenizer object internally maintains a current position within the string to be tokenized. Some operations advance this current position past the characters processed. A token is returned by taking a substring of the string that was used to create the StringTokenizer object.
Reference : Scanner and StringTokenizer

Related

How can i compare a string in arraylist with char type of array

Recently i started learning java. And after some knowledge i starts with some program. so i create a Jumble Word game. it works but i have a problem. Here is my code....
import java.util.ArrayList;
import java.util.Scanner;
import java.util.*;
class JumbleWords
{
public static void main(String args[])
{
Scanner scan = new Scanner(System.in);
ArrayList <String>alist = new ArrayList<String>();
ArrayList <Character>chars = new ArrayList<Character>();
Random rd = new Random();
int listLimit,charLimit,value,ulimit=0,counter=0;
String string,temp;
alist.add("done");
alist.add("nest");
alist.add("rat");
alist.add("cat");
alist.add("hello");
alist.add("cycle");
alist.add("chain");
alist.add("paint");
alist.add("collect");
alist.add("your");
alist.add("gift");
alist.add("card");
alist.add("today");
alist.add("cheer");
alist.add("what");
alist.add("time");
alist.add("share");
alist.add("build");
alist.add("help");
alist.add("success");
alist.add("career");
alist.add("access");
alist.add("learn");
alist.add("course");
alist.add("year");
alist.add("expert");
alist.add("school");
alist.add("floor");
alist.add("season");
alist.add("education");
alist.add("spread");
listLimit = alist.size();
int i=0;
System.out.println();
System.out.println("How many JumbleWords you want to play...");
System.out.println("Max limit is "+listLimit);
ulimit = scan.nextInt();
scan.nextLine();
if(ulimit < listLimit )
{
while(i<ulimit )
{
value = rd.nextInt(listLimit);
string = alist.get(value);
for ( char c : string.toCharArray() )
{
chars.add( c );
}
Collections.shuffle(chars);
Collections.shuffle(chars);
System.out.println(chars);
System.out.println("\nEnter the correct order of the word.");
temp = scan.nextLine();
if(string.equalsIgnoreCase(temp)==true){
System.out.println("You Win......");
System.out.println("(*^*)");
System.out.println();
++counter;
}
else{
System.out.println("You Lose......");
System.out.println("The correct word is :-");
System.out.println(string);
System.out.println("(*_*)");
System.out.println();
}
chars.clear();
alist.remove(value);
i++;
}
System.out.println("Your Score is "+counter+" out of "+ulimit);
System.out.println();
}
else
{
System.out.println("Not enough words we have...");
System.out.println();
}
}
}
now in case of "CHAIN" is suffle and user must input chain for winning but "CHINA" is also a word with same chars. how can i build a logic for that.
You can compare the whole word:
while(i<ulimit )
{
value = rd.nextInt(listLimit);
string = alist.get(value);
if(string.equalsIgnoreCase(value)){
System.out.println("You Win......");
System.out.println("(*^*)");
System.out.println();
++counter;
}
...
First, your code is really not straight readable.
Variable names are very very bad chosen while you implement a specific matter :
a word game.
Besides you declare your variables too early and have also a too broad scope, which is error prone and don't easy the reading too.
How to understand these statements without reading the whole code ?
string = alist.get(value);
Or :
if(string.equalsIgnoreCase(temp)==true){
It should be something like:
String wordToGuess = wordsToGuess.get(value);
and :
if(wordToGuess.equalsIgnoreCase(userInput)){
Instead of using a List of String.
ArrayList <String>alist = new ArrayList<String>();
use a List of WordToGuess where each instance will store a List<String> anagrams where WordToGuess could be declared :
public class WordToGuess{
private List<String> anagrams;
...
public WordToGuess(String... anagrams){
this.anagrams = Arrays.asList(anagrams);
}
public String getAnyWord(){
return anagrams.get(0);
}
public boolean contains(String word){
return anagrams.contains(word.toLowerCase());
}
}
In this way you have just to check if the input of the user is contained in the List.
So
ArrayList <String>alist = new ArrayList<String>();
will become :
List<WordToGuess> wordsToGuess = new ArrayList<WordToGuess>();
Favor the interface in the variable type declaration over concrete class.
And you could populate your List in this way :
wordsToGuess.add(new WordToGuess("done", "node")); // two possibilities
wordsToGuess.add(new WordToGuess("nest")); // one
...
wordsToGuess.add(new WordToGuess("chain", "china")); // two
...
And the comparing input String with the expected String :
if(wordToGuess.equalsIgnoreCase(userInput)){
will become :
if(wordsToGuess.contains(userInput)){
It is better to keep the ignoring-case task in the provider class that in the client class that may forget it.

Eclipse JAVA String reverse - reversing 1 word which is pre-declared [duplicate]

This question already has answers here:
Reverse a string in Java
(36 answers)
Closed 5 years ago.
Like to know how to reverse a string value (1 word) which is pre-declared in the program. I mean not using user input or scanner.
Like to reverse a word "TRAIN" which is pre-declared in the program.
Have tried the below program but no results and no error also.
// QUERY PROGRAM NOT RUNNING - NO RESULT, NO ERROR.
// STRING REVERSE PROGRAM USING ARRAY
package abnpackage;
class Play {
void REVERSE (){
String [] INPUT_WORD = {"T","R","A","I","N"};
int Q;
for(Q=INPUT_WORD.length-1; Q>=0; Q=Q--);
System.out.print ("REVERSE VALUE" + INPUT_WORD[Q]);
}
public static void main(String[]args){
Play PL = new Play();
PL.REVERSE();
}
}
Problem in Q=Q-- and ; symbol after for cylce. Try this:
class Play{
void REVERSE (){
String [] INPUT_WORD = {"T","R","A","I","N"};
int Q;
for(Q=INPUT_WORD.length-1; Q>=0; Q--) {
System.out.print(INPUT_WORD[Q]);
}
}
public static void main(String[]args){
Play PL = new Play();
PL.REVERSE();
}
}
I'd like to offer a few suggestions.
Indent your code. It not only makes it easier for you to follow, but makes it easier for others to read your code.
Naming conventions. Use Title case for classes, camelCase for both variables and methods, and UPPER_CASE for constants.
Strings and characters. A String can be decomposed into an array of characters with the built-in method, String.toCharArray(). A character array is mutable, so is often used as an intermediate structure when converting a String from one state to another for tasks like ciphers or interview problems.
Encapsulation. If you can make your methods use only what is submitted to them through their method signature, and only output their return value, it's usually best. Prefer passing values over referencing constants in your utility methods to make them easier to follow.
package abnpackage;
class Play {
private static final String INPUT_WORD = "TRAIN";
private String reverse(String word) {
char[] letters=word.toCharArray();
StringBuilder sb=new StringBuilder();
for (int q=letters.length-1; q>=0; q--) {
sb.append(letters[q]);
}
return sb.toString();
}
public static void main(String[]args) {
Play play = new Play();
System.out.println("REVERSE VALUE: " + play.reverse(INPUT_WORD));
}
}
class Play {
void REVERSE() {
String[] INPUT_WORD = {"T", "R", "A", "I", "N"};
String[] OUTPUT_WORD =new String[INPUT_WORD.length];
int length = INPUT_WORD.length;
int i = 0;
while(--length>=0){
OUTPUT_WORD[i++] = INPUT_WORD[length];
}
System.out.println(Arrays.toString(OUTPUT_WORD));
}
public static void main(String[] args) {
Play PL = new Play();
PL.REVERSE();
}
}
Your code is entering an endless loop because of the assignment "Q=Q--"
for(Q=INPUT_WORD.length-1; Q>=0; Q=Q--);
It should instead be
Q--
without a semicolon at the end.
If the code runs successfully, it will print the words "REVERSE VALUE" repeatedly prior to printing each character in reverse.
System.out.print ("REVERSE VALUE" + INPUT_WORD[Q]);
So you will want to keep the text in reverse prior to printing the whole statement at the end of the execution of the for loop.
What is the reason to use array of String instead of just String? Since it's not mentioned as a requirement, I'm suggesting the following as an alternative solution:
public class Play {
static void reverse(){
String inputWord = "TRAIN";
char[] toStrArray = inputWord.toCharArray();
char[] revisedInput = new char[inputWord.length()];
int i = 0;
for(int q=toStrArray.length-1; q>=0; q--){
revisedInput[i]=toStrArray[q];
i++;
}
System.out.print ("REVERSE VALUE: " + new String(revisedInput));
}
public static void main(String[]args){
//Play PL = new Play();
//PL.REVERSE();
reverse();
}
}
Note: You can declare the method reverse as a static method. By doing this you don't have to create an object before calling it. Hope this helps.

Scanner is requiring me to type inputs twice just for one to register

I've been doing a ton of research on this for the past few hours, with no luck. I am pretty sure this is a problem with .next() or .nextLine() (according to my searches). However, nothing has helped me solve my problem.
When I run the code below, I have to type in input twice, and only one of the inputs is subsequently added to the arrayList (which can be seen when you print the contents of the arrayList).
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
public class Tester{
public static void main(String[] args) {
AddStrings();
}
public static void AddStrings() {
Scanner console = new Scanner(System.in);
ArrayList<String> strings = new ArrayList<String>(); //this arraylist will hold the inputs the user types in in the while loop below
while(true) {
System.out.println("Input file name (no spaces) (type done to finish): ");
if(console.next().equals("done")) break;
//console.nextLine(); /*according to my observations, with every use of .next() or .nextLine(), I am required to type in the same input one more time
//* however, all my google/stackoverflow/ reddit searches said to include
//* a .nextLine() */
//String inputs = console.next(); //.next makes me type input twice, .nextLine only makes me do it once, but doesn't add anything to arrayList
strings.add(console.next());
}
System.out.println(strings); //for testing purposes
console.close();
}
}
Problem with your code is that you are doing console.next() two times.
1st Inside if condition and
2nd while adding to ArrayList.
Correct Code :
public class TestClass{
public static void main(String[] args) {
AddStrings();
}
public static void AddStrings() {
Scanner console = new Scanner(System.in);
ArrayList<String> strings = new ArrayList<String>(); //this arraylist will hold the inputs the user types in in the while loop below
while(true) {
System.out.println("Input file name (no spaces) (type done to finish): ");
String input = console.next();
if(input.equals("done")) break;
strings.add(input);
System.out.println(strings);
}
System.out.println(strings); //for testing purposes
console.close();
}
}
In your code, you are asking for two words to be inserted. Just remove one of them.
Use it this way:
String choice = console.next();
if (choince.equals('done')) break;
strings.add(choice);

Check through an ArrayList if it contains a String. If it doesn't, add that String

Edit
Many users are commenting that the Class Word is useless, which is probably true in this case. The reason I added it, is because I need it later on in the program.
This program has 3 classes - WordList, Word and a test class. I'm trying to get the method 'readBook' to read through a file, and send every word over to the method 'addWord'. Method addWord will check if the ArrayList allWords contains that word. If it doesn't, addWord will then add the word to an array, aswell as to send it over to class Word. When I run the program, nothing happens. I tried to print out allWords.size(), which returned 0.
Class WordList:
public class WordList {
String nextWord;
ArrayList<String> allWords = new ArrayList<String>();
public void readBook (String filename) throws Exception{
File file = new File(filename); //File has one word on each line.
Scanner innFile = new Scanner(file);
for (int i = 0; i<file.length(); i++){
if(innFile.hasNextLine()){
nextWord = innFile.nextLine();
addWord(nextWord);
}
}
}
private void addWord(String word){
for (String check : allWords){
if (!check.equalsIgnoreCase(word)){
allWords.add(word);
new Word(word);
}
else if(check.equalsIgnoreCase(word)){
System.out.println("The word allready exsist.");
}
else{
System.out.println("Something went wrong.");
}
}
}
Class Word:
public class Word {
String word;
ArrayList<String> allWords = new ArrayList<String>();
Word(String text){
word = text;
allWords.add(word);
System.out.print(allWords);
}
The test class:
public class TestClass {
public static void main (String[] args) throws Exception{
WordList list = new WordList();
list.readBook("path.../scarlet.text");
WordList newList = new WordList();
System.out.println(newList.numberOfWords());//A method printing out allWords.size()
}
}
You are populating allWords list of WordList class inside for (String check : allWords). Initially it would be empty hence it will never enter the for loop and allWords will never get populated. In turn new Word(word) will not be called and allWords of word class will be empty.
You have two issues with your code.
First, when that main loop (for (String check : allWords)) runs, allWords is going to be empty. Therefore, you will never add any elements to it, and that means it will always have a size of 0. To correct this, you probably need to add a boolean variable that gets set to true if you find the word. Then, after the loop, if the boolean variable is still false, add the word to the list.
Secondly, you've got allWords defined on two places: in your WordList class, and in your Word class. The WordList.allWords array is being updated correctly (as far as I can tell, once you fix the above mentioned issue). However, the Word.allWords array is not doing anything other than storing a single String value... twice (once in the array, once in a variable). The Word class isn't really doing anything useful, so I would opt to get rid of it.
I would get rid of the Word class completely, since it's currently not doing anything other than storing a String, which you could do with a String variable.
When the method addWord(String) is called it never enters the for loop because allWords is initially an empty ArrayList. Your call to "new Word(String)" is never reached.
I don't think you need allWords in both the Word class and the WordList class (?)
If you're just trying to get the unique words you can do this:
Set<String> words = new LinkedHashSet<>();
File file = new File("some file");
Scanner inFile = new Scanner(file);
for (int i = 0; i < file.length(); i++)
if (inFile.hasNextLine())
words.add(inFile.nextLine());
inFile.close();
then call
words.size()
to check if an array list contains a certain string you can use a for loop.
I'm not sure if this is the best way to go about it, but it should work.
for(int i = 0; i<yourArrayList.size(); i++){
if (yourArrayList.get(i).!contains(yourString)){
yourArrayList.add(yourString);
}
In test class try:
public static void main(String[] agrs) throws Exception {
WordList w = new WordList();
w.readBook("pathToMyFile"); // This way you access to readBook method
....
}
And add the word in method addWord when attribute allWords is empty.
private void addWord(String word){
if (allWords.isEmpty()) {
allWords.add(word);
} else {
// Your code
}
}

Using the Scanner class to read a scanner string

I have a problem creating a student class which contains a constructor which takes a Scanner string of a format "Brookes 00918 X12 X14 X16 X21". The conditions should be that there should be a student name and student number and the course codes should start with an "X". I have thrown IncorrectFormatExceptions in the case that they are not satisfied. However when I create a test class and enter a string and press enter , for example "abc 123" it doesn't produce an output which is usually the case.
Update: I've changed the code to use a String array tokens however now with the toString() method using "123 abc X12" it gives a Null Pointer Exception. It works when I put "123 abc" in the constructor
Update:Seems to work now forgot to initialize the arrayList
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Student extends UniversityPerson{
private String studentNumber="";
private List<String> courses=new ArrayList<String>();
private String studentName="";
public int checkNoofletters(char[] chararray){
int noofletters=0;
for (char c:chararray){
if (Character.isLetter(c)){
noofletters++;
}
}
return noofletters;
}
public String courseListinStr(){
String stringo="";
for (String c:courses){
stringo+=c;
stringo+=" ";
}
return stringo;
}
public Student(Scanner scanner) throws IncorrectFormatException{
int studentNumberCount=0;
int studentNameCount=0;
Scanner s=scanner;
String input=s.nextLine();
String[] tokens=input.split("\\s");
for (int i=0; i<tokens.length; i++){
char[] chars=tokens[i].toCharArray();
if (checkNoofletters(chars)==chars.length){//if the number of letters is equal to the character length
if (studentNameCount==1){throw new IncorrectFormatException("Can only have 1 student name");}
studentNameCount++;
this.studentName=tokens[i];
continue;
}
if (tokens[i].matches("[0-9]+")){//add to the studentNumbers list
if (studentNumberCount==1){throw new IncorrectFormatException("Can only have 1 student number");}
studentNumberCount++;
this.studentNumber=tokens[i];
continue;
}
if (!tokens[i].startsWith("X")){
throw new IncorrectFormatException("Course code must start with an 'X'");
}
System.out.println(tokens[i]);
courses.add(tokens[i]);
}
if (studentNumber=="" || studentName==""){
throw new IncorrectFormatException("Must have 1 student Number and Student Name");
}
}
#Override
public String toString() {
//return String.format("%s %s", studentName,courseListinStr());
return String.format("Student: %s %s", studentName,studentNumber);
}
#Override
public boolean equals(Object o) {
// TODO Auto-generated method stub
return false;
}
}
The best way would be to do something like this:
Scanner s=scanner;
String input = s.nextLine();
String[] tokens=input.split("\\s");
Now you can test all your conditions:
if (tokens.size() < yourNumber) throw new Exception("add here");
if (tokens[2].charAt(0)!='X') throw new Exception("add here");
and so on; it should be rather easy to create your Student Object based on your requirements.
Your program is full of errors and I'll list some of them after answering why it doesn't print anything: if you dump all threads you'll see that the main thread is stuck at next(), which blocks until next token is available, and effectively never leaves the constructor of the first student
if (s.hasNextInt()){
studentNumbers.add(s.nextInt());
s.next();
continue; // <--------- this line
}
I think this is not the only error in your program, so maybe you'd better throw the entire parsing away and restart from scratch.
You should create exactly one Scanner object for each input stream, not one for parsed object
You should not pass the scanner to the Student constructor
You should not put any algorithm in a constructor: make a separate object instead
To simplify your program introduce a Parser class
public class Parser {
public Parser(Reader in) {}
public boolean hasNext() {}
public Student next() {}
}
and inside next() make the parser deal with entire lines (Scanner.hasNextLine and Scanner.nextLine()) instead of individual tokens, otherwise you'll have to define a custom protocol to mean EOR (end of record)
Dealing with lines is easier to think about, program and test. Once you have the full record, you can further tokenize it with a simple String.split(), or directly use regular expressions.
I didn't go through, your whole code. But, I would suggest you to use StringTokenizer or split function and store it in temp array. Then, traverse through your temp array and validate the data.

Categories

Resources