Switch case increment only adding once to array - java

I have to get a text input from the user and then I have to replace every vowel a,e,i,o,u for 1,2,3,4,5 and show the amount of replacements for every vowel and then also the changed text.
The problem is the text at the end looks nicely replaced but the amount of replacements show up as 1.
(I tried doing it below counting the 1,2,3,4 and 5s in "myText" and it works perfect but it also counts if the user inputs a number so that is a problem)
Heres the first part:
public static void replaceAndCount(String myText, int[] vowels) {
for (int i = 0; i < myText.length(); i++) {
switch (myText.charAt(i)) {
case 'a':
vowels[0]++;
myText = myText.replace('a', '1');
case 'e':
vowels[1]++;
myText = myText.replace('e', '2');
case 'i':
vowels[2]++;
myText = myText.replace('i', '3');
case 'o':
vowels[3]++;
myText = myText.replace('o', '4');
case 'u':
vowels[4]++;
myText = myText.replace('u', '5');
}
}
}

You have 2 issues in your code.
You have to use break in each case, otherwise all the cases below the matching case will be executed as well. Example,
case 'a':
vowels[0]++;
myText = myText.replace('a', '1');
break;
case 'e':
vowels[1]++;
myText = myText.replace('e', '2');
break;
String replace(old,new) will replace all occurrences of the old character with new. That is why, amount of replacements show up as 1.
Refer this for string replacement at specific index

Hope this below code works for you
Code :
public class ReplaceVowels {
public static void main(String[] args) {
String myText = "aaaeiou";
int[] vowels = new int[5];
replaceAndCount(myText.toLowerCase(), vowels);
}
private static void replaceAndCount(String text, int[] vowels) {
StringBuilder myText = new StringBuilder(text);
for (int i = 0; i < myText.length(); i++) {
switch (myText.charAt(i)) {
case 'a':
vowels[0]++;
myText.setCharAt(i, '1');
break;
case 'e':
vowels[1]++;
myText.setCharAt(i, '2');
break;
case 'i':
vowels[2]++;
myText.setCharAt(i, '3');
break;
case 'o':
vowels[3]++;
myText.setCharAt(i, '4');
break;
case 'u':
vowels[4]++;
myText.setCharAt(i, '5');
}
}
for (int vowel : vowels) {
System.out.println(vowel);
}
System.out.println(myText);
}
Results
You can refer this for replacing single character

Related

Calculate Points from Letters in a Switch Case

I am trying to create a scrabble-like program that calculates the points of letters contained in a word. These word are contained in a .txt file. I can get it to read from the file, but unsure how to get it to calculate the value of each word. I have attached what I have done so far, and am wondering if a switch case is the best way to go, and if so, how do I assign a value to a letter with a switch case. Any help is appreciated.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package pointsproblem;
/**
*
*/
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class PointsProblem {
/**
* #param args the command line arguments
* #throws java.io.FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
// TODO code application logic here
//create new object//
PointsProblem task1 = new PointsProblem();
File file = new File("dictionary.txt");
// read the file//
Scanner input = new Scanner(file);
//check if file can be found//
if (!file.isFile()) {
System.err.println("Cannot open file: " + input);
System.exit(0);
}
else {
System.out.println("Successfully opened file: " + input + ".");
}
//read all the lines in the file//
{
while (input.hasNext()) {
String word = input.nextLine();
System.out.println(word);
System.out.println("'" + input + "' is worth " + point + " points");
int point = "";
switch(point) {
case 'a': = "1":
case 'e': = "1";
case 'i': = "1";
case 'l': = "1";
case 'n': = "1";
case 'o': = "1";
case 'r': = "1";
case 's': = "1";
case 't': = "1";
case 'u': = "1";
case 'g': = "2";
case 'g': = "2";
case 'b': = "3";
case 'm': = "3";
case 'c': = "3";
case 'p': = "3";
case 'f': = "4";
case 'h': = "4";
case 'v': = "4";
case 'w': = "4";
case 'y': = "4";
case 'k': = "5";
case 'j': = "8";
case 'x': = "8";
case 'q': = "10";
case 'z': = "10";
return score = point + "";
}//end switch
}//end point calculation loop
public int getScore() {
return score;
}
//public boolean containsLetter(Character letter) {
//return points.contains(letter);//
}
I have tried assigning an int of X to the value as well. I would like it to read the word contained in the file and give a total score.
Looks like a Map<Character, Integer> would fit:
public class PointsProblem {
final Map<Character, Integer> pointsMap = Map.of(
'a', 1,
'e', 1,
//.......
'z', 10
);
Then, in your function, simply use the map to find the corresponding point for each character:
int wordPoints = 0;
for(char c : word.toCharArray())
wordPoints += pointsMap.get(c);
Use a map to store the values:
Map<Character, Integer> charValues = new HashMap();
charValues.put('a', 2);
charValues.put('b', 1);
You can use the chars() and collect as sum
int total = word.chars()
.mapToObj(c -> charValues.get((char)c))
.mapToInt(i -> (int)i)
.sum();
But according to your use case you can count the chars first and then multiply
Map<Character, Integer> counter = new HashMap<>();
while (input.hasNext()) {
String word = input.next();
word.chars().forEach(c -> counter.compute(c, (k, v) -> v == null ? 1 : v + 1));
}
counter.entrySet()
.stream()
.mapToInt(e -> charValues.get(e.getKey())*e.getValue())
.sum();
if you are using switch your code will look like:
int total = 0;
switch (c){
case 'a' : total += 1; break;
case 'b' : total += 2; break;
}
I'm not sure that the code you've shown us will compile. There are a few things you need to change;
1) You're setting a String to an int. You'll want to change that to
int point = 0
2) You aren't setting anything in the switch statement
Change case 'a': = "1": to case 'a': point = 1;
3) You will never set a unique value in the switch statement because you aren't using 'break'
Checkout this page for a good tutorial: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
Basically without any break statements, your code will go through the of the statements and point will just be assigned to your last case
You want to have something along the lines of
switch(char) {
case 'a': point = 1;
break;
case 'e': point = 1;
break;
// etc.
default: point = 1; // maybe throw an error or add some logging for the default case
break;
}
return point;
I am presuming that you actually have this switch statement in it's own method and not in main as you've shown us above, otherwise the return statement won't help you.
You can also shorten this so that each case simply returns a value (again, if this is in it's own method), i.e.
switch(char) {
case 'a': return 1;
case 'b': return 1;
// etc.
}
edit:
The best way to get the point value of the whole word via a switch statement is:
char[] chars = word.toCharArray();
int point=0;
for (char c: chars) {
switch(c) {
case 'a':
point += 1;
break;
// etc.
}
}
System.out.println("Total point value of word '" + word + "' was " + point);
Instead of assigning individually for each 'case' statement, you can also use the fall through feature of the switch block.
int calcScore(String str)
{
int score = 0;
for(int i=0; i<str.length(); i++)
{
switch(str.charAt(i)) {
case 'a':
case 'e':
case 'i':
case 'l':
case 'n':
case 'o':
case 'r':
case 's':
case 't':
case 'u': score += 1; break;
case 'g': score += 2; break;
case 'b':
case 'm':
case 'c':
case 'p': score += 3; break;
case 'f':
case 'h':
case 'v':
case 'w':
case 'y': score += 4; break;
case 'k': score += 5; break;
case 'j':
case 'x': score += 8; break;
case 'q':
case 'z': score += 10; break;
}
}
return score;
}
This function can be called for each word.
Thanks everyone, I ended up with the following code which gives the output I am after;
System.out.println("Points problem");
File file = new File("dictionary.txt");
// read the file//
Scanner input = new Scanner(file);
//check if file can be found//
if (!file.isFile()) {
System.err.println("Cannot open file: " + file);
System.exit(0);
} else {
System.out.println("Successfully opened file: " + file + ".");
}
//read all the lines in the file//
while (input.hasNext()) {
String word = input.nextLine();
//System.out.println(word);
int l = word.length();
int point = 0;
for (int x = 0; x < l; x++) {
char c = word.charAt(x);
switch (c) {
case 'a':
case 'e':
case 'i':
case 'l':
case 'n':
case 'o':
case 'r':
case 's':
case 't':
case 'u':
point += 1;
break;
case 'd':
case 'g':
point += 2;
break;
case 'b':
case 'c':
case 'm':
case 'p':
point += 3;
break;
case 'f':
case 'h':
case 'v':
case 'w':
case 'y':
point += 4;
break;
case 'k':
point += 5;
break;
case 'j':
case 'x':
point += 8;
break;
case 'q':
case 'z':
point += 10;
break;
}//end switch*/
}//end point calculation loop
System.out.println(word + "is worth " + point + " points." );
}

How can I convert a hexadecimal number into binary without using parse or automatic conversion

Below I have a method named 'hextoBinary' that returns a hexadecimal to binary conversion through type void.
In order for me to continue with my program I need a conversion from hex to binary method that returns and int so I can convert that binary int into a decimal with my 'hextoDecimal' method.
Can anybody help me or guide me on what approach to take, i've been stuck on this for a while now. i am limited to doing this manually instead of using parse or java automatic conversions.
import java.io.*;
import java.util.Scanner;
import java.util.ArrayList;
public class Main
{
static void hexToBinary(char hexdec[])
{
for (char c: hexdec)
{
switch (c)
{
case '0':
System.out.print("0000");
break;
case '1':
System.out.print("0001");
break;
case '2':
System.out.print("0010");
break;
case '3':
System.out.print("0011");
break;
case '4':
System.out.print("0100");
break;
case '5':
System.out.print("0101");
break;
case '6':
System.out.print("0110");
break;
case '7':
System.out.print("0111");
break;
case '8':
System.out.print("1000");
break;
case '9':
System.out.print("1001");
break;
case 'A':
System.out.print("1010");
break;
case 'B':
System.out.print("1011");
break;
case 'C':
System.out.print("1100");
break;
case 'D':
System.out.print("1101");
break;
case 'E':
System.out.print("1110");
break;
case 'F':
System.out.print("1111");
break;
default:
System.out.print("\nInvalid hexadecimal digit " + hexdec[c]);
}
}
}
public static int hextoDecimal(int n)
{
int decimal = 0, p = 0;
while(n != 0)
{
decimal += ((n % 10) * Math.pow(2,p));
n = n / 10;
p++;
}
return decimal;
}
public static void main(String[] args) throws IOException
{
Scanner sc = new Scanner(new File("RAMerrors8x4c"));
ArrayList<String> hexValues = new ArrayList<>();
while(sc.hasNext())
{
hexValues.add(sc.nextLine());
}
hexToBinary(hexValues.get(0).toCharArray());
}
}
This code is based on some that came from here but that link no longer seems to be active. Anyway, from a hex string you can get an int like this:
int hexToDecimal(String s){
int result = 0;
int digit = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= '0' && c <= '9')
digit = c - '0';
else
if (c >= 'A' && c <= 'F')
digit = 10 + c - 'A';
else
inputError(s);
result = 16 * result + digit;
}
return result
}
I modified your code a little.
a. In your code only the first hex was printed.
Change:
call hexToBinary for every hex String.
b. the binary value was discarded after printing, so it couldn't be reused.
Change:
Changed returntype of hexToBinary from void to String and returned the binary value calculated.
To be able to return a String I add the peaces(nibbles) of the hex/binary to a String in every switch(case) clause.(a Stringbuilder might be better than a String - you can additionally improve that)
in the main: additionally collect all the returned binary values in a arraylist called "binaryValues" in order to have them for the next step.
With the above (little) changes I now have all the binary values that had already been calculated.
So I am able to simply use them in a binaryToDecimal method which just sums up the binary values weighted by their position.
Why not do it again? Because youd need to convert the A-F to numbers what your hexToBinary already did. So storing the values saves you doing that step again. I have a feeling that is what your teacher had in mind when he/she combined the tasks like this.
The resulting code is:
import java.io.*;
import java.util.Scanner;
import java.util.ArrayList;
public class Main
{
static String hexToBinary(char hexdec[]) {
String hex = "";
for (char c : hexdec) {
switch (c) {
case '0':
System.out.print("0000");
hex += "0000";
break;
case '1':
System.out.print("0001");
hex += "0001";
break;
case '2':
System.out.print("0010");
hex += "0010";
break;
case '3':
System.out.print("0011");
hex += "0011";
break;
case '4':
System.out.print("0100");
hex += "0100";
break;
case '5':
System.out.print("0101");
hex += "0101";
break;
case '6':
System.out.print("0110");
hex += "0110";
break;
case '7':
System.out.print("0111");
hex += "0111";
break;
case '8':
System.out.print("1000");
hex += "1000";
break;
case '9':
System.out.print("1001");
hex += "1001";
break;
case 'A':
System.out.print("1010");
hex += "1110";
break;
case 'B':
System.out.print("1011");
hex += "1111";
break;
case 'C':
System.out.print("1100");
hex += "1100";
break;
case 'D':
System.out.print("1101");
hex += "1110";
break;
case 'E':
System.out.print("1110");
hex += "1110";
break;
case 'F':
hex += "1111";
System.out.print("1111");
break;
default:
System.out.print("\nInvalid hexadecimal digit " + hexdec[c]);
}
}
System.out.println();
return hex;
}
public static int binaryToDecimal(String binary) {
int decimal = 0;
for (int i = 1; i < binary.length()-1; i++) {
decimal += Math.pow(2, i-1) * (binary.charAt(binary.length()-i) - '0');
}
return decimal;
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new File("RAMerrors8x4c"));
ArrayList<String> hexValues = new ArrayList<>();
ArrayList<String> binaryValues = new ArrayList<>();
while (sc.hasNext()) {
hexValues.add(sc.nextLine());
}
for (String hex : hexValues) {
String binary = hexToBinary(hex.toCharArray());
binaryValues.add(binary);
System.out.println(binary);
}
for (String binary : binaryValues) {
int decimal = binaryToDecimal(binary);
System.out.println(decimal);
}
}
}
}
Besides using a Stringbuilder another idea could be to do all the printing of the binary values in the main. The hexToBinary returns the String - so you can print it in the loop - if you want.

Why is my text parser getting into an infinite loop despite the loop being explicitly broken?

I have been working on a utility to parse text files in the format used by Paradox Interactive in their grand strategy games to be used with a visual-based modding tool I am also developing. I have a mostly-implemented, crude, early version of the parser written out and it is mostly working as intended. This is my second attempt at writing a text parser (the first, which ended up working just fine, parsed a subset of XML).
I speed-wrote my parser on the 9th and have spent all weekend trying to debug it, but all my efforts have failed. I have tracked the issue down to the 3rd line of nextChar(). It was throwing an ArrayIndexOutOfBounds error with a crazy small number (in the -2 millions). After I added a bounds check the program just... continues. It reads all the information as needed, it just doesn't ever exit the parse loop.
The format is basically this:
car = {
model_year = 1966
model_name = "Chevy"
components = {
"engine", "frame", "muffler"
}
}
though I have yet to add support for nested lists like I plan, so my test string is:
car = {
model_year = 1966
model_name = "Chevy"
}
For both my understanding and anybody who would see my code, I tried to generously comment my code where I thought it might be necessary, though if any clarification is needed I would be happy to provide it.
My code:
/**
* Parses text files in the format used by Paradox Interactive in their computer games EUIV, CK2, and Stellaris.
*
* #author DJMethaneMan
* #date 12/9/2016
*/
public class Parser
{
private int pos, line, len, depth;
public String text;
private char[] script; //TODO: Initialize in the parse method
public Parser()
{
pos = 0;
line = 1;
len = 0;
depth = 0;
text = "car = {\n" +
" model_year = 1966 \n" +
" model_name = \"Chevy\"\n" +
"}\u0003";
//text = "Hello World";
//Car c = new Car();
//parse(text, c);
}
public static void main()
{
Car c = new Car();
Parser p = new Parser();
p.parse(p.text, c);
System.out.println("The model name is " + c.model_name);
System.out.println("The model year is " + c.model_year);
}
//TODO: Work
public void parse(String text, Parseable parsed)
{
char[] script = text.toCharArray();
this.script = script;
boolean next_char = false;
PARSE_LOOP:while(true)
{
char c;
if(next_char)
{
c = nextChar();
}
else
{
c = script[0];
next_char = true;
}
switch(c)
{
case 'A':
case 'a':
case 'B':
case 'b':
case 'C':
case 'c':
case 'D':
case 'd':
case 'E':
case 'e':
case 'F':
case 'f':
case 'G':
case 'g':
case 'H':
case 'h':
case 'I':
case 'i':
case 'J':
case 'j':
case 'K':
case 'k':
case 'L':
case 'l':
case 'M':
case 'm':
case 'N':
case 'n':
case 'O':
case 'o':
case 'P':
case 'p':
case 'Q':
case 'q':
case 'R':
case 'r':
case 'S':
case 's':
case 'T':
case 't':
case 'U':
case 'u':
case 'V':
case 'v':
case 'W':
case 'w':
case 'X':
case 'x':
case 'Y':
case 'y':
case 'Z':
case 'z':
case '_'://TODO: HERE
if(depth > 0) //
{
parsed.parseRead(buildWordToken(true), this);//Let the class decide how to handle this information. Best solution since I do not know how to implement automatic deserialization.
}
continueUntilChar('=', false); //A value must be assigned because it is basically a key value pair with {} or a string or number as the value
skipWhitespace();//Skip any trailing whitespace straight to the next token.
break;
case '{':
depth++;
break;
case '}':
depth--;
break;
case '\n':
line++;
break;
case ' ':
case '\t':
skipWhitespace();
break;
case '\u0003': //End of Text Character... Not sure if it will work in a file...
break PARSE_LOOP;
}
}
}
//Returns a string from the next valid token
public String parseString()
{
String retval = "";
continueUntilChar('=', false);
continueUntilChar('"', false);
retval = buildWordToken(false);
continueUntilChar('"', false); //Don't rewind because we want to skip over the quotation and not append it.
return retval;
}
//Returns a double from the next valid token
public double parseNumber()
{
double retval = 0;
continueUntilChar('=', false); //False because we don't want to include the = in any parsing...
skipWhitespace(); //In case we encounter whitespace.
try
{
retval = Double.parseDouble(buildNumberToken(false));
}
catch(Exception e)
{
System.out.println("A token at line " + line + " is not a valid number but is being passed as such.");
}
return retval;
}
/**********************************Utility Methods for Parsing****************************************/
protected void continueUntilChar(char target, boolean rewind)
{
while(true)
{
char c = nextChar();
if(c == target)
{
break;
}
}
if(rewind)
{
pos--;
}
}
protected void skipWhitespace()
{
while(true)
{
char c = nextChar();
if(!Character.isWhitespace(c))
{
break;
}
}
pos--;//Rewind because by default parse increments pos by 1 one when fetching nextChar each iteration.
}
protected String buildNumberToken(boolean rewind)
{
StringBuilder token = new StringBuilder();
String retval = "INVALID_NUMBER";
char token_start = script[pos];
System.out.println(token_start + " is a valid char for a word token."); //Print it.
token.append(token_start);
while(true)
{
char c = nextChar();
if(Character.isDigit(c) || (c == '.' && (Character.isDigit(peek(1)) || Character.isDigit(rewind(1))))) //Makes sure things like 1... and ...1234 don't get parsed as numbers.
{
token.append(c);
System.out.println(c + " is a valid char for a word token."); //Print it for debugging
}
else
{
break;
}
}
return retval;
}
protected String buildWordToken(boolean rewind)
{
StringBuilder token = new StringBuilder(); //Used to build the token
char token_start = script[pos]; //The char the parser first found would make this a valid token
token.append(token_start); //Add said char since it is part of the token
System.out.println(token_start + " is a valid char for a word token."); //Print it.
while(true)
{
char c = nextChar();
if(Character.isAlphabetic(c) || Character.isDigit(c) || c == '_')//Make sure it is a valid token for a word
{
System.out.println(c + " is a valid char for a word token."); //Print it for debugging
token.append(c); //Add it to the token since its valid
}
else
{
if(rewind)//If leaving the method will make this skip over a valid token set this to true.
{
//Rewind by 1 because the main loop in parse() will still check pos++ and we want to check the pos of the next char after the end of the token.
pos--;
break; //Leave the loop and return the token.
}
else //Otherwise
{
break; //Just leave the loop and return the token.
}
}
}
return token.toString(); //Get the string value of the token and return it.
}
//Returns the next char in the script by amount but does not increment pos.
protected char peek(int amount)
{
int lookahead = pos + amount; //pos + 1;
char retval = '\u0003'; //End of text character
if(lookahead < script.length)//Make sure lookahead is in bounds.
{
retval = script[lookahead]; //Return the char at the lookahead.
}
return retval; //Return it.
}
//Returns the previous char in the script by amount but does not decrement pos.
//Basically see peek only this is the exact opposite.
protected char rewind(int amount)
{
int lookbehind = pos - amount; //pos + 1;
char retval = '\u0003';
if(lookbehind > 0)
{
retval = script[lookbehind];
}
return retval;
}
//Returns the next character in the script.
protected char nextChar()
{
char retval = '\u0003';
pos++;
if(pos < script.length && !(pos < 0))
{
retval = script[pos]; //It says this is causing an ArrayIndexOutOfBoundsException with the following message. Shows a very large (small?) negative number.
}
return retval;
}
}
//TODO: Extend
interface Parseable
{
public void parseRead(String token, Parser p);
public void parseWrite(ParseWriter writer);
}
//TODO: Work on
class ParseWriter
{
}
class Car implements Parseable
{
public String model_name;
public int model_year;
#Override
public void parseRead(String token, Parser p)
{
if(token.equals("model_year"))
{
model_year = (int)p.parseNumber();
}
else if(token.equals("model_name"))
{
model_name = p.parseString();
}
}
#Override
public void parseWrite(ParseWriter writer)
{
//TODO: Implement along with the ParseWriter
}
}
Use of the labeled break statement break PARSE_LOOP; is generally considered bad practice. You are essentially writing a "goto" statement: whenever the break PARSE_LOOP; condition is hit, it jumps back to the beginning of the while loop (because that's where you wrote PARSE_LOOP:). This is probably the reason for your infinite loop. I also don't understand why you would restart a while loop that is already infinite (while true).
Change your code to:
public void parse(String text, Parseable parsed)
{
char[] script = text.toCharArray();
this.script = script;
boolean next_char = false;
boolean parsing = true;
while(parsing)
{
char c;
if(next_char)
{
c = nextChar();
}
else
{
c = script[0];
next_char = true;
}
switch(c)
{
case 'A':
case 'a':
case 'B':
case 'b':
case 'C':
case 'c':
case 'D':
case 'd':
case 'E':
case 'e':
case 'F':
case 'f':
case 'G':
case 'g':
case 'H':
case 'h':
case 'I':
case 'i':
case 'J':
case 'j':
case 'K':
case 'k':
case 'L':
case 'l':
case 'M':
case 'm':
case 'N':
case 'n':
case 'O':
case 'o':
case 'P':
case 'p':
case 'Q':
case 'q':
case 'R':
case 'r':
case 'S':
case 's':
case 'T':
case 't':
case 'U':
case 'u':
case 'V':
case 'v':
case 'W':
case 'w':
case 'X':
case 'x':
case 'Y':
case 'y':
case 'Z':
case 'z':
case '_'://TODO: HERE
if(depth > 0) //
{
parsed.parseRead(buildWordToken(true), this);//Let the class decide how to handle this information. Best solution since I do not know how to implement automatic deserialization.
}
continueUntilChar('=', false); //A value must be assigned because it is basically a key value pair with {} or a string or number as the value
skipWhitespace();//Skip any trailing whitespace straight to the next token.
break;
case '{':
depth++;
break;
case '}':
depth--;
break;
case '\n':
line++;
break;
case ' ':
case '\t':
skipWhitespace();
break;
case '\u0003': //End of Text Character... Not sure if it will work in a file...
parsing = false;
break;
}
}
}
Put a debug statement in to prove that it's hitting your break, I'm guessing it's not (Although it could be the break label--I haven't had reason to look into that construct since I first learned java a couple decades ago). I have a couple suggestions though...
I'd use isAlpha instead of that part of the switch. Cleaner, shorter, probably about as efficient and language-agnostic.
Instead of using the break label (Which is very uncommon), You might want to use boolean parsing=true;while(parsing)... instead. It's not really wrong to use the break label, but... Anything that causes the next guy to spend a minute or two scratching his head is a few minutes wasted.

Java Homework - File Encryption

String letters = "abcdefghijklmnopqrstuvwxyz";
String enc = "kngcadsxbvfhjtiumylzqropwe";
Hello, for my homework assignment I have to write a program that encodes or decodes a File, and then encodes or decodes the File using the mapping above. So for example, every 'a' becomes a 'k' when encoding a text, and every 'k' becomes an 'a' when decoding. Same concept if it is capital, and numbers and other characters are not encoded and remain the same.
Now the problem I am having is how to get the index of each character from the file and then correspond it to the index of the encrypt array. As you can see, I was using a switch statement but that is just going to take forever and I know there has to be something in the api that can help me with this I just can't find anything. Thanks in advance!
Here is my code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Encode {
public static void main(String[] args) throws FileNotFoundException
{
char[] alphabet = {'a', 'b', 'c', 'd', 'e', 'f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char[] decryption = {'k','n','g','c','a','d','s','x','b','v','f','h','j','t','i','u','m','y','l','z','q','r','o','p','w','e'};
char[] alphabetLower = new char [26];
char[] alphabetUpper = new char[26];
char[] decryptedPassword = new char[26];
/* for(int i=0; i<decryptedPassword.length; i++)
{
decryptedPassword[i] = '';
}*/
//add the letters of the alphabet to alphabet lower
for(int i=0; i<alphabet.length; i++)
{
alphabetLower[i] = alphabet[i];
}
//add the letters of the alphabet to alphabetdecryptedPassword
for(int i=0; i<alphabet.length; i++)
{
alphabetUpper[i] = Character.toUpperCase(alphabet[i]);
}
Scanner input = new Scanner(System.in); //scanner for input file name
String filePath = "C:/Users/omid/Desktop/";
System.out.println("Please enter the file name for which you want to decode");
String fileName = "password"; //input.nextLine();
String file = filePath + fileName + ".txt";
System.out.println("File name entered: " + file);
//import file
File fileEncrypted = new File(file);
Scanner in = new Scanner(fileEncrypted);
String document = "";
//store entire password in document
while(in.hasNextLine())
{
document = in.nextLine();
}
in.close();
System.out.println("password normal: " + document);
char[] letters = new char[document.length()];
for(int i = 0; i<document.length(); i++)
{
letters[i] = document.charAt(i);
}
for(int i=0; i<letters.length; i++)
{
System.out.println(letters[i]);
}
/*
for(int i=0; i<letters.length; i++)
{
switch(letters[i])
{
case 'a':
decryptedPassword[0] = decryption[0];
break;
case 'A':
decryptedPassword[0] = decryption[0];
break;
case 'b':
decryptedPassword[1] = decryption[1];
break;
case 'B':
decryptedPassword[1] = decryption[1];
break;
case 'c':
decryptedPassword[2] = decryption[2];
break;
case 'C':
decryptedPassword[2] = decryption[2];
break;
case 'd':
decryptedPassword[3] = decryption[3];
break;
case 'D':
decryptedPassword[3] = decryption[4];
break;
case 'e':
decryptedPassword[4] += 1;
break;
case 'E':
decryptedPassword[4] +=1;
break;
case 'f':
decryptedPassword[5] += 1;
break;
case 'F':
decryptedPassword[5] +=1;
break;
case 'g':
decryptedPassword[6] +=1;
break;
case 'G':
decryptedPassword[6] +=1;
break;
case 'h':
decryptedPassword[7] +=1;
break;
case 'H':
decryptedPassword[7] +=1;
break;
case 'i':
decryptedPassword[8] +=1;
break;
case 'I':
decryptedPassword[8] +=1;
break;
case 'j':
decryptedPassword[9] +=1;
break;
case 'J':
decryptedPassword[9] +=1;
break;
case 'k':
decryptedPassword[10] +=1;
break;
case 'K':
decryptedPassword[10] +=1;
break;
case 'l':
decryptedPassword[11] +=1;
break;
case 'L':
decryptedPassword[11] +=1;
break;
case'm':
decryptedPassword[12] +=1;
break;
case 'M':
decryptedPassword[12] +=1;
break;
case'n':
decryptedPassword[13] += 1;
break;
case 'N':
decryptedPassword[13] +=1;
break;
case'o':
decryptedPassword[14] +=1;
break;
case 'O':
decryptedPassword[14] +=1;
break;
case'p':
decryptedPassword[15] +=1;
break;
case 'P':
decryptedPassword[15] +=1;
break;
case'q':
decryptedPassword[16] +=1;
break;
case 'Q':
decryptedPassword[16] +=1;
break;
case'r':
decryptedPassword[17] +=1;
break;
case 'R':
decryptedPassword[17] +=1;
break;
case's':
decryptedPassword[18] +=1;
break;
case 'S':
decryptedPassword[18] +=1;
break;
case't':
decryptedPassword[19] +=1;
break;
case 'T':
decryptedPassword[19] +=1;
break;
case'u':
decryptedPassword[20] +=1;
break;
case 'U':
decryptedPassword[20] +=1;
break;
case'v':
decryptedPassword[21] +=1;
break;
case 'V':
decryptedPassword[21] +=1;
break;
case'w':
decryptedPassword[22] +=1;
break;
case 'W':
decryptedPassword[22] +=1;
break;
case'x':
decryptedPassword[23] +=1;
break;
case 'X':
decryptedPassword[23] +=1;
break;
case'y':
decryptedPassword[24] +=1;
break;
case 'Y':
decryptedPassword[24] +=1;
break;
case'z':
decryptedPassword[26] +=1;
break;
case 'Z':
decryptedPassword[26] +=1;
break;
}
}
*/
/*for(int i=0; i<decryptedPassword.length; i++)
{
System.out.println("password decrypted: " + decryptedPassword);
}*/
}
private static String split(String string) {
// TODO Auto-generated method stub
return null;
}
}
You can try using a hash structure. Essentially each character maps in a 1 to 1 mapping to every other character, so that fits nicely into a hashtable or hashmap structure. Rather than using a switch statement, just look up the character in the map.
HashMap<Character, Character> encryptionMap = new HashMap<Character,Character>();
for (char c : alphabet) {
for (char d: decryption) {
encryptionMap.put(c,d);
}
}
....
char nextChar = "a";
char encryptedChar = encryptionMap.get(nextChar);
You'll need an encryptionMap and a decryptionMap in the other direction (decryption > alphabet).
You should consider reading your file using BufferedReader but that's a different problem. As far as encoding a character without using switch, consider that a character is encoded internally as an integer. You can Google "Ascii Table" to see how each character is encoded. For example, 'A' is encoded as 65 and 'a' is encoded as 97. You can use this to your advantage to index into your alphabet and decryption arrays. If your character is uppercase, we subtract 65 from it to get the index of that character in the array. So 'A' becomes 0, 'B' becomes 1, etc. Similarly if the letter is lowercase, we subtract 97 from it.
For example lets assume that ch contains the letter you want to decode:
int index = -1;
//ch is between A and Z
if (ch >= 65 && ch <= 90){
index = ch - 65;
} else if (ch >= 97 &7 ch <= 122){//ch is between a and z
index = ch - 97;
}
if (index > -1){
char encodedChar = decryption[index];
}

Trying to save the first 3 words of each line from a text file, java

So I'm trying to do a private project using a text file and the robot class to read the first 3 words in each line and using the robot Object to input those words into another windows application.
The text file will look like that and it can have many more lines and every word is separated by a tab.
abc def hij klm opq rstu
cba fed jih mlk qpo utsr
Now, I want to store the first 3 words from each line and use them with the Robot Object, which works perfectly fine the way I need it to work.
I can read the whole line and separate the words, but not just the first 3 words.
I just learned how to write and how to read from a file using the Scanner Object, so I would like to keep using this method.
Help would be really appreciated.
Here's my code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
public class IO_Example_03 {
public static void main(String[] args) throws FileNotFoundException, AWTException {
run(); // Runs the main program.
Robot r2 = new Robot();
r2.keyPress(KeyEvent.VK_ENTER);
}
public static void run() throws AWTException, FileNotFoundException {
Robot r1 = new Robot();
// Put the file path, separated by \\
File f = new File("filename.txt");
Scanner in = new Scanner(f);
ArrayList<String> newArr = new ArrayList<String>();
while (in.hasNext()) {
// Inputs all the words from the file that are separated by a Tab.
String input = in.next();
// Adds all the words to the ArrayList, one by one
newArr.add(input);
}
try {
// How much time in milliseconds to pause, to give the user time to
// open the desired application. 1000 milliseconds = 1 second.
Thread.sleep(7000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
// An outer loop that go the beginning until the end of the ArrayList
for (int i = 0; i < newArr.size(); i++) {
// An inner loop that takes each word separate from the ArrayList.
for (int j = 0; j < newArr.get(i).length(); j++) {
// Saves to the singleChar variable each character from
// individual word. Also, it makes all the words as a lower case.
char singleChar = newArr.get(i).toLowerCase().charAt(j);
key(singleChar); // Invoking the key method.
try {
// How much time in milliseconds to pause between each character.
// 1000 milliseconds = 1 second.
Thread.sleep(99);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
r1.keyPress(KeyEvent.VK_ENTER); // A delimiter like Enter, Tab, or Period.
}
}
// A switch method that takes each character, and convert it into a KeyPress robot object.
public static void key(char character) throws AWTException {
Robot r = new Robot();
switch (character) {
case 'a': r.keyPress(KeyEvent.VK_A); break;
case 'b': r.keyPress(KeyEvent.VK_B); break;
case 'c': r.keyPress(KeyEvent.VK_C); break;
case 'd': r.keyPress(KeyEvent.VK_D); break;
case 'e': r.keyPress(KeyEvent.VK_E); break;
case 'f': r.keyPress(KeyEvent.VK_F); break;
case 'g': r.keyPress(KeyEvent.VK_G); break;
case 'h': r.keyPress(KeyEvent.VK_H); break;
case 'i': r.keyPress(KeyEvent.VK_I); break;
case 'j': r.keyPress(KeyEvent.VK_J); break;
case 'k': r.keyPress(KeyEvent.VK_K); break;
case 'l': r.keyPress(KeyEvent.VK_L); break;
case 'm': r.keyPress(KeyEvent.VK_M); break;
case 'n': r.keyPress(KeyEvent.VK_N); break;
case 'o': r.keyPress(KeyEvent.VK_O); break;
case 'p': r.keyPress(KeyEvent.VK_P); break;
case 'q': r.keyPress(KeyEvent.VK_Q); break;
case 'r': r.keyPress(KeyEvent.VK_R); break;
case 's': r.keyPress(KeyEvent.VK_S); break;
case 't': r.keyPress(KeyEvent.VK_T); break;
case 'u': r.keyPress(KeyEvent.VK_U); break;
case 'v': r.keyPress(KeyEvent.VK_V); break;
case 'w': r.keyPress(KeyEvent.VK_W); break;
case 'x': r.keyPress(KeyEvent.VK_X); break;
case 'y': r.keyPress(KeyEvent.VK_Y); break;
case 'z': r.keyPress(KeyEvent.VK_Z); break;
case '1': r.keyPress(KeyEvent.VK_1); break;
case '2': r.keyPress(KeyEvent.VK_2); break;
case '3': r.keyPress(KeyEvent.VK_3); break;
case '4': r.keyPress(KeyEvent.VK_4); break;
case '5': r.keyPress(KeyEvent.VK_5); break;
case '6': r.keyPress(KeyEvent.VK_6); break;
case '7': r.keyPress(KeyEvent.VK_7); break;
case '8': r.keyPress(KeyEvent.VK_8); break;
case '9': r.keyPress(KeyEvent.VK_9); break;
case '0': r.keyPress(KeyEvent.VK_0); break;
case '-': `enter code here`
r.keyPress(KeyEvent.VK_MINUS);
}
}
}
String#split() is what you are looking for.
When reading the file line by line, just split the returned String by \t (Tab character).
Your desired first three words will be the indices 0 to 2.
while (in.hasNext()) {
String[] words = in.nextLine().split("\t");
for (int i = 0; i < 3; i++) {
newArr.add(words[i]);
}
}
You could try reading each line individually with String line = in.nextLine(), then you could make an array of each word in each line by doing String[] words = line.split("\t"). Then you could access the first three words of that line by words[0], words[1], and words[2].
Here's some sample code:
while (in.hasNext()) {
String input = in.nextLine();
String[] words = input.split("\t");
newArr.add(words[0]);
newArr.add(words[1]);
newArr.add(words[2]);
}

Categories

Resources