I am trying to code a letter frequency program that counts the alphabetic characters from a .txt file and presents the frequency data in a 2 column table. I am struggling to call the function char2int from the function processFile. I am not sure if I need to use an if statement or not as well. Also I am summing up all the alphabetic characters and other characters. If someone can help explain what I am doing wrong I'd be grateful.
Here is my code:
final static int AlphabetSize = 26;
final static Scanner cin = new Scanner(System.in);
final static PrintStream cout = System.out;
final static int MaxBarLength = 50;
public static void main(String[] args) {
String fileName;
// get the file name
cout.print("Enter the file name: ");
fileName = cin.nextLine();
// process the file
try {
processFile(fileName);
}
catch (IOException e) {
e.printStackTrace();
} // end try
} // end main
static void processFile(final String fileName)
throws FileNotFoundException, IOException
{
FileInputStream inFile = new FileInputStream(fileName);
int inputValue;
// declare other variables you need
int counters [] = new int [26];
int alpha = 0;
int num = 0;
int ticker = 0;
// get the first character from file
inputValue = inFile.read();
while (inputValue != -1) {
char ch = (char) inputValue;
// add code to process this character
if (){
counters[char2int(ch)]++;
alpha++;
}else{
num++;
}
// read next input character
inputValue = inFile.read();
} // end loop
inFile.close();
System.out.println("\nThe data file has " + alpha + " alphabetic, and " + num + " other characters.\n");
// generate appropriate output
display(counters);
} // end function
static void display(final int [] counters) {
// write code for this function
System.out.println("Letter" + " " + "Count" + " " + "Bar");
System.out.println("------" + " " + "-----" + " " + "---");
printChars(counters);
} // end function
// char2int is complete
static int char2int(final char arg) {
if (!Character.isLetter(arg))
return -1;
else
return (int) Character.toUpperCase(arg) - (int) 'A';
} // end function
// function printChars writes n copies of the character c to the
// standard output device
static void printChars (final int[] counters) {
// write the code
for (int i = 0; i < 26; i++){
System.out.printf("%c%7d\n", i + 'A', counters[i]);
}
// end printChars
} // end function
I would personally do it this way William:
int c = char2int(ch);
if (c >= 0) {
counters[c]++;
alpha++;
}
else { num++; }
You should also consider taking care of non-alphabetic characters should there be any within the text file. This can also be handled within the char2int() method.
Related
I have tried to write a Java program that count number of words start with UpperCase in each line separately, like in a txt file, and print the line number next to the number of words start with UpperCase in that line.
I have only come out with how to count the number for a single line using:
Scanner in = new Scanner(System.in);
String s = new String();
System.out.println("Enter a line:");
s = " " + in .nextLine();
char ch;
int count = 0;
for (int i = 1; i < s.length(); i++) {
ch = s.charAt(i);
if (Character.isUpperCase(ch) && (i == 0 || Character.isWhitespace(s.charAt(i - 1)))) {
count++;
}
}
System.out.println("total number of words start with capital letters are :" + count);
I tried to do it on the way I want, but it keep showing me "File is empty":
FileInputStream in = new FileInputStream("io-02.txt");
Scanner inScanner = new Scanner(in);
FileOutputStream out = new FileOutputStream("io-02-out.txt");
PrintWriter pwr = new PrintWriter(out);
int linenumb=0;
String s="";
char c;
int count = 0;
inScanner.useDelimiter("");
for (int i = 1; i < s.length(); i++) {
s = " " + inScanner.nextLine().trim();
c = s.charAt(i);
if (Character.isUpperCase(c) && (i == 0 || Character.isWhitespace(s.charAt(i - 1)))) {
count++;
} else if(s == "\n"){
if(linenumb == 0)
pwr.printf("%6s%35s%n", "Line#", "Number of Uppercase characters");
linenumb++;
pwr.printf("%5d.%35d%n", linenumb, count);
count = 0;
}
}
if(linenumb == 0)
System.out.println("Error: The input file is empty");
else{
linenumb++;
pwr.printf("%5d.%35d%n", linenumb, count);
System.out.println("The file output.txt has been created . . . ");
}
Please help.
Java 8 solution:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
final public class UppercaseWordCounter { // https://stackoverflow.com/questions/49193228/counting-number-of-words-start-with-uppercase-letter-in-strings-java
final private static File FILE_WORDS = new File("io-02.txt");
final private static File FILE_RESULTS = new File("io-02-out.txt");
public static void main(final String[] args) {
if (!FILE_WORDS.exists()) {
System.err.println("Input file does not exist: " + FILE_WORDS);
System.exit(1);
}
if (FILE_RESULTS.exists()) {
if (!FILE_RESULTS.delete()) {
System.err.println("Intended output file exists already and can't be deleted: " + FILE_RESULTS);
System.exit(2);
}
}
try (final BufferedReader br = Files.newBufferedReader(FILE_WORDS.toPath(), StandardCharsets.UTF_8);
final BufferedWriter bw = Files.newBufferedWriter(FILE_RESULTS.toPath(), StandardCharsets.UTF_8)) {
int lineCounter = 1;
String line;
while ((line = br.readLine()) != null) {
final int upperCaseWordsInThisLine = countUpperCaseWords(line);
bw.write("Line " + lineCounter + " has " + upperCaseWordsInThisLine + " upper case word" + (upperCaseWordsInThisLine == 1 ? "" : "s") + ".\n");
lineCounter++;
}
} catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
}
private static int countUpperCaseWords(final String line) {
int ret = 0;
final int length = line.length();
boolean newWord = true;
for (int i = 0; i < length; i++) {
final char c = line.charAt(i);
if (" .,;/".indexOf(c) >= 0) {
newWord = true;
} else if (newWord) {
newWord = false;
if (Character.isUpperCase(c)) {
ret++;
}
}
}
return ret;
}
}
Why don't you use a method from Files class, which is available from java 1.7
List<String> lst = Files.readAllLines(Path path, Charset cs)
then you can loop over the lst List checking your condition
My program stimulates FCFS scheduling algorithm. It takes a .csv file as input and output the average waiting time. I have trouble with inputting the file. This is the error that i get when i ran the code:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at main.FCFS.main(FCFS.java:16)
What am I doing wrong? I cannot seems to figure it out. Please help.
package main;
//programming FCFS scheduling algorithm
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
public class FCFS {
public static void main(String[] args) throws FileNotFoundException {
// To Store Name of the file to be opened
String file = args[0];
int i = 0, n;
double AWT = 0, ATT = 0;
int AT[] = new int[100];
int BT[] = new int[100];
int WT[] = new int[100];
int TAT[] = new int[100];
int PID[] = new int[100];
// To open file in read mode
FileInputStream fin = null;
// To read input(file name) from standard input stream
Scanner s = new Scanner(new File("/Users/SLO/ex.csv"));
// To hold each single record obtained from CSV file
String oneRecord = "";
try {
// Open the CSV file for reading
fin = new FileInputStream(file);
// To read from CSV file
s = new Scanner(fin);
// Loop until all the records in CSV file are read
while (s.hasNextLine()) {
oneRecord = s.nextLine();
// Split record into fields using comma as separator
String[] details = oneRecord.split(",");
PID[i] = Integer.parseInt(details[0]);
AT[i] = Integer.parseInt(details[1]);
BT[i] = Integer.parseInt(details[2]);
System.out.printf("Process Id=%d\tArrival Time=%d\tBurst Time=%d\n", PID[i], AT[i], BT[i]);
i++;
}
WT[0] = 0;
for (n = 1; n < i; n++) {
WT[n] = WT[n - 1] + BT[n - 1];
WT[n] = WT[n] - AT[n];
}
for (n = 0; n < i; n++) {
TAT[n] = WT[n] + BT[n];
AWT = AWT + WT[n];
ATT = ATT + TAT[n];
}
System.out.println(" PROCESS BT WT TAT ");
for (n = 0; n < i; n++) {
System.out.println(" " + PID[n] + " " + BT[n] + " " + WT[n] + " " + TAT[n]);
}
System.out.println("Avg waiting time=" + AWT / i);
System.out.println("Avg waiting time=" + ATT / i);
} catch (FileNotFoundException e) {
System.out.printf("There is no CSV file with the name %s", file);
}
finally {
if (fin != null) {
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Well, an ArrayIndexOutOfBoundsException is thrown if there are no arguments, because you access the empty array at a non existing index. Add the following lines to check if the argument is passed correctly:
...
public static void main(String[] args) throws FileNotFoundException {
if (args.length == 0)
throw new IllegalArgumentException("Missing mandatory file name in argument list");
// To Store Name of the file to be opened
String file = args[0];
...
If the missing argument ist the reason for the failure, check out https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html to find out how to pass it properly.
I'm trying to encrypt a txt file, but when i send my chars to array I lose my spaces. I want to keep my spaces along with punctuation and cases of letters. I am so close but cannot seem to do anything that doesn't make A.) everything a null character or B.) loop capital letters. Thanks in advance.
public class Encryption {
CaesarCipher c= new CaesarCipher();
Scanner kb = new Scanner(System.in);
String end = "";
public void changeLetters(File file) {
System.out.println("How far would you like to shift?");
int shift = Integer.parseInt(kb.nextLine());
Scanner fileScanner;
try {
fileScanner = new Scanner(file);
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
shift(line, shift);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private void shift(String line, int shift) {
char[] og = line.toCharArray();
for (int i = 0; i < og.length; i++) {
char letter = og[i];
letter = (char) (letter + shift);
if (letter > 'z') {
letter = (char) (letter - 26);
} else if (letter < 'a') {
letter = (char) (letter + 26);
}
end = end + Character.toString(letter);
}
System.out.println(end);
File file = new File("Encrypted.txt");
FileWriter writer = null;
{
try {
writer = new FileWriter(file);
writer.write(end);
writer.close();
} catch (
IOException e)
{
e.printStackTrace();
}
System.out.println("Decryption Complete");
System.out.println("Q to quit, C to Continue");
String response = kb.next();
if (response.equals("q") || response.equals("Q")) {
System.out.println("Goodbye");
} else if (response.equals("c") || response.equals("C")) {
c.getInformation();
}
}
}
I believe the problem comes from the fact you are adding (+/-) 26 to your letter, for example letter = (char) (letter - 26);. This would only work within the alphabet [a-z]. However as you want to be able to handle capital letters, special characters and such you can't do this.
It would also be cleaner to use the modulo operator % in order to do this. Hence you won't have to make an explicit test, like you did if (letter > 'z').
Here is the shift procedure, which is really simple
private String shift(String str, int shift) {
String shifted = "";
for(int i = 0; i < str.length(); i++) {
char original = str.charAt(i);
char shiftedChar = (char) ((original + shift) % Integer.MAX_VALUE);
shifted += shiftedChar; // Append shifted character to the end of the string
}
return shifted;
}
However i'm not sure this is the modulus to use. But i did some tests and this seemed to work.
Here is how you can shift and unshift
String test = "This is a test!";
String encoded = shift(test, 3);
String decoded = shift(encoded, -3);
System.out.println("Encoded : " + encoded + "\n" + "Decoded : " + decoded);
I have a line of text that I need to decrypt into a cipher text.
Let's say my line of text is abc def ghijklm n opq rstu vwx yz
and I want an output like this: aei qu c k rvzdhmptxbfjn y glosm
lets say I entered my "key" as 5. The code then will enter every 5th element of the array o f strings of the text from the text file.
This is the code I have come up with and I have hit a wall on what to do.
import java.io.*;
import java.util.*;
public class Files1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int key;
System.out.print("Enter file: ");
String fileName = input.nextLine();
System.out.print("Please enter your Cipher Key: ");
key = input.nextInt();
Scanner inputStream = null;
System.out.println("File name is: " + fileName);
try {
inputStream = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
System.out.println("Error opening the file" + fileName);
System.exit(0);
}
while (inputStream.hasNextLine()) {
String text = inputStream.nextLine();
System.out.println(text);
char arrayText[] = text.toCharArray();
for (int i = 0; i < arrayText.length; i += key) {
System.out.print("\n" + arrayText[i]);
}
}
}
}
Here is whats happening in the console:
Enter file: abc.txt
File name is: abc.txt
abc def ghijklm n opq rstu vwx yz
a
e
i
q
u
What you need is a circular list.
Here is a very simple and crude implementation of a circular list using arrays.
import java.util.Iterator;
import java.util.List;
public class CircularList implements Iterator<String> {
private String[] list;
private int pointerIndex;
private int key;
public CircularList(String[] list, int key) {
this.list = list;
pointerIndex = 1 - key;
this.key = key;
}
#Override
public boolean hasNext() {
if(list.length == 0){
return false;
}
return true;
}
#Override
public String next() {
if(pointerIndex + key > list.length) {
int diff = (list.length-1) - pointerIndex;
pointerIndex = key - diff;
return list[pointerIndex];
}else {
pointerIndex = pointerIndex + key;
return list[pointerIndex];
}
}
#Override
public void remove() {
//Do Nothing
}
}
Once you have a list in which you can iterate in a circular fashion, you can change you existing implementation to this -
import java.io.*;
import java.util.*;
public class Files1 {
public static void main(String[] args) {
System.out.print("Enter file: ");
Scanner input = new Scanner(System.in);
String fileName = input.nextLine();
Scanner inputStream = null;
System.out.println("" + fileName);
try {
inputStream = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
System.out.println("Error opening the file: " + fileName);
System.exit(0);
}
while (inputStream.hasNextLine()) {
String text = inputStream.nextLine();
System.out.println(text);
String[] splits = text.split("");
CircularList clist = new CircularList(splits, 5);
for (int i = 0; i < splits.length -1; i += 1) {
System.out.print("" + clist.next());
}
}
}
}
Output -
Enter file: resources\abc.txt
resources\abc.txt
abc def ghijklm n opq rstu vwx yz
aei qu c k rvzdhmptxbfjn y glosw
Also the last character in your cipher should be 'w' and not 'm'.
You don't specify what should happen to the spaces, or what happens when wraparound is required, but assuming spaces are significant and wrap-around just happens naturally:
for (int i = 0; i < text.length(); i++)
{
System.out.print(text.charAt((i*5) % text.length()));
}
prints aei qu c k rvzdhmptxbfjn y glosw, which strongly suggests an error in your expected output.
import java.io.;
import java.util.;
public class Files1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int key;
System.out.print("Enter file: ");
String fileName = input.nextLine();
System.out.print("Please enter your Cipher Key: ");
key = input.nextInt();
Scanner inputStream = null;
System.out.println("File name is: " + fileName);
try {
inputStream = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
System.out.println("Error opening the file" + fileName);
System.exit(0);
}
while (inputStream.hasNextLine()) {
String text = inputStream.nextLine();
System.out.println(text);
for (int i = 0; i < text.length(); i++) {
System.out.print(text.charAt((i * key) % text.length()));
}
}
}
}
MANY THANKS TO EJP AND Pai!
i learned alot!
I am trying to create a program which will read a file and check whether the text is a palindrome or not. The code compiles, but doesnt really work.
The problem is I dont know how to break a complete token into characters or assign it to a string in order to use string's length to push(enqueue) each letter or digit into the stack(queue). Can anyone suggest a solution for this?
public static void main(String [] args) throws IOException{
StackReferenceBased stack = new StackReferenceBased();
QueueReferenceBased queue = new QueueReferenceBased();
Scanner s = null;
String fileName=args[0]+".txt";
int symbols = 0;
int lettersAndDigits =0;
int matches = 0;
try{
s = new Scanner(new File(fileName));
while(s.hasNext()){
String current = s.next();
for(int i=0;i<current.length();i++){
char temp = s.next().charAt(i);
if(Character.isLetterOrDigit(temp)){
stack.push(temp);
queue.enqueue(temp);
lettersAndDigits++;
}
else {
symbols++;
}
}
}
System.out.println("There are: " + " "+ symbols + " " +"symbols and " + " "+lettersAndDigits + " "+ "digits/letters");
}
catch (FileNotFoundException e) {
System.out.println("Could not open the file:" + args[0]);
} //catch (Exception e) {
//System.out.println("ERROR copying file");
finally {
if(s != null){
s.close();
}
}
while (!stack.isEmpty()){
if(!stack.pop().equals(queue.dequeue())){
System.out.println("not pali");
break;
}
else {
++matches;
}
}
if(matches==lettersAndDigits){
System.out.print("pali");
}
}
Instead of
char temp = s.next().charAt(i);
you need
char temp = current.charAt(i);
By calling s.next() you read the next token from the file and try to access the ith element of that token based on the first string's (current) length, which will lead to exceptions if the tokens read are shorter than the first stoken