I stuck with get out from while loop in method - java

I am writing program that asks user to type seven names of product.
what I try to do is if there is duplicate, then repeat the method.
I used while loop but I stuck.
If I put a,b,c,d,e,f,g at the first time, method ends and moves on to next method.
But if I typed a,a,b,c,d,e,f, program repeats same method and even if I type a,b,c,d,e,f,g, it gets in infinite loop.
here is my codes.
in main....
purchasedList.setShopList();
in purchasedList class...
public void setShopList() {
Scanner keyboard = new Scanner(System.in);
// print out description.
System.out.println("\n- Only have one entry of any type in the item list.");
System.out.println("- The name of items cannot be longer than 16 characters.");
System.out.println("\nType seven products.");
boolean sameNames = true;
while (sameNames == true) {
for (int i=0; i<7; i++) {
String n = keyboard.nextLine();
name.add(n);
name.set(i,name.get(i).toUpperCase());
}
sameNames = checkName();
}
}
// accessor.
public ArrayList<String> getShopList () {
return name;
}
// check duplicate.
public boolean checkName() {
Set<String> uniqueName = new HashSet<String>();
boolean foundName = false;
for (int i=0; i<7; i++) {
if (!uniqueName.add(name.get(i))) { // check duplicate
foundName = true;
}
}
if (foundName == true) {
System.out.println("※ There is a duplicate. Try it again.");
return true;
} else {
return false;
}
}
my checkName() method is fine because in my last project it worked.
in my last project, I put while loop in main like this
public static void main(String[] args) {
PurchasedList purchasedList = new PurchasedList();
.
.
.
boolean sameNames = true;
boolean tooLong = true;
while (sameNames == true || tooLong == true) {
System.out.println("\nType seven products.");
purchasedList.setShopList();
sameNames = purchasedList.checkName();
tooLong = purchasedList.checkLength();
}
but this time, because my professor wants me to make all operations are done within a method, so I try to fix.
I tried to solve it by myself in last 8 hours, but I could not get the solution.
Please help me.
Thank you.

add this line.
if (foundName == true) {
System.out.println("※ There is a duplicate. Try it again.");
-> name = new ArrayList<String>();
return true;
right now you are adding new names to the end of the array, and then setting them to upper case in the start of the array.
for (int i=0; i<7; i++) {
String n = keyboard.nextLine(); //Say I type in g on my second try
name.add(n); //This add g to the end of the array
name.set(i,name.get(i).toUpperCase()); //And this sets name[0] to G.
}
this means your name array is getting longer, instead of resetting.

Do you ever clean name? It appears you just keep adding to it, so the previous entrances are still there in loop's next round. And therefore there will always be a duplicate if you use same input as before (the order will not matter).
This change should do it:
while (sameNames == true) {
name = newArrayList <String>();
for (int i=0; i<7; i++) {
String n = keyboard.nextLine();
name.add(n);
name.set(i,name.get(i).toUpperCase());
}
sameNames = checkName();
}
So new name ArrayList is created every time. (Garbage collector will take care of the old ones, if necessary.) If name is already created somewhere else, then think if you really need it there - as far as I see you use it to gather input, and this happens in the method setShopList() so it appears you do not need it earlier than this.

Related

Why does for readelements() fro loop not print out?

So I've been stuck trying to get my array list to print out in the right order but it keeps printing the original input i inserted backwards for some reason, i've tried reading the array in reverse order but it doesn't work either.
public static void Add()
{
System.out.println("You may now enter your virtual diary entry...");
System.out.println("You may END the program at any time by typing in endp...\n");
boolean loop = true;
while(loop)
{
String Stop = Cons.nextLine();
if (Stop.equals("endp")| Stop.equals(""))
{
readelements();
break;
} else {
for (int i =0 ; i <= Notes.size(); ) {
Notes.add(i, Stop);
i++;
break;
}
}
}
}
public static void readelements()
{
if (Empty()) {
Empty();
}
for(int i =0; i < Notes.size(); i++) {
System.out.println(i + " = " + Notes.get(i).toString());
Notes.toString();
}
}
In your else block, you break after one iteration (when i = 0) so you're always running Notes.add(0, Stop). This prepends Stop to Notes, so Notes will be in reverse order. Removing the break will cause you to insert duplicate elements into Notes (note that you're looping but always inserting Stop). Try changing your entire else block to just Notes.add(Stop);. This will add the current value of Stop to the end of Notes and should fix your problem.

Array will not update but rather print out the wrong array

I managed to figure out how to print the array for my connect four program but I cannot get the board to update with my code, I looked at it and ran it the code works in theory but however the array won't take the new inputs
Ive tried running it through with a for loop but that turned out wrong and I was thinking about putting the drop method in the print board method but I feel that that would result in an error
public class Connect4 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// DON'T MODIFY THE MAIN METHOD UNLESS FOR DEBUGGING
//MAKE SURE YOU GET RID OF YOUR MODIFICATIONS HERE BEFORE
SUBMISSION
String[][] board = createEmptyBoard();
Scanner input = new Scanner(System.in);
boolean bl = true;
printPattern(board);
while(bl) {
int player1 = 1 , player2 = 2 , userInput;
System.out.println("Please drop a RED disk at the column between 0
and 6:");
userInput = input.nextInt();
dropDisk(board, userInput , player1);
printPattern(board);
System.out.println("Please drop a YELLOW disk at the column
between 0 and 6:");
userInput = input.nextInt();
dropDisk(board, userInput , player2);
printPattern(board);
String win = checkWinner(board);
/*
Write code to announce if there is winner and end the game
*/
}
}
public static String[][] createEmptyBoard() {
/* This method prints the first empty pattern for the game
DON'T MODIFY THIS METHOD
*/
String[][] f = new String[7][15];
for (int i =0;i<f.length;i++) {
for (int j =0;j<f[i].length;j++) {
if (j% 2 == 0) f[i][j] ="|";
else f[i][j] = " ";
if (i==6) f[i][j]= "-";
}
}
return f;
} // end of createEmptyBoard
public static void printPattern(String[][] brd) {
for (int i = 0; i < 7; i++){
System.out.println(brd[i][0] + brd[i][1]+ brd[i][2]+ brd[i][3]+
brd[i][4]+ brd[i][5]+ brd[i][6]+ brd[i][7]+ brd[i][8]+ brd[i][9]+
brd[i][10]+ brd[i][11]+ brd[i][12]+ brd[i][13]+ brd[i][14]);
}
} // end of printPattern
public static void dropDisk(String[][] brd, int position, int
player) {
if (player == 1){
brd[6][position] = "R";
if(brd[6][position] == "R"){
brd[6][position] = brd[6 - 1][position];
}
}
else if (player == 2){
brd[6][position] = "Y";
if(brd[6][position] == "Y"){
brd[6][position] = brd[6 - 1][position];
}
}
/*Write your code to drop the disk at the position the user entered
depending on which player*/
} // end of dropDisk
The logic of dropDisk seems to be not finished yet.
It sets the brd[6][position] to R or Y, just to immediately after that set it to the current value of brd[5][position].
And this should always be null.
In Java, objects are passed into methods by value. This means that when you pass a parameter into a function, the JVM makes a copy of that object which can be modified in the method.
In this case, when you pass brd into dropDisk, it is copied, and you make changes to the copy inside dropDisk. But once dropDisk ends, that copy is discarded. No changes are made to the board from your main method. This is because your board is an array of Strings, and Strings are immutable, meaning that they cannot be changed after instantiation.
If you wanted the board from your main method to update, consider returning brd in dropDisk.

How to Make Program flow control jump back to a former loop in java?

So I have written a code that allows a user to find a word in a TextArea. I have nearly succeeded but for one thing. here, I will show you all the code and tell my problem.
if(ta.getText().length() != 0 && t1.getText().length() != 0)
{
char c1[] = ta.getText().trim().toCharArray();
char c2[] = t1.getText().trim().toCharArray();
for(int i=startFlag;i<c1.length;i++)
{
if(c1[i]==c2[0])
{
start = i;
break;
}
}
k=start;
for(int i=0;i<c2.length;i++)
{
if(c2[i] != c1[start++])
{
}
else
countFlag++;
}
if(countFlag==c2.length)
{
ta.select(k,c2.length);
startFlag++;
}
}
For reference, ta is the TextArea and t1 is the TextField where the user enters a word to find. i have a problem in the second for loop. What should I write in the if () block there so that whenever c2[i] != c1[start++] the control is shifted to the first for loop, that would again determine the value of start?
Create a method to get "start" that you can then call whenever you want.
if(ta.getText().length() != 0 && t1.getText().length() != 0)
{
char c1[] = ta.getText().trim().toCharArray();
char c2[] = t1.getText().trim().toCharArray();
k=getStart(startFlag, c1.length);
for(int i=0;i<c2.length;i++)
{
if(c2[i] != c1[start++])
{
start = getStart(startFlag, c1.length);
}
else
countFlag++;
}
if(countFlag==c2.length)
{
ta.select(k,c2.length);
startFlag++;
}
}
And getStart() is:
public int getStart(int startFlag, int length) {
for(int i=startFlag;i<length;i++)
{
if(c1[i]==c2[0])
{
return i;
}
}
}
You may need different inputs to getStart(), but hopefully this gets across the general idea.
The way your code is set up right now, what you're asking for is impossible. To do what you're asking, you'll need to refactor your current code into different methods. More specifically, you'll need to put the for loops into their own methods and then call these methods.
So what you would need to do is make a separate method for the for loop.
public static int startForLoop(int i) {
for(int i=startFlag;i<c1.length;i++)
{
if(c1[i]==c2[0])
{
start = i;
break;
}
}
}
Then you can just call startForLoop(0) initially and in the 2nd for loops if statment:
if(c2[i] != c1[start++])
{
startForLoop(start+1)
}
This will continue the for loop where it left off. If you need to run the 2nd for loop again then you have to make a separate method for it as well and basically place both of them in a while loop that continues till you find the result you want in the 2nd for loop.
May be this code piece help you what you are looking for.
Basically it moves along with the string to be searched in keeping in mind the index of the string to be searched for.
Sorry but i have implemented it in java, but the notion is same and the result returned is the best what i got.you must give it a try!
private static String searchString(String searchIN,String searchFOR){
if (searchFOR != "") {
int index = searchIN.toUpperCase().indexOf(searchFOR.toUpperCase());
String before = "";
String highlighted = "";
String after = "";
while (index >= 0) {
int len = searchFOR.length();
before = searchIN.substring(0, index);
highlighted = "\"" + searchFOR + "\"";//do what ever you want to do with searched string
after = searchIN.substring(index + len);
searchIN = before + highlighted + after;
index = searchIN.toUpperCase().indexOf(searchFOR.toUpperCase(), index + highlighted.length());
}
}
return searchIN;
}

Controlling a linked list queue from my user/main class, not working

Okay so I need to create queue(contains enqueue, dequeue, and isEmpty methods), queueNode(stores names, setters and getters), and queueUser(Main) classes. User enters one name at a time. Once 3 names have been entered, each new name entered will kick the front of the queue to the screen. This process will continue until the user enters "quit" as the name. Once this happens, all the remaining names will be displayed. I have everything but my user/main class. I can't seem to get it to work properly. It accepts 3 names, and after the third name is entered, displays the first name that was entered. Problem is, it stops there. I need it to keep going. I have a feeling I need a different loop, but I am just stuck right now. No help from my instructor, nothing in my textbook, and I have hit a brick wall. Any help or suggestions is greatly appreciated. I am still fairly new to Java and totally new to data structures.
queueUser
import java.util.Scanner;
public class queueUser {
public static void main(String[] args){
queue qName = new queue();
Scanner input = new Scanner(System.in);
int limit = 3;
String name;
String stop = "quit";
boolean flag = false;
do{
for(int i = 0; i < limit; i++){
System.out.println("Please enter one name: ");
name = input.nextLine();
if(!name.equalsIgnoreCase(stop)){
qName.enqueue(name);
flag = true;
}else{
flag = false;
while(!qName.isEmpty()){
System.out.println(qName.dequeue());
}
}
}
System.out.println(qName.dequeue());
}while(!flag);
}
}
queue
public class queue{
queueNode front, rear;
int count = 0;
public queue(){
front = null;
rear = null;
}
public boolean isEmpty(){
boolean empty = false;
if(front == null){
empty = true;
}else{
empty = false;
}
return empty;
}
public void enqueue(String pName){
queueNode node = new queueNode(pName);
if(isEmpty()){
front = node;
}else{
rear.setNext(node);
}
rear = node;
}
public String dequeue(){
String firstName = null;
if(isEmpty()){
System.out.println("Queue is empty!");
}else{
firstName = front.getName();
front = front.getNext();
}
return firstName;
}
}
queueNode
public class queueNode {
private String name;
private queueNode next;
public queueNode(String pName){
name = pName;
}
public void setNext(queueNode pNext){
next = pNext;
}
public queueNode getNext(){
return next;
}
public void setName(String pName){
name = pName;
}
public String getName(){
return name;
}
}
(Edit: your professor)
In your loop code you are saying this:
Give me three names, but I'll stop if any the most recent name given was "quit".
After you give me these three names, I will tell you whats on top of the queue.
Now do it all over again.
You are not removing from the queue when you repeat the loop until you have put in an additional 3 names. Even then, you will only dequeue the top, leaving 4 in the queue.
First and foremost, you have a variable int count in your queue class that is never used. If you use that, it will GREATLY improve the solution here. When something is enqueued, increment the count variable. Decrement when dequeued. Add a method that will return the count variable. Then just do this:
boolean flag = false;
do {
System.out.println("Please enter one name: ");
name = input.nextLine();
if(name.equalsIgnoreCase("stop")) flag = true;
if (!flag) qName.enqueue(name);
if (qName.getCount() > 3) System.out.println(qName.dequeue());
} while (!flag);
for (int x = 0; x < 3; x++) System.out.println(qName.dequeue());
If your instructor wants it otherwise, then your code should be as follows:
boolean flag = false;
int count = 0;
do {
System.out.println("Please enter one name: ");
name = input.nextLine();
if (name.equalsIgnoreCase("stop")) flag = true;
if (!flag) {
count++;
qName.enqueue(name);
}
if (count > 3) {
count--;
System.out.println(qName.dequeue());
}
} while (!flag);
for (int x = 0; x < 3; x++) System.out.println(qName.dequeue());
EDIT: All of these apply to your QueueUser class.
Make sure you CamelCase your class names.
The do-while loop is redundant since the flag starting value is false. You can accomplish the same thing by just making it a while loop (unless that was a requirement by your professor to have one).
while(!flag) {
//do your stuff
}
Completely get rid of the for loop.
The problem with your original code is that the flag values are switched around, the flag is already false so there is no need to declare that in the do-while loop. If you wanted to leave this redundant portion in it would need to be flag = false.
if(!name.equalsIgnoreCase(stop)){
qName.enqueue(name);
flag = true; //<-----SHOULD BE FALSE if you don't want to break the loop (is redundant)
}else {
flag = false //<-------CHANGE TO TRUE
Set the limit variable to 0 (or rename it count and set it to 0) to satisfy the count functionality your professor wants and add an if statement in your while loop to dequeue when it reaches 3.
count++
if(count >= 3) {
System.out.println(qName.dequeue());
}

For loop error, how do i fix this?

for(int x = 0;x<14;x++){
day[x]= theSheet.changeLetters(day[x]);
}
public String changeLetters(String entering){
if(entering.equalsIgnoreCase("a")){
entering = "10";
} else {
if(entering.equalsIgnoreCase("b")){
entering = "11";
} else {
if(entering.equalsIgnoreCase("c")){
entering = "12";
} else {
if(entering.equalsIgnoreCase("d")){
entering = "13";
} else {
if(entering.equalsIgnoreCase("e")){
entering = "14";
} else {
if(entering.equalsIgnoreCase("f")){
entering = "15";
} else {
if(entering.equalsIgnoreCase("g")){
entering = "16";
} else {
if(entering.equalsIgnoreCase("h")){
entering = "17";
}
}
}
}
}
}
}
}
return entering;
}
Says the error is here if(entering.equalsIgnoreCase("a")) and in the for loop I am using to run the method. I'm trying to change the letter put into the string into a number.
Can anyone explain to me where the error might be? I'm having trouble spotting the issue. it lets me enter the letters fine but it has an exception once it gets to this for loop and runs this method.
why don't you use
if (condition) {
// ...
} else if (condition2) {
// ...
} else if (condition3) {
// ...
}
// and so on
to make your code more readable. Your nested conditions are a mess. If you fix them, you might as well fix the error (if it's in the part of code you showed us).
Also add
System.out.println("Entering = '" + entering "'");
at the beginnig of your method to see if really receives what you are expecting it to receive.
Ok according to
Yes the code is being initialized in a for loop before that one using
for(int x =1;x<8;x++){ day[x-1] = JOptionPane.showInputDialog("Enter
hour pairs for day "+x +".\n Enter the first digit: "); day[x] =
JOptionPane.showInputDialog("Enter the second digit: "); } the letters
being put in the array are then changed into numbers using the for
loop posted earlier.
You have a logic error. You are overwriting previous entries and not filling the array up to 14 items. So items after 8 are left null, thus the NullPointerException.
Try this:
String[] day = new String[14];
for( int i = 0; i < 14; i+=2 ) {
day[i] = JOptionPane.showInputDialog("Enter hour pairs for day "+(i/2+1) +".\n Enter the first digit: ");
day[i+1] = JOptionPane.showInputDialog("Enter the second digit: ");
}
As a bonus, you can simplify the if-else code with:
public String changeLetters( String entering ) {
return String.valueOf(entering.toUpperCase().charAt(0) - 55);
}
As #jlordo already stated avoid nested if-statements with such a depth.
As an alternative you might use a switch statement in combination with an enum like this - although the following approach consists of more code it is more general and better suitable to be extended (e.g. using all letter of the alphabet and beyond) and it would make the code much more readable and more appropriate with respect to what you want to express.
Letter letter;
if (letter.equals("a")) letter = Letter.a;
if (letter.equals("A")) letter = Letter.A;
// and so on ...
switch (letter) {
case a : {
// do some code here ...
break;
}
case A : {
// do some code here ...
break;
}
// and so on ...
}
public enum Letter {
a (1),
A (2),
b (3),
B (4),
c (5),
C (6);
// and so on
private final int index;
Letter(int i) {
index = i;
}
public int getIndex () {
return index;
}
}
Note that if you're using Java 7 you can use the switch statement even without the enum since it accepts strings as well like this:
switch (entering) {
case "a" : {
// ...
}
// ...
}

Categories