Java ISBN checksum generator -- infinite loop? - java

I need to build this ISBN checksum generator (for both ISBN-10 and ISBN-13) for my CS class using strings, chars, and a bunch of nested loops and conditional statements. Somewhere in this mess, I think something is triggering an infinite loop because when I am prompted for an input, I give the input and press enter and it just goes to a new line and expects me to enter a bunch more data I guess when instead it should be prompting me again to enter another one after each successful entry and otherwise tell me it's incorrect and then still again ask for another input. And when I type in quit it doesn't end the program and display the checksum results like it's supposed to, instead it exhibits the same behavior as other inputs do. If I type in quit the first time without giving the program any numbers it does end the program properly but of course, the values of the output variables are null.
My code thus far:
/******************************************************************************
* Program Name: Lab05A - ISBN
* Program Description: Calculate ISBN-10 AND ISBN-13
* Program Author: xxxxxxxxx
* Date Created: 10/10/2018
* Change# Change Date Programmer Name Description
* ------- ------------ ------------------- ---------------------
******************************************************************************/
package lab05a;
import java.util.Scanner;
public class Lab05A {
public static void main(String[] args) {
// Input for s
Scanner input = new Scanner(System.in); // Create new scanner
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: "); // our ever-lasting prompt
String s = input.next(); // declare string variable "s" and set it equal to next input from user.
String output10 = null; // Declaring string output10
String output13 = null; // Declaring string output13
// main while loop
while (!"QUIT".equals(s)) { //this will run as long as the program does not receive an input of "QUIT", not case sensitive.
char checkDigit;
char checkSum = '0';
if (s.length() == 9) { //if the length of the inputted string is 9 characters...
int sum = 0; // initialize sum variable
for (int i=0; i <= s.length();) {
sum = sum + ((s.charAt(i) - '0') * (i + 1));
}
if (sum % 11 == 10) {
checkDigit = 'X';
}
else {
checkDigit = (char) ('0' + (sum % 11));
}
output10 = output10 + "\n" + s + checkDigit;
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: ");
s = input.next();
}
else if (s.length() == 12) {
int sum = 0;
for (int i=0; i <= s.length();) {
if (i % 2 == 0) {
sum = sum + (s.charAt(i) - '0');
}
else {
sum = sum + (s.charAt(i) - '0') * 3;
}
checkSum = (char) (10 - sum % 10);
if (checkSum == 10) {
checkSum = 0;
}
output13 = "\n" + output13 + checkSum;
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: ");
s = input.next();
}
}
else if (!s.toUpperCase().equals("QUIT")) {
System.out.println(s + " is invalid input.");
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: ");
s = input.next();
}
}
System.out.println("The 10 digit ISBNs are \n" + output10);
System.out.println("The 13 digit ISBNs are \n" + output13);
}
}
Instructions
Flowchart as a separate image since it's kinda small in the instructions doc
Thanks for your help.

Yes, you are missing the incrementor in this for loop
for (int i=0; i <= s.length();) {
change to
for (int i=0; i <= s.length(); i++) {
I am sure that you do not want <=, maybe just <
so
for (int i=0; i < s.length(); i++) {
BTW this is easy to solve if you debug your code - an essential skill --
edit
If you have the below code (and s.length == 12)
for (int i=0; i < s.length(); i++) {
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: ");
s = input.next();
}
Then it will execute 12 times. Fix your loop

UPDATED CODE since I implemented some of the suggestions here:
package lab05a;
import java.util.Scanner;
public class Lab05A {
public static void main(String[] args) {
// Input for s
Scanner input = new Scanner(System.in); // Create new scanner
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: "); // our ever-lasting prompt
String s = input.next(); // declare string variable "s" and set it equal to next input from user.
String output10 = ""; // Declaring string output10
String output13 = ""; // Declaring string output13
// main while loop
while (!"QUIT".equalsIgnoreCase(s)) { //this will run as long as the program does not receive an input of "QUIT", not case sensitive.
char checkDigit;
char checkSum = '0';
if (s.length() == 9) { //if the length of the inputted string is 9 characters...
int sum = 0; // initialize sum variable
for (int i=0; i < s.length(); i++) {
sum = sum + ((s.charAt(i) - '0') * (i + 1));
}
if (sum % 11 == 10) {
checkDigit = 'X';
}
else {
checkDigit = (char) ('0' + (sum % 11));
}
output10 = output10 + "\n" + s + checkDigit;
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: ");
s = input.next();
}
else if (s.length() == 12) {
int sum = 0;
for (int i=0; i < s.length(); i++) {
if (i % 2 == 0) {
sum = sum + (s.charAt(i) - '0');
}
else {
sum = sum + (s.charAt(i) - '0') * 3;
}
checkSum = (char) (10 - sum % 10);
if (checkSum == 10) {
checkSum = 0;
}
output13 = "\n" + output13 + s + checkSum;
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: ");
s = input.next();
}
}
else if (!"QUIT".equalsIgnoreCase(s)) {
System.out.println(s + " is invalid input.");
System.out.println("Enter the first 9 or 12 digits of an ISBN number. Enter QUIT to exit: ");
s = input.next();
}
}
System.out.println("The 10 digit ISBNs are \n" + output10);
System.out.println("The 13 digit ISBNs are \n" + output13);
}
}

Related

How to show only occurrences of numbers user input in java?

I'm new to programing and trying to solve this problem, but have no idea what I did wrong.
The program is supposed to take user input until 0 is entered and after that, print out information of occurrences of numbers user input - and here is my problem.
The program I wrote shows occurrences of all numbers (up to max number that can be input), not only those that user wrote.
My code:
package numbers;
import java.util.Scanner;
public class Numbers {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int[] occurences = new int[11];
int num = scan.nextInt();
while (num > 0 && num <= 11) {
occurences[num]++;
num = scan.nextInt();
}
for (int i = 0; i < 11; i++) {
System.out.print("Value: " + i + " Occurences: " + occurences[i] + " ");
}
}
}
Use if statement to print only numbers with occurences higher than 0.
Side notes:
Array values initialization is not needed:
for (int i = 0; i < 11; i++) {
occurences[i] = 0;
}
Value at each index is already 0, check this question.
While loop condition, does not make much sense
while (num > 0 && num <= 11) {
occurences[num]++;
num = scan.nextInt();
}
Array size is 11, meaning indexes range from 0 to 10 inclusive. Since you allow input 11, you will get ArrayIndexOutOfBoundsException.
You can make use of map.
Map<Integer, Integer> occ = new HashMap<>();
int num = scan.nextInt();
while (num > 0 && num <= 11) {
occ.put(num, occ.getOrDefault(num, 0)+1);
num = scan.nextInt();
}
for(int i : occ.keySet()){
System.out.print("Value: " + i + " Occurences: " + occ.get(i) + " ");
}

Filling an array with doubles from user in a given range

So it's time to come back to the users of stackoverflow for help again on an assignment.
I'm supposed to fill an array with a size of 10 with doubles given from the user. The entered numbers are supposed to be grades so they have to be in the range of 0 - 100. Anything out of the range (more, less, or incorrect characters) are not saved to the array and the user is prompted to try again at the given index of the array. After either the array is filled to the max value or the user presses enter to skip, the program is supposed to return the grades entered in order and display the average.
public static final SIZE = 10;
Scanner userIn = new Scanner(System.in);
double[] grades = new double [SIZE];
int counter = 0;
int counterList = 1;
boolean exit = false;
String sTemp = "";
double gradeNum = 0;
double avrGrade = 0.0;
double sum = 0;
while((counter < SIZE) && (!exit)) {
System.out.println("Enter grade " + counterList +
", or press enter to quit.");
sTemp = userIn.nextLine();
counterList++;
if(sTemp.length() < 1) {
exit = true; //ending for loop
} else {
gradeNum = Double.parseDouble(sTemp);
grades[counter] = gradeNum;
counter++;
} //else statement
} //end of while loop
counterList = 1;
System.out.println("You entered " + counter + " grades total.");
for(int i = 0; i <= counter; i++) {
System.out.println("Your grade " + counterList + " is " + grades[i]);
counterList++;
}
for(int i = 0; i < grades.length; i++)
sum += grades[i];
System.out.println("The average grade is: " + sum / grades.length);
So I finished taking my user's input and calculating the average but I'm having trouble setting the range and not saving the invalid inputs. I also feel like once I started to struggle I got really sloppy and there might be stuff going on in there that's not needed. Let me know anything helps!
An example of what the program should output given different scenarios
You can trim down your code. There are variables that you don't require. Explanations after the code.
import java.util.Scanner;
public class GradeAvg {
private static final int SIZE = 10;
public static void main(String[] args) {
Scanner userIn = new Scanner(System.in);
double[] grades = new double [SIZE];
int counter = 0;
String sTemp = "";
double sum = 0;
while(counter < SIZE) {
System.out.println("Please enter grade " + (counter + 1) + ": ");
sTemp = userIn.nextLine();
if (sTemp.isEmpty()) {
break;
}
try {
grades[counter] = Double.parseDouble(sTemp);
}
catch (NumberFormatException xNumberFormat) {
System.out.println("That wasn't a valid percentage, I need a number between 0 - 100. Try again.");
continue;
}
if (grades[counter] < 0 || grades[counter] > 100) {
System.out.println("That wasn't a valid percentage, I need a number between 0 - 100. Try again.");
continue;
}
sum += grades[counter];
counter++;
} //end of while loop
for (int i = 0; i < counter; i++) {
System.out.println("grade " + (i + 1) + ": " + grades[i]);
}
System.out.println();
System.out.println("number of valid grades entered: " + counter);
System.out.println();
System.out.println("average: " + sum / counter);
}
}
After accepting the user input, first check if the user simply pressed <ENTER> without entering a value. I used method isEmpty(), of class java.lang.String, to do this check. If the user simply pressed <ENTER>, you need to exit the while loop. This is what break does. So no need for boolean variable exit.
Variable counter is all you need to both keep track of how many grades have been entered and which index of array grades needs to be assigned a value, so no need for variable counterList.
If an invalid value is entered, continue skips the rest of the while loop and starts a new loop iteration. Think of it as a sort of goto that jumps back to the statement:
while (counter < SIZE)
You can assign a value directly to an element in array grades so no need for variable gradeNum.
You can update variable sum inside the while loop so no need for the extra for loop in order to calculate the average. By the way, your calculation of the average is incorrect since you are dividing by the size of array grades and not by the actual number of grades that were entered. Adding up all the elements in array grades still gives you the correct sum since all elements of the array are implicitly initialized to 0 (zero).
I changed what the program displays on the screen so as to match your example of what the program should output given different scenarios.
Here is the output according to the sample you provided.
Please enter grade 1:
A
That wasn't a valid percentage, I need a number between 0 - 100. Try again.
Please enter grade 1:
100
Please enter grade 2:
Bob
That wasn't a valid percentage, I need a number between 0 - 100. Try again.
Please enter grade 2:
41.5
Please enter grade 3:
-7
That wasn't a valid percentage, I need a number between 0 - 100. Try again.
Please enter grade 3:
grade 1: 100.0
grade 2: 41.5
number of valid grades entered: 2
average: 70.75
I made some adjustments:
final int SIZE = 10;
Scanner userIn = new Scanner(System.in);
double[] grades = new double [SIZE];
int counter = 0;
String sTemp = "";
double gradeNum = 0;
double sum = 0;
while(counter < SIZE) {
boolean err = false;
System.out.println("Enter grade " + (counter + 1) +
", or press enter to quit.");
sTemp = userIn.nextLine();
try {
gradeNum = Double.parseDouble(sTemp);
} catch(NumberFormatException ex)
{
err = true;
}
if(sTemp.length() < 1) {
break; //ending the loop
} else if(gradeNum <= 100 && gradeNum >= 0 && !err)
{
grades[counter] = gradeNum;
counter++;
} else
{
System.out.println("That wasn't a valid percentage, I need a number between 0 - 100. Try again.");
}
} //end of while loop
userIn.close(); //closing the Scanner
System.out.println("You entered " + counter + " grades total.");
for(int i = 0; i < counter; i++) {
System.out.println("Your grade " + (i + 1)+ " is " + grades[i]);
}
for(int i = 0; i < counter; i++) {
sum += grades[i];
}
System.out.println("\nNumber of valid grades entered: " + counter + "\n");
System.out.println("The average grade is: " + sum / counter);
}
This seems to work, I made some corrections (like SIZE declaration, took out the println from the last loop, replaced exit with a break statement, ...). The most relevant changes are the input checks and the average grade calculation (I used counter instead of grades.length because it is always 10). The try/catch checks if the input string contains only numbers.
(sorry for bad english, just ask if something isn't clear)

How to make while loop check if there are 16 digits in a string

How do I make the loop check if there is 16 digits in a string and reset the string if there is not enough. I am trying to make a credit card program that will calculate the check digit. I have everything else working I just cant get the program to check the number of digits in the user inputted string.Thanks for any and all help!
import java.util.Scanner;
public class LuhnAlgorithm {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter a number credit card number (Enter a blank line to quit: ");
String nums = input.nextLine();
int i = 0;
char chk = nums.charAt(15);
while(!nums .equals("") ) {
if (nums.length()<16 || nums.length() > 15){ //How do I get this line to reset the while loop?
System.out.println("ERROR! Number MUST have exactly 16 digits.");
}
int sum = 0;
for( i = 0; i < 15; i++) {
char numc = nums.charAt(i);
int num = Character.getNumericValue(numc);
if ( i % 2 == 0 ) {
num = num * 2;
if ( num >= 10) {
num = num - 9;
}
}
sum = num + sum;
}
int sum2 = sum % 10;
if (sum2 > 0) {
sum2 = 10 - sum2;
}
int chk2 = Character.getNumericValue(chk);
System.out.println("The check digit should be: " + sum2);
System.out.println("The check digit is: " + chk);
if ( sum2 == chk2) {
System.out.println("Number is valid.");
}
else {
System.out.println("Number is not valid. ");
}
System.out.print("Enter a number credit card number (Enter a blank line to quit:) ");
nums = input.nextLine();
}
System.out.println("Goodbye!");
input.close();
}
}
You can include your code that you only want done if the length ==16 in an if statement.
Meaning, instead of:
if (nums.length != 16) {
//code if there is an error
}
//code if there is no error
you can do:
if (nums.length == 16) {
//code if there is no error
} else {
//code if there is an error
}
(I also want to point out that you set chk = nums.charAt(15) before your while loop, but you don't reset it in the while loop for the next time the user inputs a new credit card number.)
You can bring the prompts and all your initialization except the scanner itself into the while loop. Then if they say "", break to exit the loop. If they say a number that is too short or too long, say continue to go back to the prompting.
Thus:
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (true) {
System.out.print("Enter a number credit card number (Enter a blank line to quit: ");
String nums = input.nextLine().trim();
if (nums.length() == 0) {
break; //exits while loop
}
if (nums.length() != 16) { //How do I get this line to reset the while loop?
System.out.println("ERROR! Number MUST have exactly 16 digits.");
continue; //goes back to the beginning right away
}
//still here, process the number
char chk = nums.charAt(15);
int sum = 0;
for (int i = 0; i < 15; i++) {
char numc = nums.charAt(i);
int num = Character.getNumericValue(numc);
if (i % 2 == 0) {
num = num * 2;
if (num >= 10) {
num = num - 9;
}
}
sum = num + sum;
}
int sum2 = sum % 10;
if (sum2 > 0) {
sum2 = 10 - sum2;
}
int chk2 = Character.getNumericValue(chk);
System.out.println("The check digit should be: " + sum2);
System.out.println("The check digit is: " + chk);
if (sum2 == chk2) {
System.out.println("Number is valid.");
} else {
System.out.println("Number is not valid. ");
}
}
System.out.println("Goodbye!");
input.close();
}
}

Java, removing duplicate output from separate lines generated by nested for loops

I am new to java, and I have this program that takes a number between 1 and 10 from a user and displays the multiplication table for that number. Here is the code:
import java.util.Scanner; //importing the scanner library
public class question3 {
public static void main(String[] args){
Scanner keyb = new Scanner(System.in);
System.out.print("Enter an integer between 1 and 10: ");
int userNumber = keyb.nextInt();
while (userNumber <= 0 || userNumber >= 10){
System.out.print("Enter an integer between 1 and 10: ");
userNumber = keyb.nextInt();
}
keyb.close();
for (int counter = 1; counter <= userNumber; counter++){
System.out.print(counter + "\t");
for (int number = 2; number <= userNumber; number++){
System.out.print((counter * number) + "\t");
}
System.out.println(" ");
}
}
}
So if the user enters 4, the output will look like:
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
This works. I need to take the multiplication table and remove any duplicate numbers. So if the user enters 4, the desired output will look like:
1 2 3 4
4 6 8
9 12
16
How can I remove the duplicate output when it only exists in the for loop print statements?
Thanks!
Set<Integer> generatedNumbers = new HashSet<>();
for(int counter = 1; counter <= userNumber; counter+=1)
{
System.out.print((generatedNumbers.contains(counter) ? "" : counter) + "\t");
generatedNumbers.add(counter);
for(int number = 2; number <= userNumber; number+=1)
{
int product = number * counter;
System.out.print((generatedNumbers.contains(product) ? "" : product) + "\t");
generatedNumbers.add(product);
}
System.out.println();
}
You need an extra List<Integer> to check the condition only: (Just need to align the space(DIY))
public class question3 {
public static void main(String[] args) {
Scanner keyb = new Scanner(System.in);
System.out.print("Enter an integer between 1 and 10: ");
int userNumber = keyb.nextInt();
while (userNumber <= 0 || userNumber >= 10) {
System.out.print("Enter an integer between 1 and 10: ");
userNumber = keyb.nextInt();
}
keyb.close();
List<Integer> arr = new ArrayList<Integer>();
for (int counter = 1; counter <= userNumber; counter++) {
if (!arr.contains(counter)) {
System.out.print(counter + "\t");
arr.add(counter);
} else
System.out.println("\t");
for (int number = 2; number <= userNumber; number++) {
if (!arr.contains((counter * number))) {
System.out.print((counter * number) + "\t");
arr.add((counter * number));
} else {
System.out.print("\t");
}
}
System.out.println("\t");
}
}
}
EDIT:
Also utilize do-while loop here to avoid duplicate code to ask input like
System.out.print("Enter an integer between 1 and 10: ");
int userNumber = keyb.nextInt();

UPC Code Problems

I have been trying to find out why my output is not what it is supposed to be. The Samples given are
Enter a UPC (enter a blank line to quit): 036000291453 Check digit
should be: 2 Check digit is: 3 UPC is not valid
Enter a UPC (enter a blank line to quit): 036000291452 Check digit
should be: 2 Check digit is: 2 UPC is valid
Enter a UPC (enter a blank line to quit): 014633149077 Check digit
should be: 4 Check digit is: 7 UPC is not valid
Enter a UPC (enter a blank line to quit): 014633149074 Check digit
should be: 4 Check digit is: 4 UPC is valid
Enter a UPC (enter a blank line to quit): 0853911765722 ERROR! UPC
MUST have exactly 12 digits
Enter a UPC (enter a blank line to quit): 085391176572 Check digit
should be: 2 Check digit is: 2 UPC is valid
Enter a UPC (enter a blank line to quit): Goodbye!
The algorithm of getting the that output is this From left to right, add the digits in the odd-numbered positions (starting the count from 1) and multiply the result by 3.
From left to right, add the digits in the even-numbered positions to the total computed in step 1
Take the result from step 2 and compute the remainder when divided by 10 (result modulo 10). If the remainder is not zero, subtract this remainder from 10 to get the check digit. If the remainder is zero, then the check digit should be 0.
String str1 = validinput(in);
int odd1 = odd(str1);
int even1 = even(str1);
int f = (odd1+even1)%10;
if(f != 0){
f = 10-f;
}
System.out.println(odd1);
System.out.println(even1);
System.out.println("Check digit should be: "+f);
System.out.println("Check digit is: "+str1.charAt(11));
int y = Character.getNumericValue(str1.charAt(11));
if (f == y){
System.out.println("UPC is valid");
}
else{
System.out.println("UPC is not valid");
}
}
private static String validinput(Scanner inScanner){
System.out.print("Enter a UPC (enter a blank line to quit): ");
String str = inScanner.nextLine();
while(str.length() != 12){
if (str.length() == 0){
System.out.println("Goodbye");
break;
}
else{
System.out.println("ERROR! UPC MUST have exactly 12 digits");
System.out.print("Enter a UPC (enter a blank line to quit): ");
str = inScanner.nextLine();
}
}
return str;
}
private static int odd(String input){
int i = 1;
char ch;
int sumOdd = 0;
while (i < 11){
ch = input.charAt(i);
int x = Character.getNumericValue(ch);
sumOdd = x +sumOdd;
i += 2;
}
int Mx3=sumOdd*3;
return Mx3;
}
private static int even(String input){
int i = 0;
char ch;
int sumEven = 0;
while (i < 11){
ch = input.charAt(i);
int x = Character.getNumericValue(ch);
sumEven = x +sumEven;
i += 2;
}
return sumEven;
}
charAt() uses null-based indexes, but the instruction wants you to use 1-based indexes. So, in odd() start with i = 0. And in even() start with i = 1.
Secondly, you use Character.getNumericValue(ch) to get the unicode codepoint value of the character, but the instructions ask you to use the digit value. So, use Integer.parseInt(ch.ToString()) instead.
private static int odd(String input){
int i = 0;
char ch;
int sumOdd = 0;
while (i < 11){
ch = input.charAt(i);
int x = Integer.parseInt(ch.ToString());
sumOdd = x +sumOdd;
i += 2;
}
int Mx3=sumOdd*3;
return Mx3;
}
private static int even(String input){
int i = 1;
char ch;
int sumEven = 0;
while (i < 11){
ch = input.charAt(i);
int x = Integer.parseInt(ch.ToString());
sumEven = x +sumEven;
i += 2;
}
return sumEven;
}
Code not tested

Categories