Exception in thread "main" java.util.NoSuchElementException - java

I'm practice to write java code and i try to fix this but i don't know how to fix it anymore. I'll show you my code.
In my Fortunecookie.java is:
public class FortuneCookie {
private String subjectList;
private String objectList;
private String verbList;
private int sWord;
private int oWord;
private int vWord;
private Random random = new Random() enter code here;
public FortuneCookie() {
subjectList = "I#You#He#She#It#They";
objectList = "me#you#him#her#it#";
verbList = "hate#love#deny#find#hear#forgive#hunt#win#teach";
}
public String getFortuneMsg() {
StringTokenizer subSt = new StringTokenizer(subjectList,"#");
StringTokenizer objSt = new StringTokenizer(objectList,"#");
StringTokenizer verbSt = new StringTokenizer(verbList,"#");
sWord = subSt.countTokens();
oWord = objSt.countTokens();
vWord = verbSt.countTokens();
int c1 = random.nextInt(sWord);
String line1 = " ";
String line2 = " ";
String line3 = " ";
while(subSt.hasMoreTokens()) {
line1 = subSt.nextToken("#");
for (int i=0;i<sWord;i++)
if (i == c1) {
break;
}
else{
line1 = subSt.nextToken("#");
}
}
int c2 = random.nextInt(oWord);
while(objSt.hasMoreTokens()) {
line2 = objSt.nextToken("#");
for (int i=0;i<sWord;i++)
if (i == c2) {
break;
}
else{
line2 = objSt.nextToken("#");
}
}
int c3 = random.nextInt(vWord);
while(verbSt.hasMoreTokens()) {
line3 = verbSt.nextToken("#");
for (int i=0;i<sWord;i++)
if (i == c3) {
break;
}
else{
line3 = verbSt.nextToken("#");
}
}
return line1+line2+line3;
}
public void setSubjectList(String aSubjectList) {
subjectList = aSubjectList;
}
public void setObjectList(String aObjectList) {
objectList = aObjectList;
}
public void setVerbList(String aVerbList) {
verbList = aVerbList;
}
public void print() {
StringTokenizer subSt = new StringTokenizer(subjectList,"#");
StringTokenizer objSt = new StringTokenizer(objectList,"#");
StringTokenizer verbSt = new StringTokenizer(verbList,"#");
sWord = subSt.countTokens();
oWord = objSt.countTokens();
vWord = verbSt.countTokens();
System.out.println("Subject List : "+subjectList);
System.out.println("Object List : "+objectList);
System.out.println("Verb List : "+verbList);
}
And in my FortuneCookieTest.java is
public class FortuneCookieTest {
public static void main(String[] args) {
FortuneCookie ck = new FortuneCookie();
System.out.println(ck.getFortuneMsg());
}
}
And when I compile and run it:
//Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(Unknown Source)
at java.util.StringTokenizer.nextToken(Unknown Source)
at CS_111_Homework_2.FortuneCookie.getFortuneMsg(FortuneCookie.java:39)
at CS_111_Homework_2.FortuneCookieTest.main(FortuneCookieTest.java:6)
How can I solve it?

In this part of the code, you can call objSt.nextToken("#") twice, and if the first calls gets the last element, on the second call you'll get the NoSuchElementException as no more elements are available.
while (objSt.hasMoreTokens()) {
line2 = objSt.nextToken("#");
for (int i = 0; i < sWord; i++)
if (i == c2) {
break;
} else {
line2 = objSt.nextToken("#");
}
}
This is a different use case, but has the same problem

Actually there are several issues with the code, specially with this method getFortuneMsg() :
you are using sWord for all the loops, instead you should use sWord for the first loop oWordfor the second and vWordand for the last.
Also you are calling line1 = subSt.nextToken("#"); before starting the loop so you have consumed one token already, this could produceNoSuchElementException i suggest to change this for (int i=0; i<sWord; i++) to this for (int i=0; i<sWord - 1; i++) to take in consideration the consumed token.
And for this loop while(subSt.hasMoreTokens()) it will be started all over again if not all tokens are consumed (it could be happen when c1 < sWord) .
Note: The code need some refactoring to prevent duplication and use loops wisely.
Edit: I didn't understand exactly what you are trying to achieve but if I were you I would like to change this method getFortuneMsg() to something like this:
public String getFortuneMsg() {
StringTokenizer[] tokenizers = {new StringTokenizer(subjectList, "#"), new StringTokenizer(objectList, "#"), new StringTokenizer(verbList, "#")};
StringBuilder sb = new StringBuilder();
for (StringTokenizer tokenizer : tokenizers) {
int rCount = random.nextInt(tokenizer.countTokens());
for (int i = 0; i < rCount; i++) {
tokenizer.nextToken();
}
sb.append(tokenizer.nextToken());
}
return sb.toString();
}

Related

Why is Java string array appending a string to null in first cell?

Here is my class below, that compares elements in two string arrays, and returns the word with the highest frequency in both arrays. However as visible from the output, the first index is appending none to null in spite of initializing both arrays with the String none. Can someone kindly let me know what I am doing wrong that is leading to this?
public class HelloWorld{
public String[] pro;
public String[] con;
String proSplitter;
String conSplitter;
public HelloWorld() {
this.pro = new String[9];
this.con = new String[9];
for(int i=0;i<this.pro.length;i++)
{
this.pro[i]="none";
this.con[i]="none";
}
}
public String[] getPro() {
return pro;
}
public String[] getCon() {
return con;
}
public void setPro(String pros, int proIndex) {
pro[proIndex] = pros;
}
public void setCon(String cons, int conIndex) {
con[conIndex] = cons;
}
public String[] proWord(){
for(int i=0;i<9;i++)
{
proSplitter = proSplitter + pro[i] + ",";
}
for(int i=0;i<9;i++)
{
conSplitter = conSplitter + con[i] + ",";
}
String[] values = proSplitter.split(",");
for(int i=0;i<values.length;i++)
{
values[i] = values[i].trim();
}
String[] values1 = conSplitter.split(",");
for(int i=0;i<values1.length;i++)
{
values1[i] = values1[i].trim();
}
int [] fr = new int [values.length];
int visited = -1;
for(int i = 0; i < values.length; i++){
int count = 1;
for(int j = i+1; j < values.length; j++){
if(!values[i].equalsIgnoreCase("none"))
{
if(values[i].compareTo(values[j])==0){
count++;
//To avoid counting same element again
fr[j] = visited;
}
}
}
if(fr[i] != visited)
fr[i] = count;
}
int max = fr[0];
int index = 0;
for (int i = 0; i < fr.length; i++)
{
if (max < fr[i])
{
max = fr[i];
index = i;
}
}
int [] fr1 = new int [values1.length];
int visited1 = -1;
for(int i = 0; i < values1.length; i++){
int count1 = 1;
for(int j = i+1; j < values1.length; j++){
if(!values1[i].equalsIgnoreCase("none"))
{
if(values1[i].compareTo(values1[j])==0){
count1++;
//To avoid counting same element again
fr1[j] = visited1;
}
}
}
if(fr1[i] != visited1)
fr1[i] = count1;
}
for(int i = 0;i<values.length;i++)
{
System.out.println("pro = "+values[i]);
}
for(int i = 0;i<values1.length;i++)
{
System.out.println("con = "+values1[i]);
}
int max1 = fr1[0];
int index1 = 0;
for (int i = 0; i < fr1.length; i++)
{
if (max1 < fr1[i])
{
max1 = fr1[i];
index1 = i;
}
}
String sentence[] = new String[2];
if(values[index].equalsIgnoreCase(values1[index1])) {
sentence[0] = "balanced";
}else {
sentence[0] = values[index];
sentence[1] = values1[index1];
}
return sentence;
}
public static void main(String[] args){
HelloWorld tracker = new HelloWorld();
tracker.setPro("Apple, Pear", 1);
tracker.setCon("Banana", 1);
tracker.setPro("Apple", 2);
tracker.setCon("Water Melon", 2);
tracker.setPro("Guava", 3);
tracker.setCon("Ball", 3);
tracker.setPro("Apple", 4);
tracker.setCon("Mango, Plum", 4);
String[] arr = tracker.proWord();
System.out.println("pro = "+arr[0]);
System.out.println("con = "+arr[1]);
}
}
The output being generated is :
pro = nullnone
pro = Apple
pro = Pear
pro = Apple
pro = Guava
pro = Apple
pro = none
pro = none
pro = none
pro = none
con = nullnone
con = Banana
con = Water Melon
con = Ball
con = Mango
con = Plum
con = none
con = none
con = none
con = none
pro = Apple
con = nullnone
As mentioned by Arnaud, the immediate problem is that you're leaving proSplitter uninitialized, so its value is null. Then, when you come to append a string to it with proSplitter = proSplitter + pro[i] + ",";, proSplitter will be converted (effectively) to "null", and then stuff is appended to the end. So, instead, make it "" initially.
However, you've got another problem here, which is that you're mutating a member variable each time you invoke that method - so it's not null (or empty) second time around, it still contains what was there previously.
The fix for that is straightforward: instead of using a member variable, declare these as local variables.
You've also got the problem that you're effectively duplicating the code to count the most frequent thing in an array: this is what methods are for, to allow you to run the same code over different inputs.
You can also make use of library methods. For example:
String mostFrequent(String[] array) {
int maxFreq = 0;
String maxFreqS = "";
for (String s : array) {
if (s.equalsIgnoreCase("none")) continue;
int freq = Collections.frequency(Arrays.asList(array), s);
if (freq > maxFreq) {
maxFreq = freq;
maxFreqS = s;
}
}
return maxFreqS;
}
(There are lots of inefficiencies here. The point is more about writing this as a method, to remove the duplication).
Then you can use this inside your existing method, and it will be a whole lot easier for others - and you - to read.

Java ArrayList<String> using for loop and overwriting itself

I'm trying to make my t String save to an ArrayList. but every time I run my program more than once it overwrites the previous data I want it to be a continuation. Creating the Array inside or out of the loop doesn't seem to help it just keeps rewriting over what is already there.
private void sets(ArrayList<Integer> save, int answer) {
String s = ", ";
String t = "";
for (int i = 0; i < 6; i += 1) {
t = t + String.valueOf(save.get(i)) + s;
}
for(int n = place ;n<1 ;){
ArrayList<String> message = new ArrayList<String>();
message.add(t);
place=place+1;
System.out.println(message);
return;
}
}
Move ArrayList<String> message = new ArrayList<String>(); to right after your class statement. Example:
public class xxxxx{
ArrayList<String> message = new ArrayList<String>();
//rest of your code
}
You can do that in two ways..
You can place the data structure at the beginning of the method sets and this obviously will have all the data in message lost once the method has exited.
private void sets(ArrayList<Integer> save, int answer) {
ArrayList<String> message = new ArrayList<String>();
String s = ", ";
String t = "";
for (int i = 0; i < 6; i += 1) {
t = t + String.valueOf(save.get(i)) + s;
}
for (int n = place; n < 1;) {
message.add(t);
place = place + 1;
System.out.println(message);
}
return;
}
Or you can declare a global variable that can always handle your data for as long as the program still executes.
private ArrayList<String> message = new ArrayList<String>();
private void sets(ArrayList<Integer> save, int answer) {
String s = ", ";
String t = "";
for (int i = 0; i < 6; i += 1) {
t = t + String.valueOf(save.get(i)) + s;
}
for (int n = place; n < 1;) {
message.add(t);
place = place + 1;
System.out.println(message);
}
return;
}
It all comes down to your requirements. #GOODLUCK

Constructor Parameter Value Not Implemented

I'm creating a very simple encoder that will shuffle the characters in a string. I've written it to split this string in half, forming two new variables. The user chooses the number of shuffles they want and that is passed as a parameter in the new class constructor -- which should then use that shuffle value throughout the class. Mine is not. The shuffleEncryption method is using the class variable, 0, instead. I know this must be something very obvious, but I am not catching it. :/
//From Main Class
System.out.println("Enter message to encrypt: ");
String message = input.next();
System.out.print("Number of shuffles: " );
int numShuffles = input.nextInt();
ShuffleCipher shuffle = new ShuffleCipher(numShuffles);
System.out.println(shuffle.encode(message));
//The shuffle class
public class ShuffleCipher implements MessageEncoder {
int shuffle;
public ShuffleCipher(int shuffle) {
shuffle = this.shuffle;
}
private String shuffleEncryption(String str) {
int middle = str.length()/2;
int loop = 1;
System.out.println("shift" + shuffle);
StringBuilder sb = new StringBuilder();
do {
String firstHalf = str.substring(0, middle);
System.out.println("first:" + firstHalf);
String secondHalf = str.substring(middle);
System.out.println("second:" + secondHalf);
for(int i = 0, j = 0; i < firstHalf.length(); i++, j++) {
sb = sb.append(secondHalf.charAt(i));
if(j < secondHalf.length()) {
sb = sb.append(firstHalf.charAt(i));
}
str = sb.toString();
}
loop++;
} while (loop <= shuffle);
return str;
}
#Override
public String encode(String plainText) {
String shuffled;
shuffled = shuffleEncryption(plainText);
return shuffled;
}
}
You are not setting the shuffle member variable in the constructor.
Change this:-
public ShuffleCipher(int shuffle) {
shuffle = this.shuffle;
}
to this:-
public ShuffleCipher(int shuffle) {
this.shuffle = shuffle;
}

Java split string with combinations

My input string is
element1-element2-element3-element4a|element4b-element5-
Expected output is
element1-element2-element3-element4a-element5-
element1-element2-element3-element4b-element5-
So the dash (-) is the delimiter and the pipe (|) indicates two alternative elements for a position.
I am able to generate combinations for input containing a single pipe:
ArrayList<String> finalInput = new ArrayList<String>();
String Input = getInputPath();
StringBuilder TempInput = new StringBuilder();
if(Input.contains("|")) {
String[] splits = Input.split("\\|", 2);
TempInput.append(splits[0]+"-"+splits[1].split("-", 2)[1]);
finalInput.add(TempInput.toString());
TempInput = new StringBuilder();
String[] splits1 = new StringBuilder(Input).reverse().toString().split("\\|", 2);
finalInput.add(TempInput.append(splits1[0]+"-"+splits1[1].split("-", 2)[1]).reverse().toString());
}
But this logic fails if there are multiple pipe symbols.
How to split a String on the last occurrance only?
Is there any efficient way to use split String with combinations?
Input:
element1-element2-element3-element4a|element4b-element5-element6a|element6b
Output:
element1-element2-element3-element4a-element5-element6a
element1-element2-element3-element4b-element5-element6a
element1-element2-element3-element4a-element5-element6b
element1-element2-element3-element4b-element5-element6b
Recursion helps.
public static void main(String[] args) {
produce("element1-element2-element3-element4a|element4b"
+ "-element5-element6a|element6b");
}
private static void produce(String input) {
String[] sequence = input.split("-");
String[][] elements = new String[sequence.length][];
for (int i = 0; i < sequence.length; ++i) {
elements[i] = sequence[i].split("\\|");
}
List<String> results = new ArrayList<>();
walk(results, elements, 0, new StringBuilder());
}
private static void walk(List<String> results, String[][] elements,
int todoIndex, StringBuilder done) {
if (todoIndex >= elements.length) {
results.add(done.toString());
System.out.println(done);
return;
}
int doneLength = done.length();
for (String alternative : elements[todoIndex]) {
if (done.length() != 0) {
done.append('-');
}
done.append(alternative);
walk(results, elements, todoIndex + 1, done);
done.setLength(doneLength); // Undo
}
}
The String.split method is used twice to get a navigatable String[][]. And to build a final String a StringBuilder is used.
You can use StringTokenizer in Java. Basically it makes tokens of the string.
public StringTokenizer(String str, String delim)
Here's an example:
String msg = "http://100.15.111.60:80/";
char tokenSeparator= ':';
StringTokenizer st = new StringTokenizer(msg, tokenSeparator + "");
while(st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
I have write a demo for you as what I comment after your post, the code may be ugly, but it works
public class TestSplit {
//define a stringList hold our result.
private static List<String> stringList = new ArrayList<String>();
//this method fork the list array when we meet a "|"
public static void forkStringList(){
List<String> tmpList = new ArrayList<String>();
for(String s: stringList){
tmpList.add(s);
}
stringList.addAll(tmpList);
}
//when we meet "|" split two elems, should add it to
//the string list half-half
public static void addTowElems(String s1, String s2){
for(int i=0;i<stringList.size()/2;i++){
stringList.set(i,stringList.get(i)+s1);
}
for(int i = stringList.size()/2;i<stringList.size();i++){
stringList.set(i,stringList.get(i)+s2);
}
}
// if not meet with a "|" just add elem to everyone of the stringlist
public static void addOneElem(String s){
for(int i=0;i<stringList.size();i++){
stringList.set(i,stringList.get(i)+s);
}
}
public static void main(String[] argvs){
//to make *fork* run, we must make sure there is a "init" string
//which is a empty string.
stringList.add("");
// this is your origin string.
String input = "a-b-c-d|e-f";
for (String s: input.split("\\-")){
if(s.contains("|")){
//when meet with "|", first fork the stringlist
forkStringList();
// then add them separately
addTowElems(s.split("\\|")[0],s.split("\\|")[1]);
}else {
// else just happily add the elem to every one
// of the stringlist
addOneElem(s);
}
}
//checkout the result, should be expected.
System.out.println(stringList);
}
}
Here's my iterative solution:
import java.util.*;
public class PathParser {
private static final String DELIMINATOR_CONCAT = "-";
private static final String DELIMINATOR_OPTION = "|";
private List<String> paths;
private List<String> stack;
private List<String> parse(final String pathSpec) {
stack = new ArrayList<String>();
paths = new ArrayList<String>();
paths.add("");
final StringTokenizer tok = createStringTokenizer(pathSpec);
while (tok.hasMoreTokens()) {
final String token = tok.nextToken();
parseToken(token);
}
if (!stack.isEmpty()) {
updatePaths();
}
return paths;
}
private void parseToken(final String token) {
if (DELIMINATOR_CONCAT.equals(token)) {
updatePaths();
} else if (DELIMINATOR_OPTION.equals(token)) {
// nothing to do
} else {
stack.add(token);
}
}
private void updatePaths() {
final List<String> originalPaths = new ArrayList<String>(paths);
paths.clear();
while (stack.size() > 0) {
paths.addAll(createNewPaths(originalPaths));
}
}
private List<String> createNewPaths(final List<String> originalPaths) {
final List<String> newPaths = new ArrayList<String>(originalPaths);
addPart(newPaths, stack.remove(0));
addPart(newPaths, DELIMINATOR_CONCAT);
return newPaths;
}
private void addPart(final List<String> paths, final String part) {
for (int i = 0; i < paths.size(); i++) {
paths.set(i, paths.get(i) + part);
}
}
private StringTokenizer createStringTokenizer(final String pathSpec) {
final boolean returnDelimiters = true;
final String delimiters = DELIMINATOR_CONCAT + DELIMINATOR_OPTION;
return new StringTokenizer(pathSpec, delimiters, returnDelimiters);
}
public static void main(final String[] args) {
final PathParser pathParser = new PathParser();
final String input = "element1-element2-element3-element4a|element4b|element4c-element5-element6a|element6b|element6c";
System.out.println("Input");
System.out.println(input);
System.out.println();
final List<String> paths = pathParser.parse(input);
System.out.println("Output");
for (final String path : paths) {
System.out.println(path);
}
}
}
Output:
Input
element1-element2-element3-element4a|element4b-element5-element6a|element6b
Output
element1-element2-element3-element4a-element5-element6a-
element1-element2-element3-element4b-element5-element6a-
element1-element2-element3-element4a-element5-element6b-
element1-element2-element3-element4b-element5-element6b-
This helps to acheive the same..
public class MultiStringSplitter {
public static void main(String arg[]) {
String input = "a-b|c-d|e-f|g-h";
String[] primeTokens = input.split("-");
String[] level2Tokens = null;
String element = "";
String level2element = "";
ArrayList stringList = new ArrayList();
ArrayList level1List = new ArrayList();
ArrayList level2List = new ArrayList();
for (int i = 0; i < primeTokens.length; i++) {
// System.out.print(primeTokens[i]);
if (primeTokens[i].contains("|")) {
level2Tokens = primeTokens[i].split("\\|");
for (int j = 0; j < level2Tokens.length; j++) {
for (int k = 0; k < stringList.size(); k++) {
element = (String) stringList.get(k);
level2element = element + level2Tokens[j];
level2List.add(level2element);
}
}
stringList = new ArrayList();
for (int w = 0; w < level2List.size(); w++) {
stringList.add(level2List.get(w));
}
level2List = new ArrayList();
}
else {
if (stringList.size() > 0) {
for (int z = 0; z < stringList.size(); z++) {
element = (String) stringList.get(z);
element = element + primeTokens[i];
level1List.add(element);
}
stringList = new ArrayList();
for (int w = 0; w < level1List.size(); w++) {
stringList.add(level1List.get(w));
}
level1List = new ArrayList();
}
else {
element = element + primeTokens[i];
if (stringList.size() == 0) {
stringList.add(element);
}
}
}
}
for (int q = 0; q < stringList.size(); q++) {
System.out.println(stringList.get(q));
}
}
}
Input : a-b|c-d|e-f|g-h
Output:
abdfh
acdfh
abefh
acefh
abdgh
acdgh
abegh
acegh

Parameter passing in Java problems

I am new to java, and have been writing a program to check if a given string is periodic or not.A string is not periodic if it cannot be represented as a smaller string concatenated some number of times. Example "1010" is periodic but "1011" is not. Here is my code. It compiles, but the problem is that it tells every string is not periodic. I guess the problem is with the for loop in the isPeriodic function. Please help me get it correct.
import java.io.*;
import java.util.*;
public class Test {
/**
* #param args
*/
public static void main(String[] args) throws java.lang.Exception {
java.io.BufferedReader R = new java.io.BufferedReader
(new java.io.InputStreamReader(System.in));
//String st = R.readLine();
String st = "10101010";
if (isPeriodic(st) == false) {
System.out.println(" Non Periodic");
}
else {
System.out.println("Periodic");
}
}
private static boolean isPeriodic(String s)
{
String temp = s;
int i;
boolean pflag = false;
for ( i = 1; i <= (s.length()/2); i++) {
s = rotateNltr(s,i);
if (s == temp) {
pflag = true;
break;
}
}
return pflag;
}
private static String rotateNltr(String s, int n) {
if( n > s.length()) {
return null;
}
for ( int i = 0; i < n; i++) {
s = leftRotatebyOne(s);
}
//System.out.println(s);
return s;
}
private static String leftRotatebyOne(String s) {
char[] temp = s.toCharArray();
char t = temp[0];
for ( int i = 0 ; i < s.length()-1 ;i++ ) {
temp[i] = temp [i+1];
}
temp[s.length()-1] = t;
String r = new String(temp);
//System.out.println(r);
return r;
}
}
You can't compare objects (and that includes String's) with ==. You have to use the equals method.
Unlike C++ (which I assume is your language of preference) Java doesn't allow comparing String objects with the == operator. Use the equals method to compare the strings.
if (s.equals(temp)) {
pflag = true;
break;
}
In your isPeriodic() the check you are doing is wrong. Do it as below:
if (s.equals(temp)) {
pflag = true;
break;
}
s.equal(temp) alone wont solve the problem, yes it will make the code execute correctly for the input as given in Main method but for 1010, 1011 it wont.
Try using this method :
private static boolean isPeriodic(String s) {
String temp = s;
int i;
boolean pflag = false;
for (i = 1; i <= (s.length() / 2); i++) {
s = leftRotatebyOne(s);
if (s.equals(temp)) {
pflag = true;
break;
}
}
return pflag;
}
This will ensure that for all combination this program works.

Categories