Prevent JUnit test from getting stuck in while-loop - java

I'm currently writing some JUnit tests for some assignments on Replit.com's Teams for education. I have a test that's getting stuck, I believe, because of a while loop in the main method. If the first input is valid, according to the program, the test runs. If the first input is invalid, the test gets stuck.
Here's the test:
#Test
public void validPW(){
String correctOutput = "Enter a password >> Not enough uppercase letters!\nNot enough digits!\nReEnter a password >> Valid password\nGoodbye!";
try{
// IMPORTANT: Save the old System.out!
PrintStream old = System.out;
// Create a stream to hold the output
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//PrintStream ps = new PrintStream(baos);
System.setOut(new PrintStream(baos, false, "UTF-8"));
// IMPORTANT: save old Sytem.in!
InputStream is = System.in;
// Set new System.in
System.setIn(new ByteArrayInputStream("Iljvm4\nVaGN76js\n".getBytes()));
// Calling main method should save main method's output as string literal to baos.
String[] requiredArray = {"Hello", "There"};
ValidatePassword.main(requiredArray);
// Put things back
System.out.flush();
System.setOut(old);
//Restore
System.setIn(is);
assertEquals(correctOutput, baos.toString());
}catch(IOException ioe){
new IOException("i/o problem - test not executed\n");
}
}
Here's the program:
import java.util.*;
public class ValidatePassword {
public static void main(String[] args) {
String passWord;
boolean Valid = false;
final int NUM = 2; // two digits and two Upper case letters
// counters to count the required digits and letters
int upperCount = 0;
int lowerCount = 0;
int digitCount = 0;
while (!Valid) {
Scanner in = new Scanner(System.in);
int numSpaces = 0;
System.out.print("Enter a password >> ");
passWord = in.next();
in.nextLine(); // capture dangling newline char.
// Using a for loop to iterate over each character in the String
for (int i = 0; i < passWord.length(); i++) {
char ch = passWord.charAt(i);
if (Character.isUpperCase(ch)){ // Using the Character class's methods
upperCount++;
}
else if (Character.isLowerCase(ch)){
lowerCount++;
}
else if (Character.isDigit(ch)){
digitCount++;
}
}
if (upperCount >= NUM && lowerCount >= 3 && digitCount >= NUM) {
System.out.println("Valid password\nGoodbye!");
Valid = true;
} else {
if (upperCount < NUM)
System.out.println("Not enough uppercase letters!");
if (lowerCount < 3)
System.out.println("Not enough lowercase letters!");
if (digitCount < NUM)
System.out.println("Not enough digits!");
System.out.print("Re");
// Resetting the counters if not a valid password
upperCount = 0;
lowerCount = 0;
digitCount = 0;
}
}
}
}

First, the code in ValidatePassword tries to read the input stream beyond its end, so the scanner initialization needs to be moved out of the loop and a condition in.hasNextLine() needs to be checked.
Also, it's better to use a single reading of the line passWord = in.nextLine(); instead of a pair in.next(); in.nextLine();.
These two fixes should resolve the issue with incorrect loop.
Scanner in = new Scanner(System.in);
while (!Valid && in.hasNextLine()) {
int numSpaces = 0;
System.out.print("Enter a password >> ");
passWord = in.nextLine();
//in.nextLine(); // capture dangling newline char.
// ... keep the rest as is
And the last, correctOutput needs to be fixed for assertEquals to complete successfully.

Related

How to resolve the following program with a for loop into producing an appropriate output?

The following Java program is supposed to manipulate a string input by the user in such a way that the user will decide which character needs to be replaced with another and just the last character from the string should be replaced. Example if the user enters the string "OYOVESTER" and decides to replace "O" with "L", the program should output the following result: "OYLVESTER" (notice that only the last "O" was replaced with "L")
NOTE: YOU CANNOT USE BREAK COMMAND TO STOP THE LOOP. IT IS PROHIBITED.
import java.util.Scanner;
public class StringFun {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter the string to be manipulated");
String inString = keyboard.nextLine();
String outString = "";
//Replace Last
System.out.println("Enter the character to replace");
char oldCharF = keyboard.next().charAt(0);
System.out.println("Enter the new character");
char newCharF = keyboard.next().charAt(0);
int count = 0; // variable that tracks number of letter occurrences
for(int index = inString.length() - 1;index >= 0;index--) {
if(inString.charAt(index) == oldCharF && count < 1){
outString = newCharF + outString;
outString = outString + inString.substring(0,index);
count++;
}
if (count < 1) {
outString = outString + inString.charAt(index);
}
}
System.out.print("The new sentence is: "+outString);
}
}
I keep getting the following output which is incorrect:
Enter the string to be manipulated
OYOVESTER
Enter the character to replace
O
Enter the new character
L
The new sentence is: LRETSEVOY
There are many simpler ways to achieve your requirement but I hope you have to demonstrate this with loops (without breaks)
Then you can use some thing like this :
boolean skip = false;
for (int index = inString.length() - 1; index >= 0; index--) {
if (!skip && inString.charAt(index) == oldCharF) {
outString = newCharF + outString;
skip = true;
}
else {
outString = inString.charAt(index) + outString;
}
}
PS : Using String concatenation inside loops is not recommended since
every String concatenation copies the whole String, usually it is preferable to
replace it with explicit calls to StringBuilder.append() or StringBuffer.append()
No break command seems like a weird condition. You could just a boolean value, and other methods, to break the loop when you need. Why not do something like this?
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter the string to be manipulated");
String word = keyboard.nextLine();
//Replace Last
System.out.println("Enter the character to replace");
char oldCharF = keyboard.next().charAt(0);
System.out.println("Enter the new character");
char newCharF = keyboard.next().charAt(0);
int index = word.lastIndexOf(oldCharF);
if(index > 1){
word = word.substring(0,index) + newCharF + word.substring(index+1);
}
System.out.println("The new sentence is: " + word);
}

Why does setting a value to a specific subscript of an array not print it out?

In the code below, at the bottom, for some reason although I assign the value of encodingCharacter = encodeArray[j];. After that I try to print that specific subscript value out. But for some reason that statement is causing issues. After I run the program I see that it ran 2 empty lines, I don't know why I can't assign the char value 'z' to encodingCharacter.
import java.util.Scanner;
public class UserInputDemo1
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
//creating scanner named input.
System.out.println ("Would you like to encode or decode a message.");
System.out.println ("If you would like to encode a message enter true. If you would like to decode a message enter false");
System.out.println("Note that blank spaces are seperated by a space and the message terminates with a period.");
boolean encodeOrDecode = input.nextBoolean();
if (encodeOrDecode)
{
Scanner scan = new Scanner(System.in);
System.out.println("Please enter the message you would like to be encoded.");
String encodeMessage = scan.nextLine();
char[] encodeCharArray = encodeMessage.toCharArray();
encodeMessage(encodeCharArray);
}
if (!encodeOrDecode)
{
Scanner scan = new Scanner(System.in);
System.out.println("Please enter the message you would like to be decoded.");
String decodeMessage = scan.nextLine();
char[] decodeCharArray = decodeMessage.toCharArray();
}
}
public static void encodeMessage (char encoding [])
{
char encodeArray [] = new char [encoding.length];
for (int j = 0; j < encoding.length; j++ )
{
char encodingCharacter = encoding[j];
if (encodingCharacter == 'a')
{
encodingCharacter = 'z';
System.out.println(encodingCharacter);
encodingCharacter = encodeArray[j];
System.out.println(encodeArray[j]);
}
if (encodingCharacter == 'b')
{
encodingCharacter = 'y';
System.out.println(encodingCharacter);
encodingCharacter = encodeArray[j];
}
}
String encodedArray = new String(encodeArray);
System.out.println (encodeArray);
}
}
At line 15 is where the java.util.InputMismatchException occurs.
Your input.nextBoolean() returns whether the next token of the input is a boolean, rather than whether there is another character.
I believe you are looking for input.hasNext(), or something of the sort.

Random String Generator keeps adding to previous iterations

I am writing a program that takes a user's input for a string that must be of length 6, and creates a random version of that string. Then, it prints out 5-10 iterations of a randomised string. For example:
The input of 8 and abcdef would create 8 lines of random variations of abcdef. The program below does that, but it's adding strings together, as so:
abbdfe
abbdfeacbfed
and so on. Does anyone know how to change it so it would print abbdfe acbfed and so on.
I know there are some functional issues with my code but it works as a start.
package matrixMaker;
import java.util.Scanner;
import java.util.Random;
public class matrixMaker
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Please enter a number between 5 and 10, inclusively: ");
int userInput = in.nextInt();
in.nextLine();
System.out.print("Please enter a string of length 6 characters: ");
String textToChange = in.nextLine();
String randomText = "";
int length = 6;
// Print error if text is not 6 characters long.
while(textToChange.length() != 6)
{
System.out.println("Error! Enter a string of length 6.");
}
// If input is 6 characters, print out randomText X amount of times, depending on the user's specification of user.
if(textToChange.length() == 6)
{
for (int i = 1; i <= userInput; i++)
{
// Initialise array to create random order of chars.
Random rand = new Random();
char[] text = new char[length];
for(int a = 0; a < length; a++)
{
text[a] = textToChange.charAt(rand.nextInt(textToChange.length()));
}
// Take the chars from array and concatenate them into a string of the same size as the text variable.
for(int a = 0; a < text.length; a++)
{
randomText += text[a];
}
System.out.printf(randomText + "\n");
}
}
in.close();
}
}
You seem to be initializing the variable randomText at the top of the method, but keep adding to the same variable inside the loop, so it will keep adding to itself.
String randomText = "";
randomText += text[a];
Either initialize the randomText String inside the loop, or after your last line inside the loop, assign it back to an empty string again.
Btw, you seem to have another error here:
// Print error if text is not 6 characters long.
while(textToChange.length() != 6)
{
System.out.println("Error! Enter a string of length 6.");
}
This loop will go for infinite, you need to add a way to allow the user to change the input after the error is displayed.
while(textToChange.length() != 6)
{
System.out.println("Error! Enter a string of length 6.");
in.nextLine();
textToChange = in.nextLine();
}
--Edit added to OP comment:
To print the character of the odd generated text on the odd row number; one way to do it is to consider pushing your generated randomText to an empty ArrayList which you initialize outside the loop..then you can loop over your ArrayList separately. You can think of ways to refactor this and put in an outside method in the way you like. like this:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Please enter a number between 5 and 10, inclusively: ");
int userInput = in.nextInt();
in.nextLine();
System.out.print("Please enter a string of length 6 characters: ");
String textToChange = in.nextLine();
int length = 6;
// Print error if text is not 6 characters long.
while (textToChange.length() != 6) {
System.out.println("Error! Enter a string of length 6.");
in.nextLine();
textToChange = in.nextLine();
}
//new array list for results of random text generated
ArrayList<String> randomTextArray = new ArrayList<>();
// If input is 6 characters, print out randomText X amount of times, depending on the user's specification of user.
if (textToChange.length() == 6) {
for (int i = 1; i <= userInput; i++) {
String randomText = "";
// Initialise array to create random order of chars.
Random rand = new Random();
char[] text = new char[length];
for (int a = 0; a < length; a++) {
text[a] = textToChange.charAt(rand.nextInt(textToChange.length()));
}
// Take the chars from array and concatenate them into a string of the same size as the text variable.
for (int a = 0; a < text.length; a++) {
randomText += text[a];
}
randomTextArray.add(randomText);
System.out.printf(randomText + "\n");
}
System.out.printf("Odd Characters \n");
String oddCharsOfRandomText = "";
for (int i=0; i < randomTextArray.size(); i++) {
if (!(i%2 == 0)) { //resolve true only if we are in an odd line
for (int x=0; x <= randomTextArray.get(i).length(); x++ ){
if (!(x%2 == 0)) { //resolve true only if we are in an odd character
oddCharsOfRandomText += randomTextArray.get(i).charAt(x);
}
}
}
}
System.out.printf(oddCharsOfRandomText + "\n");
}
in.close();
}

only checks first and last character

I am new to java and am trying to create a palindrome word program, to check if the word backwards is the same.
public static void isPalindromeWord(){
Scanner input = new Scanner (System.in);
System.out.print("Enter a word to check: ");
String word = input.next().toLowerCase();
String reversed = new StringBuffer(word).reverse().toString();
int len = word.length();
for(int x = 0; x < len ; x++){
if(word.charAt(x) == reversed.charAt(x)){
System.out.println("True");
}else{
System.out.println("False");
}
}
}
Please excuse if I've done anything wrong, I have only started learning today.
My problem is :
With the current it outputs True for something such as "otto" which is a palindrome. But it also does True for "oplko" which isn't. So I know that it only checks the first and last letters but I thought that with the for loop it will go through each letter?
Can someone be kind enough to explain where I am going wrong and suggest how to fix it? The reason I am using a for loop is because the task is requiring me to do so.
You are very close to the solution. Since you have already reversed the string you can check if they are equal
new StringBuffer(word).reverse().equals(word);
Edit: Added one more solution for using loop
What you are doing in the loop is mostly correct. You are getting True for oplko is because you are not exiting the loop when the word.charAt(x) == reversed.charAt(x) condition fails. This can be fixed by
public static void isPalindromeWord() {
Scanner input = new Scanner(System.in);
System.out.print("Enter a word to check: ");
String word = input.next().toLowerCase();
String reversed = new StringBuffer(word).reverse().toString();
int len = word.length();
for (int x = 0; x < len; x++) {
if (word.charAt(x) != reversed.charAt(x)) {
System.out.println("False");
return;
}
}
System.out.println("True");
}
there are a lot of ways to do what you want (including Anthony C's very elegant answer), but here is a simple fix to make yours work :
public static void isPalindromeWord(){
Scanner input = new Scanner (System.in);
System.out.print("Enter a word to check: ");
String word = input.next().toLowerCase();
//you don't really need to get a reverse here
//String reversed = new StringBuffer(word).reverse().toString();
int len = (int)(word.length() / 2);//only check half (and not evnt the middle one for odd numbers
boolean isPalindrom = true;
for(int x = 0; x < len ; x++){
if(word.charAt(x) != word.charAt(word.length() - 1 - x)){
isPalindrom = false;
//at least one difference, this is not a palindrome
break;
}
}
if(isPalindrom)
System.out.println("True");//the for wasn't broken
else
System.out.println("False");
}
public static void isPalindromeWord(){
Scanner input = new Scanner (System.in);
System.out.print("Enter a word to check: ");
String word = input.next();
String reversed = input.next();
char c[]=word.toLowerCase().toCharArray();
char d[]=reversed.toLowerCase().toCharArray();
if(word.length() != reversed.length()) System.out.print("False ");
Arrays.sort(c);
Arrays.sort(d);
if(Arrays.equals(c,d)) System.out.print("True ");
else System.out.print("False ");
}
Just to describe where you have a mistake. You are writing in console on every step of loop, doesn't matter which result of comparing do you have.
boolean isPolindrom = true;
for(int x = 0; x < len ; x++){
isPolindrom = (word.charAt(x) == reversed.charAt(x)); //compare chars and store result into variable
if (!isPolindrom) { //if chars are different break a loop, because word is already not a polindrom
break;
}
}
System.out.println(isPolindrom); //output result
Solution from #AnthonyC is really better

Unable to accept two strings in first iteration but works fine during successive iterations

I'm scanning 2 strings during each iteration and storing it in s and t. Only during the first iteration, the first string that I scan is getting stored in t and not in s (I got to know this by debugging in eclipse). During successive iterations the piece of code works fine. I'm not able to understand what is going on during the first iteration. Please help me. Thanks.
import java.io.*;
import java.util.*;
public class ResidentInfo {
public static void main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
Scanner scan = new Scanner(System.in);
int i,n;
n = scan.nextInt();
for(i=0 ; i<n ; i++)
{
int sl,tl,j,k;
String s, t;
boolean flag = false;
s = scan.nextLine();
t = scan.nextLine();
sl = s.length();
tl = t.length();
char[] sa = new char[sl];
char[] ta = new char[tl];
sa = s.toCharArray();
ta = t.toCharArray();
for(j=0 ; j<sl ; j++)
{
for(k=0 ; k<tl ; k++)
{
if(sa[j]==ta[k])
{
flag = true;
break;
}
}
if(flag)
{
break;
}
}
if(flag)
{
System.out.println("YES");
}
else
{
System.out.println("NO");
}
}
}
}
The first thing this code does is determine if the two strings' lengths are equal. If the strings' lengths are not equal, the code prints no. If the lengths are equal, the code then checks each character in the exact same index in the strings, to see if they are equal. If the characters at a specific index is not equal, the code breaks the loop and prints no. If all of the characters at each index are equal the code prints yes.
You asked a question about next() and nextLine().
Try: Question asked already.
Scanner scan = new Scanner(System.in);
System.out.print("enter a number: ");
int n = scan.nextInt();
for(int i=0; i < n; i++)
{
boolean flag = true;
System.out.print("enter something for s: ");
String s = scan.next();
System.out.print("enter something for t: ");
String t = scan.next();
if(s.length() == t.length())
{
for(int j = 0; j < s.length(); j++)
{
if(s.charAt(j) != t.charAt(j))
{
flag = false;
break;
}
}
if(flag)
{
System.out.println("Yes");
}
else
{
System.out.println("NO");
}
}
else
{
System.out.println("NO");
}

Categories

Resources