Input Validation - Only Integers? - java

I'm working on a project where the Java code must find the total,
average, etc. of exam scores. It reads the scores from an external
file.
I've been trying for hours to find a way to edit my code so that it ignores any data in the file that is not an integer between 0-100. But I can't. Checked all the questions and answers on Stack Overflow, and I can't find any answers that would help my specific situation. Here's the while loop of my code that I'm trying to work with:
Scanner reader = new Scanner(file);
while (reader.hasNext())
{
String line = reader.nextLine();
nextScore = Integer.parseInt(line);
System.out.println(nextScore);
sum = nextScore + sum;
totalNumberOfScores++;
if (nextScore > maxScore)
{
maxScore = nextScore;
}
else if (nextScore < minScore)
{
minScore = nextScore;
}
if (nextScore >= A)
{
countA++;
}
else if (nextScore >= B)
{
countB++;
}
else if (nextScore >= C)
{
countC++;
}
else if (nextScore >= D)
{
countD++;
}
else
{
countF++;
}
}
reader.close();
Can anyone help ?

if(isInteger(line)){
nextScore = Integer.parse(line);
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch(NumberFormatException e) {
return false;
} catch(NullPointerException e) {
return false;
}
// only got here if we didn't return false
return true;
}
then you can do this
boolean isNumber = false;
for(int i = 0; i < line.length; i++){
try{
Integer.parseInt(String.valueOf(line.charAt(i)));
}catch(Exception e){
isNumber = false;
break;
}
}
if(isNumber){
Integer.parse(line);
}
or even
boolean isNumber = true;
try{
Integer.praseInt(line);
}catch(Exception e){
isNumber = false;
}
if(isNumber){
//everthing else
}

I would use a try-with-resources Statement to close the Scanner when through reading. Next, you need to define your min, max, total and lines count outside the loop. You could default min to the maximum possible value, and max to the minimum; then use Math.max(int,int) and Math.min(int,int) to set the max and min respectively. Then, you need to validate that you read an int and that is in the correct range before processing it as input. Something like,
try (Scanner reader = new Scanner(file)) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
int total = 0;
int lines = 0;
int countA = 0, countB = 0, countC = 0, countD = 0, countF = 0;
while (reader.hasNextLine()) {
String line = reader.nextLine();
try {
int nextScore = Integer.parseInt(line);
if (nextScore >= 0 && nextScore <= 100) {
min = Math.min(nextScore, min);
max = Math.max(nextScore, max);
total += nextScore;
lines++;
if (nextScore >= A) {
countA++;
} else if (nextScore >= B) {
countB++;
} else if (nextScore >= C) {
countC++;
} else if (nextScore >= D) {
countD++;
} else {
countF++;
}
}
} catch (NumberFormatException nfe) {
}
}
System.out.printf("Min: %d, Max: %d, Total: %d, Lines: %d, Average: %.2f%n",
min, max, total, lines, total / (float) lines);
System.out.printf("%d As, %d Bs, %d Cs, %d Ds, %d Fs", countA, countB,
countC, countD, countF);
} catch (IOException e) {
e.printStackTrace();
}

Related

How to find matching audio sample within a wave file sliding window

I have an algorithm that should be able to tell a repeat in an audio. I used sliding window to implement this. The issue with this algorithm that I'm having is it works perfectly when I create a Sin_tone, but when I take a wav file and I concatenate it with itself, it will never recognize that second half. for some reason, the second half has different sample numbers than the first half.
The main question is why would concatenating a wave file of the exact same audio cuz the samples to be different at those two points (I concatenated using Adobe audition and Adobe audacity
I can get a double[] array of all the samples, but should I run a DFT on the sections of the sample and then compare them?
This takes a beat that I concatenated so I knew for sure there was an exact repeat, and it still fails, but when I use a sin tone I created then it can find the loop successfully
package Waves;
public class FindAudioAttempt2 {
public static void main(String[] args)
{
WavFile wavFile;
double[] buffer;
try
{
// Open the wav file specified as the first argument
wavFile = WavFile.openWavFile(new File("beat_on_repeat2.wav"));
// Display information about the wav file
wavFile.display();
// Find a matching loop that is 0.2 seconds
int numFramesinCut = (int) (0.2* wavFile.getSampleRate());
System.out.println("num frames in cut: " +numFramesinCut);
long numFrames = wavFile.getNumFrames();
// Create a buffer of half the frames
int framesRead;
// buffer size is 2 * the number of frames since it is stereo
buffer = new double[(int) (numFrames)*2];
framesRead = wavFile.readFrames(buffer, (int)numFrames);
System.out.println("Buffer Length: " +buffer.length);
HashMap<Double, ArrayList<Integer>> savedPoints = new HashMap<>();
// Read frames into buffer
int endPointer = buffer.length-1;
int beginPointer = 0;
boolean dictComplete = false;
boolean found = false;
for(int i=buffer.length-1-numFramesinCut; i>buffer.length/2; i--){
if(dictComplete){
if(!savedPoints.containsKey(buffer[i])){
continue;
}
ArrayList<Integer> pointers = savedPoints.get(buffer[i]);
for (int p:pointers) {
found = checkLoops(buffer,i,p, numFramesinCut);
if(found){
beginPointer = p;
endPointer = i;
break;
}
}
if(found){
break;
}
} else {
for (int j = 0; j < buffer.length/2; j++) {
handleDict(savedPoints,buffer[j],j);
if(buffer[i] == buffer[i]){
found = checkLoops(savedPoints,buffer, i,j,numFramesinCut);
}
if(found){
beginPointer = j;
endPointer = i;
break;
}
if(j == buffer.length/2 -1){
dictComplete = true;
}
}
}
if(found){
break;
}
}
int sampleRate = (int)wavFile.getSampleRate();
WavFile wavFile2 = WavFile.newWavFile(new File("beatLooping.wav"), 2, numFrames/2, 16, sampleRate);
double[] bufferFinal = new double[endPointer-beginPointer];
System.out.println("Final Buffer Length: " +bufferFinal.length);
System.arraycopy(buffer, buffer.length/2 -1, bufferFinal, 0, buffer.length/2);
wavFile2.writeFrames(bufferFinal, (endPointer-beginPointer)/2);
// Close the wavFile
wavFile.close();
wavFile2.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
static private boolean checkLoops(HashMap<Double, ArrayList<Integer>> savedPoints, double[] buffer, int i, int j, int framesinCut){
int frameCount =1;
while(frameCount < framesinCut && i<buffer.length && j<buffer.length/2){
handleDict(savedPoints, buffer[j], j);
if(buffer[i] != buffer[j]){
return false;
}
i = i+2;
j = j+2;
frameCount++;
}
if(frameCount == framesinCut){
return true;
} else {
return false;
}
}
static private boolean checkLoops( double[] buffer, int i, int j, int framesinCut){
int frameCount =1;
while(frameCount < framesinCut && i<buffer.length && j<buffer.length/2){
if(buffer[i] != buffer[j]){
return false;
}
i = i+1;
j = j+1;
frameCount++;
}
if(frameCount == framesinCut){
return true;
} else {
return false;
}
}
static public void handleDict(HashMap<Double, ArrayList<Integer>> dict, Double key, int pointer){
if(dict.containsKey(key)){
dict.get(key).add(pointer);
} else {
dict.put(key,new ArrayList<Integer>(){{add(pointer);}});
}
}
}

the error when i change a number in decimal base to another base

I am writing a java code to Change a number from decimal base to another base.
But I don't know why the program runs wrong. I think the error comes from function Prin_as. Can anyone tell me why ?
Below is my code,
import java.util.Scanner;
public class bai2chuyendoi {
public static void main(String[] args) {
int a, b;
System.out.println("Number in decimal base:");
a = Enter();
System.out.println("Other base :");
b = Enter();
Change_base (a, b);
}
public static int Enter() {
int n = 0;
boolean check = false;
while (!check) {
Scanner sc = new Scanner(System.in);
try {
n = sc.nextInt();
check = true;
} catch (Exception e) {
System.out.println("Enter again:");
sc.nextLine();
}
}
return n;
}
public static void Change_base(int a, int b) {
int i = 0;
int[] c = new int[8];
while (a != 0) {
c[i] = a % b;
a = a / b;
i++;
}
while (i >= 0) {
--i;
if (c[i] < 10) {
System.out.print(c[i]);
} else {
System.out.print((char) (c[i] + 55));
}
}
}
}
The error was in Change_base method in second while loop.
You need decrement 'i' and check that i >= 0, but you didn't.
while (--i >= 0) {
if (c[i] < 10) {
System.out.print(c[i]);
} else {
System.out.print((char) (c[i] + 55));
}
}

Uniformly distributed random prime generator

public class RandomPrime
{
public static void main(String[] args)
{
int squareNumber = readInput();
BigInteger randomPrimes[] = generateRandomPrime(squareNumber);
}
public static BigInteger[] generateRandomPrime(int num)
{
int numberOfPrimes = (int) Math.sqrt(num);
int start, end, step;
start = 1;
step = num / numberOfPrimes;
end = start + (step - 1);
/*int randomPrimes[] = new int[numberOfPrimes];*/
BigInteger randomPrimes[] = new BigInteger[numberOfPrimes];
Random rand = new Random();
int tempPrime;
for (int i = 0; i < numberOfPrimes; i++) {
while (true) {
tempPrime = rand.nextInt(end - start) + start;
if (isPrime(tempPrime)) {
randomPrimes[i] = new BigInteger(tempPrime + "");
System.out.println("Random prime is "+tempPrime);
break;
}
}
start = end + 1;
end = end + (step - 1);
System.out.println("OUTER WHILE");
}
return randomPrimes;
}
public static boolean isPrime(int num)
{
for (int i = 2; i < num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
public static int readInput()
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int num = 0, sqrt;
while (true) {
System.out.println("Enter a square number");
try {
num = Integer.parseInt(br.readLine());
sqrt = (int) Math.sqrt(num);
if (num == (sqrt * sqrt)) {
System.out.println("Entered valid square num is "+num);
break;
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Entered a non square number.So");
}
return num;
}
}
This is the code I wrote. I want to generate uniformly distributed random prime. This code works.
My problem: I am not sure whether my code generated uniformly distributed primes. Is it correct? If not, how do I solve it?

Is it possible to merge these two do loops

I've tried merging the two loops into one do loop, but every time I enter an invalid value it doesn't prompt me the error message and ask to enter the value again. Instead it just moves on to the next prompt statement.
do {
try {
dependents = Integer.parseInt(JOptionPane.showInputDialog("number of dependents:"));
}
catch (NumberFormatException e) {
dependents = MIN_DEPENDENTS - 1;
}
if (dependents < MIN_DEPENDENTS || dependents > MAX_DEPENDENTS) {
JOptionPane.showMessageDialog(null, "Number of dependents must be between 0 and 9.");
}
} while (dependents < MIN_DEPENDENTS || dependents > MAX_DEPENDENTS);
do {
try {
income = Double.parseDouble(JOptionPane.showInputDialog("amount of income:"));
}
catch (NumberFormatException e) {
income = MIN_INCOME - 1;
}
if (income < MIN_INCOME || income > MAX_INCOME) {
JOptionPane.showMessageDialog(null, "income must be between $0 and $999,999.");
}
} while (income < MIN_INCOME || income > MAX_INCOME);
No, but you could create some sort of GetInput function and pass in min, max, promptText, and errorText. This would save you duplicating the code.
dependents = getInput(MIN_DEPENDENTS, MAX_DEPENDENTS,"number of dependents:","Number of dependents must be between 0 and 9.")
income = getInput(MIN_INCOME,MAX_INCOME,"amount of income:","income must be between $0 and $999,999.")
private double getInput(double min, double max, String promptText, String errorText) {
double result = 0.0;
do {
try {
result = Double.parseDouble(JOptionPane.showInputDialog(promptText));
}
catch (NumberFormatException e) {
result = min - 1;
}
if (result < min || result > max) {
JOptionPane.showMessageDialog(null, errorText);
}
} while (result < min || result > max);
return result;
}
Dan, you need to put below lined in your catch block to show error message and prompt again for input.
catch (NumberFormatException e) {
dependents = MIN_DEPENDENTS - 1;
JOptionPane.showMessageDialog(null, "Number of dependents must be between 0 and 9.");
dependents = Integer.parseInt(JOptionPane.showInputDialog("number of dependents:"));
}
Another option could to main list of input in array and then use it in while loop
Object[][] input = {
{"number of dependents", MIN_DEPENDENTS, MAX_DEPENDENTS},
{"amount of income", MIN_INCOME, MAX_INCOME},
};
int index = 0;
int value, min, max;
do {
Object[] inputDetails = input[index];
String label = inputDetails[0].toString();
min = Integer.valueOf(inputDetails[1].toString());
max = Integer.valueOf(inputDetails[2].toString());
try {
value = Integer.parseInt(JOptionPane.showInputDialog(label));
} catch (NumberFormatException e) {
value = min - 1;
}
if (value < min || value > max) {
JOptionPane.showMessageDialog(null, String.format("%s must be between %s and %s", label, min, max));
} else {
index++;
}
} while ((value < min || value > max) || index < input.length);

char array to int array conversion in java generates null pointer exception

I am trying to run the following HillCipher program but it is terminated after the line of conversion of char array to int array and after compilation of that code it shows me null pointer exception.It works fine if I replace int array with int variable,but I need int array in this code to encrypt the data:
try{
do//key
{
System.out.println("Enter Key of length 4 character : ");
sKey=(new BufferedReader(new InputStreamReader(System.in))).readLine();
cKey=new char[2][2];
}while(!checkKey());
}
catch(Exception e)
{}
}
boolean checkKey()
{
boolean flag=true;
if(sKey.length()!=4)
flag=false;
int k=0;
int temp;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
cKey[i][j]=sKey.charAt(k);
k++;
iKey[i][j]=(int)cKey[i][j]; //program is terminated after this line
iKey[i][j]-=97;
if(cKey[i][j]<97 || cKey[i][j]>122)
{
flag=false;
break;
}
}
if(flag==false)
{
System.out.println("flag: "+flag);
break;
}
}
int d;
if((d=iKey[0][0]*iKey[1][1]-iKey[1][0]*iKey[0][1])==0)
flag=false;
if(flag==false)
System.out.println("Invalid Key!! ");
else
keygen(d);
return flag;
}
void keygen(int d)
{
if (d<0)
d*=-1;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
if(i==0 && j==0)
iDKey[i][j]=iKey[1][1]/d;
else if(i==1 && j==1)
iDKey[i][j]=iKey[0][0]/d;
else
iDKey[i][j]=-iKey[i][j]/d;
}
}
}
String encrypt()
{
int l;
if(sPlainTxt.length()%2==0)
l=sPlainTxt.length();
else
l=sPlainTxt.length()+1;
int temp1,temp2,ans;
for(int i=0;i<l;i+=2)
{
temp1=(int)cPlainTxt[i]-97;
temp2=(int)cPlainTxt[i+1]-97;
ans=iKey[0][0]*temp1+iKey[0][1]*temp2;
System.out.println(ans);
ans%=26;
ans+=65;
cCipherTxt[i]=(char)ans;
cCipherTxt[i+1]=(char)((iKey[1][0]*temp1+iKey[1][1]*temp2)%26+65);
}
sCipherTxt=new String(cCipherTxt);
return sCipherTxt;
}
}
You never assign a value to iKey, so it has its initial default value of null - it's as simple as that. You need to create a new array, e.g.
// Given that you've hard-coded the length of cKey as well...
iKey = new int[2][2];
I'd also strongly urge you not to catch exceptions like this:
catch(Exception e)
{}

Categories