Encoding string using cipher table - java

I need to encode a given message using cipherTable and a given key. I'm pretty sure there's something wrong with the encode method but i'm not sure what. This code:
import java.util.ArrayList;
public class Prog3Cipher {
// INSTANCE VARIABLES
static char[] keyList; // VARIABLE DESCRIPTION COMMENT
static char[][] cipherTable; // VARIABLE DESCRIPTION COMMENT
String alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static String encode(String message) {
String result = "";
ArrayList<Character> w = new ArrayList<>();
String[] m = new String[]{message};
for (int p = 0; p < m.length; p++) {
int row = Character.getNumericValue(keyList[p]);
int column = Character.getNumericValue(Integer.parseInt(m[p]));
char q = cipherTable[row][column];
w.add(q);
}
result = String.join(" ", (CharSequence) w);
return result;
}
public Prog3Cipher(char code, String key) {
keyList = key.toCharArray();
int offset = code - 'A';
cipherTable = new char[26][26];
for (int x = 0; x < cipherTable.length; x++) {
for (int y = 0; y < cipherTable[0].length; y++) {
cipherTable[x][y] =
alpha.charAt((x + y + offset) % alpha.length());
}
}
}
public static void main(String[] args) {
// Testing only works if using VM argument -ea
Prog3Cipher self = new Prog3Cipher('H', "BABBAGE");
assert "PHXXF MQYBPKNJ".equals(self.encode("Happy Birthday"));
}
}
Output:
Exception in thread "main" java.lang.NumberFormatException: For input string: "Happy Birthday"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at Prog3Cipher.encode(Prog3Cipher.java:24)
at Prog3Cipher.main(Prog3Cipher.java:68)
Process finished with exit code 1
the encode method takes a cipher table, cipherTable, and finds the intersection point of the row and column, which are found with keyList and m, and the intersection is set to q and then added to an Arraylist w. Result is set to a String and returned.
i'm not sure what's wrong as there are no errors with the code so if anyone could look over it and give some guidance it would be much appreciated.

This line is the likely culprit.
int column = Character.getNumericValue(Integer.parseInt(m[p]));
The NumberFormatException is from the Integer.parseInt(). If you inspect m[p] you'll find that it is an array of length 1 with an where m[0]="Happy Birthday". The String "Happy Birthday" can't be parsed as a number, thus the exception.
If you want to break a String into its individual characters, you could use String.toCharArray() like this: char[] m = message.toCharArray();
There are some other issues in your code:
In the main() method an instance of Prog3Cipher is being created, but encode() is static, so the call to self.encode() likely isn't working as you might expect. Removing static from the method declaration of encode() should fix that problem.
Character.getNumericValue() returns the unicode value of the provided character. That method returns 10 for 'A' through 35 for 'Z', so the values don't match the bounds of your cipherTable array.
As written, the for loop in encode() will walk past the end of the keyList[] array. This is because keyList[] only has 7 characters compared to the 14 chars in message.
The encode() method doesn't have any special handling for spaces in message, so they'll most likely also cause an exception.

Related

i am trying to implement a caesar cipher in java but have no ideas since i have to need a char[] key as parameters and not an int shift

public static void getkey() {
char[] resultat = new char[256];
for (char r = 0; r < 256; r++) {
resultat[r] = r;
System.out.print(r);
}
}
Hello , when i run this programm it shows me all the 256 characters in java.like thisjava console
But my goal is to use a parameter of type String like this.
public static void getkey(String key)
this parameter are the letter of the alphabet. when i run the programm , it should replace the position of the caracters that are already stored as showed in the imagelink. And the result would be , if i add "ZYXWVUTSRQPONMLKJIHGFEDCBA" as a parameter , A would become Z , B would become Y , C = X , until Z becomes A.
And i will have to create a method encrypt , As i am trying to create a caesar cipher , and i will have to call this method getkey(String key) in other to encode my text, i am not using an int shift , the signature of the method looks like this:
public static void encrypt(String text , char[] key)
i am looking every where and i don't find any answer , please does somebody have an idea , i am a beginner at java programming . Thank you.
You want to do something like this:
private static char[] key = ZYXWVUTSRQPONMLKJIHGFEDCBA".toCharArray(); //for reference
public String encrypt(char[] key, String plaintext){
char[] encryptedText = new char[plaintext.size];
for(int i = 0; i < plaintext.size(); i++){
int charIndex = plaintext.charAt[i] - 'A'; //normalizes to A=0, Z=24
encryptedText[i] = key[charIndex % key.length];
}
return new String(encryptedText);
}
It seems like you will have edge cases with ' ' characters and others so you may need to add some logic to ignore characters not within the range you are encrypting.

Making a loop that returns the characters before it hits a colon character

Whenever I run my code it returns this error message:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 5
at java.lang.String.charAt(Unknown Source)
at codes.Main.main(Main.java:10)
Here is my code:
package codes;
public class Main {
public static void main(String[] args) {
String cord1 = "Name: x=23 y=60 z= 600";
String cord2 = "Name: x=200 y=20 z= 300";
int c1 = cord1.length();
String mychar = String.valueOf("cord1".charAt(0));
for (int a = 0; a < c1; a++){
mychar = String.valueOf("cord1".charAt(a));
if (mychar == ":"){
break;
}else{
cord1.substring(a);
}
}
}
}
There are multiple things wrong in your code..
mychar == ":" should be mychar.equals(":") instead. Since Strings are immutable, we need to use the .equals to compare them instead of == (<- this checks if the references are equal instead of the String-values).
"cord1".charAt should be your variable cord1.charAt.. By using "cord1" you basically create a new String with the value cord1.
cord1.substring(a); doesn't change the cord1 value, but returns a new String. So you'll have to save this String result, or print it, and then stop the loop with a break.
Using cord1 = cord1.substring(a) would shorten the String itself. Since you still loop in the range [0, c1) where c1 was the original String, we would still get a StringIndexOutOfBoundsException. Instead, you don't need the else-case and need both the cord1 = cord1.substring(a) and break inside the if-case. (Also, I assume you want to remove the : itself as well, so you'll have to use .substring(a+1) instead.)
Also, why use String.valueOf( char ) instead of just using the char themselves? Not really a requirement, but the String.valueOf is kinda redundant here, and makes the code less readable.
Putting it all together:
public class Main {
public static void main(String[] args) {
String cord1 = "Name: x=23 y=60 z= 600";
System.out.println("cord1 before:\t" + cord1);
int c1 = cord1.length();
char mychar = cord1.charAt(0);
for (int a = 0; a < c1; a++){
mychar = cord1.charAt(a);
if (mychar == ':'){
cord1 = cord1.substring(a+1);
break;
}
}
System.out.println("cord1 after:\t" + cord1);
}
}
Which will result in cord1 having the value " x=23 y=60 z= 600" (note the leading space) in the end.
Try it online.
Here is a much simpler alternative with the same result:
String cord1 = "Name: x=23 y=60 z= 600";
String cord1ExcludingName = cord1.replaceFirst("^.*:","");
Try it online.
^ : Only look at the start of the String for:
.* : Zero or more of any character,
: : followed by a `:`
Which will be replaced with "" (an empty String), so they're basically removed.
Use equals instead of "=="
Like this
if (mychar.equals(":")){
break;
You need to use equals method because you are working with a string. Whenever you work with string u must compare them with the method equals.
If you used
char myChar = .....
Your code would work. You can compare chars with "=="
String.valueOf("cord1".charAt(0)) means you are looking into the 0th character of string "cord1" which has a highest index of 4, that is why it is giving out of bound exception at 5.
What you have to do is String.valueof(cord1.charAt(0)). This will consider the string in the variable cord1.

Java method not doing what expected. Trying to understand why

Trying to write a java method that will take a string, loop through it and where it finds a vowel (A,E,I,O,U,Y) replace it with the vowel plus "OB".
I've written the below but it isn't working as I'd expect and doesn't seem to be matching the current character in my string with the vowels from my list. (The program compiles and runs so it isn't an issue with not importing necessary bits at the beginning. The input string will always be uppercase and only contain alphas.) I'm struggling to figure out where I'm going wrong.
Can anyone help?
public static String obifyText(String text) {
String[] myList = new String[] {"A","E","I","O","U","Y"};
StringBuilder tempText = new StringBuilder(text);
String obify = "OB";
for (int i = 0; i < text.length() -1 ; i ++ ) {
if ( Arrays.asList(myList).contains(tempText.charAt(i)) ) {
System.out.println(tempText.charAt(i)+" found.");
tempText = tempText.insert((i+1),obify);
}
}
text = tempText.toString();
return text;
}
Don't play with indexes.
Managing with indexes could be difficult when you are dealing with changing the string.
Loop on the chars itself as follows:
public static void main(String[] args){
String[] myList = new String[] {"A","E","I","O","U","Y"};
String text = "AEE";
StringBuilder tempText = new StringBuilder("");
String obify = "OB";
for (char c : text.toCharArray()){
tempText = tempText.append(c);
if ( Arrays.asList(myList).contains(c+"") ) {
System.out.println(c+" found.");
tempText = tempText.append(obify);
}
}
text = tempText.toString();
System.out.println(text);
}
OUTPUT:
A found.
E found.
E found.
AOBEOBEOB
charAt returns a char, but myList stores String elements. An array of Strings can never contain values of char. Your if statement never runs.
You can convert the char value to a string:
Arrays.asList(myList).contains(Character.toString(tempText.charAt(i)))
There's just one more problem with your code.
When the code inserts OB after a vowel, there is a side effect: a new vowel O is created. Your code then tries to insert OB after the new O. This is undesired, right?
To make it not do this, you can loop from the end of the string to the start:
for (int i = text.length() - 1; i >= 0 ; i--) {
If this is not a homework question to practice using StringBuilder or for loops, here's a one liner solution using regex:
return text.replaceAll("([AEIOUY])", "$1OB");
You compare two different types in Arrays.asList(myList).contains(tempText.charAt(i)), Arrays.asList(myList) is a List<String> and tempText.charAt is a char. So the contains check will never result in true.
One possible fix, change myList to Character[]
Character[] myList = new Character[] {'A','E','I','O','U','Y'};
There is another problem with the actual insertion, see Pankaj Singhal answer for a solution to that.

stripping input causing null pointer

I am trying to create a method that strips a string of whitespace and punctuation to check if it is a palindrome. When filling a char array of stripped chars I get a null pointer exception. To me it makes perfect sense, i am filling the array of the same length with only letters or numbers. if there are leftover chars then i fill them with a space (later to be stripped with trim). Without char[] strippedInput = null; i get variable may not have been initialized. With it I get null pointer exception. I drew a simple diagram of what would happen to the stripped array when I input "if, then." and everything seemed to match up. There seemed to be a value for each array index of strippedInput yet netbeans is telling me that something is null.
static boolean palindromeCheckC(String inputString)
{
boolean isPalin2 = false;
char[] inChars = inputString.toCharArray();
char[] strippedInput = null;
int offsetIndex = 0;
for (int i = 0; i < inputString.length(); i++)
{
if ((Character.isLetter(inChars[i]) || Character.isDigit(inChars[i]
)) == true)
{
strippedInput[i-offsetIndex] = inChars[i];
}
else offsetIndex++;
}
for (int i = inputString.length()- offsetIndex; i < inputString.length(); i++)
{
strippedInput[i] = ' ';
}
System.out.println(strippedInput);
//to string
//reverse
//compare to if 0 => isPalin2 = true
return isPalin2;
}
The problem is that instead of initializing your array, you set it to null. Try changing:
char[] strippedInput = null;
to
char[] strippedInput = new char[inputString.length()];
I understand that the strippedInput will likely contain fewer characters than are in the inputString. However, as far as I know, it is possible that you will need the same amount of characters in the stripped array. If you do not need all of them, just write a null character at the end the data and it will work/print correctly. Regardless, this will solve your NullPointerException.

Using Sort Arrays and finding the growth rate in states

I am having trouble figuring out why I am getting a mismatch exception, everything was working fine until I opened it on my computer. I have to take the census file and read it in, which I did, I found the growth rate, but the only problem seems to be this mismatch exception and I dont understand why there is a mismatch error, please help.
Here is the file example:
Alabama,4447100
Alaska,626932
Arizona,5130632
Arkansas,2673400
Here is the program:
public static void main(String[] args) throws IOException {
File f = new File("census2010.txt");
File ff = new File("census2000.txt");
if(!f.exists()) {
System.out.println( "f does not exist ");
}
if(!ff.exists()) {
System.out.println( "ff does not exist ");
}
Scanner infile2010 = new Scanner(f);
Scanner infile2000 = new Scanner(ff);
infile2010.useDelimiter("[\t|,|\n|\r]+");
infile2000.useDelimiter("[\t|,|\n|\r]+");
final int MAX = 60;
int[] pop10 = new int[MAX];
int[] pop00 = new int[MAX];
String[] statearray10 = new String[MAX];
String[] statearray00 = new String[MAX];
double [] growtharray = new double[MAX];
int fillsize;
fillsize = fillArrayPop (pop10, statearray10, MAX, infile2010, prw);
fillsize = fillArrayPop2 (pop00, statearray00, MAX, infile2000, prw); // the mismatch exception occurs here
growthRate(growtharray, pop10, pop00, fillsize);
sortarray(growtharray, statearray10, fillsize);
printarray (growtharray, statearray10, fillsize, prw);
}
public static int fillArrayPop (int[] num, String[] statearray10, int mAX, Scanner infile2010, PrintWriter prw) throws FileNotFoundException{
int retcnt = 0;
int pop;
String astate;
while(infile2010.hasNext()){
astate = infile2010.next();
pop = infile2010.nextInt();
statearray10[retcnt] = astate;
num[retcnt] = pop;
retcnt++;
}
return (retcnt);
}
public static int fillArrayPop2 (int[] number, String[] statearray00, int mAX, Scanner infile2000, PrintWriter prw) throws FileNotFoundException{
int retcounts = 0;
int pop;
String state;
while(infile2000.hasNext()){
state = infile2000.next();
pop = infile2000.nextInt(); // the mismatch exception occurs here
statearray00[retcounts] = state;
number[retcounts] = pop;
retcounts++;
}
return (retcounts);
}
public static void printarray (double[] growth, String[] state, int fillsize, PrintWriter prw){
DecimalFormat form = new DecimalFormat("0.000");
for (int counts = 0; counts < fillsize ; counts++){
System.out.println("For the position ["+counts+"] the growth rate for " + state[counts] + " is " +form.format(growth[counts]));
prw.println("For the position ["+counts+"] the growth rate for " + state[counts] + " is " + form.format(growth[counts]));
}
prw.close();
return;
}
public static void growthRate (double[] percent, int[] pop10, int[] pop00, int fillsize){
double growthrate = 0.0;
for(int count = 0; count < fillsize; count ++){
percent[count] = (double)(pop10[count]-pop00[count])/ pop00[count];
}
}
public static void sortarray(double[] percent, String[] statearray10, int fillsize) {
for (int fill = 0; fill < fillsize - 1; fill = fill + 1) {
for (int compare = fill + 1; compare < fillsize; compare++) {
if (percent[compare] < percent[fill]) {
double poptemp = percent[fill];
percent[fill] = percent[compare];
percent[compare] = poptemp;
String statetemp = statearray10[fill];
statearray10[fill] = statearray10[compare];
statearray10[compare] = statetemp;
}
}
}
}
Why am I getting this error?
As #Pescis' Answer says, the exception is saying that the token you are trying to get using nextInt is not a valid representation of an int. Either it contains unexpected characters, or it is out of range.
If you showed us the exception's message String, and the complete stacktrace, it would be easier to diagnose this. Without that, we have to resort to guessing.
Guess #1: there is something bad in the actual input data file that you are reading at that point.
Guess #2: the way you are setting the delimiters regex is wrong. Your regex seems to be mixing a character class and alternation in a way that is almost certainly incorrect. It should be this:
useDelimiter("[\\t,\\n\\r]+");
(It is not clear that fixing this will fix the problem ... but your regex is wrong none-the-less.)
Comments:
You have two methods fillArrayPop and fillArrayPop2 that seem to be doing the same thing. As far as I can tell the only differences are different variable names and other non-consequential stuff.
Your approach to "parsing" is ignoring the fact that the files are actually line structured. I think you should (conceptually) read lines and then split the lines into fields. What you are currently doing is treating them as a sequence of alternating fields.
Ideally, your "parsing" should be more robust. It should at least attempt to diagnose a mismatch between the expected file format and what you actually read from the file. (If I was writing this, I would at a minimum try to output the line or line number at which the "badness" was detected.)
From the javadoc of Scanner.nextInt():
InputMismatchException - if the next token does not match the Integer
regular expression, or is out of range
This means, either the next token you are trying to read when it throws the error can not be parsed as an Integer. This can happen for instance if there are non-numeric letters in the token or if the integer is out of range, i.e smaller than -2,147,483,648 or bigger than 2,147,483,647.
If no token in your file is out of range, it's most likely because the file's layout is not how you are programming it to be.
If you take out your prw in your print array your program should run without error. DELETE prw.println("For the position ["+counts+"] the growth rate for " + state[counts] + " is " + form.format(growth[counts])); and DELETE prw.close() and it should run.
If the file is formatted exactly as you have described above, then the .next() method call immediately above the error is actually pulling the whole line (i.e. the variable "state" would contain "Alabama,4447100").
Since there is no whitespace/delimiter between the state name and population, .next() reads the whole line, and the next call to .nextInt() attempts to read the next line (a string), generating an error.
I would recommend reading each line individually, and then splitting up the two pieces of data by the comma that separates them. Also, why do you pass a method a PrintWriter object, if the object isn't used in the method?

Categories

Resources