String not populating properly - java

I am writing a program that is going to read a string from a file, and then remove anything that isn't 1-9 or A-Z or a-z. The A-Z values need to become lowercase. Everything seems to run fine, I have no errors, however my output is messed up. It seems to skip certain characters for no reason whatsoever. I've looked at it and tweaked it but nothing works. Can't figure out why it is randomly skipping certain characters because I believe my if statements are correct. Here is the code:
String dataIn;
int temp;
String newstring= "";
BufferedReader file = new BufferedReader(new FileReader("palDataIn.txt"));
while((dataIn=file.readLine())!=null)
{
newstring="";
for(int i=0;i<dataIn.length();i++)
{
temp=(int)dataIn.charAt(i);
if(temp>46&&temp<58)
{
newstring=newstring+dataIn.charAt(i);
}
if(temp>96&&temp<123)
{
newstring=newstring+dataIn.charAt(i);
}
if(temp>64&&temp<91)
{
newstring=newstring+Character.toLowerCase(dataIn.charAt(i));
}
i++;
}
System.out.println(newstring);
}
So to give you an example, the first string I read in is :
A sample line this is.
The output after my program runs through it is this:
asmlietis
So it is reading the A making it lowercase, skips the space like it is suppose to, reads the s in, but then for some reason skips the "a" and the "m" and goes to the "p".

You're incrementing i in the each of the blocks as well as in the main loop "header". Indeed, because you've got one i++; in an else statement for the last if statement, you're sometimes incrementing i twice during the loop.
Just get rid of all the i++; statements other than the one in the for statement declaration. For example:
newstring="";
for(int i=0;i<dataIn.length();i++)
{
temp=(int)dataIn.charAt(i);
if(temp>46&&temp<58)
{
newstring=newstring+dataIn.charAt(i);
}
if(temp>96&&temp<123)
{
newstring=newstring+dataIn.charAt(i);
}
if(temp>64&&temp<91)
{
newstring=newstring+Character.toLowerCase(dataIn.charAt(i));
}
}
I wouldn't stop editing there though. I'd also:
Use a char instead of an int as the local variable for the current character you're looking at
Use character literals for comparisons, to make it much clearer what's going on
Use a StringBuilder to build up the string
Declare the variable for the output string for the current line within the loop
Use if / else if to make it clear you're only expecting to go into one branch
Combine the two paths that both append the character as-is
Fix the condition for numbers (it's incorrect at the moment)
Use more whitespace for clarity
Specify a locale in toLower to avoid "the Turkey problem" with I
So:
String line;
while((line = file.readLine()) != null)
{
StringBuilder builder = new StringBuilder(line.length());
for (int i = 0; i < line.length(); i++) {
char current = line.charAt(i);
// Are you sure you want to trim 0?
if ((current >= '1' && current <= '9') ||
(current >= 'a' && current <= 'z')) {
builder.append(current);
} else if (current >= 'A' && current <= 'Z') {
builder.append(Character.toLowerCase(current, Locale.US));
}
}
System.out.println(builder);
}

Related

How to compare two strings, of different length to find identical substring

The problem is:
Client accounts are filed under a classification system using codes eg MA400. I need a method that will reset the original MA400 to an updated code such as MA400.4. If the new code has 5 characters to which the original is reset then the method returns true. Not the best wording but that is all I have right now.
It hasn't been specified if the characters need to be in the same order, eg.
String str = "abc123";
String newStr = "xyz123abc";
I am assuming they need to be in the same order. So the above strings would only have 3 like characters.
char[]array = str.toCharArray();
char[]array2 = newStr.toCharArray();
I am thinking now to use a compareTo method on the two arrays, but I am not sure how this would work exactly. Perhaps I could use a for loop to stop comparing after the final element in the shortest string but not entirely sure if I can do much with that.
I feel like I am going about this in the wrong way and there is a less complicated way to check for like characters in a string?
From what I understand something like this will work. Remember this will only count unique characters. Order does not matter
public static boolean matchingChar(final String st1, final String st2) {
if(st1 == null || st2 == null || st1.length() < 5 || st2.length() < 5) {
return false;
}
//This is if you wish unique characters to be counted only
//Otherwise you can use simple int count = 0
HashSet<Character> found = new HashSet<Character>();
//found.size() < 5 so the loop break as soon as the condition is met
for(int i = 0; i < st1.length() && found.size() < 5; i++) {
if(st2.indexOf(st1.charAt(i)) != -1) {
found.add(st1.charAt(i));
}
}
return found.size() >= 5;
}

Exclude single characters from rle output?

public static String compress(String original) {
StringBuffer dest = new StringBuffer();
for (int i = 0; i < original.length(); i++) {
int runLength = 1;
while (i+1 < original.length() && original.charAt(i) == original.charAt(i+1)) {
runLength++;
i++;
}
dest.append(runLength);
dest.append(original.charAt(i));
}
return dest.toString();
}
hello all, so i have this code block for a method to compress a phrase using RLE algorithm. I'm having trouble figuring out how to make the method exclude applying RLE compression to single characters in my output.
At the moment, if the user enters "fffgggttth", then the code outputs "3f3g3t1h", but I want the output to leave the h alone, so it would just be "3f3g3th".
I feel like the solution involves a break or continue statement before the for block, but I could be wrong. Thanks!
Here is a trivial answer to your problem:
if(runLength > 1) dest.append(runLength);
Simply put, it will only add the number of continuous occurrences of a character if it appears more than once. If the character appears only one time in a row, it will not append the length (which is 1). Make sure you take into account 1's not appearing in your decompression method.

Using bufferedreader then convert to a string

Hi im having this assignment that I don't really understand how to pull off.
Ive been programing java for 2.5 weeks so Im really new.
Im supposed to import a text document into my program and then do these operations, count letters, sentences and average length of words. I've to perform the counting task letter by letter, I'm not allowed to scan the entire document at the same time. Ive managed to import the text and also print it out, but my problem is I cant use my string "line" to do any of these operations. Ive tried converting it to arrays, strings and after a lot of failed attempts im giving up. So how do I convert my input to something I can use, because i always get the error message "line is not a variable" or smth like that.
Jesper
UPDATE WITH MY SOLUTION! also some of it is in Swedish, sorry for that.
Somehow the Format is wrong so I uploaded the code here instead, really don't feel to argue with this wright now!
http://txs.io/3eIb
To count letters, check each character. If it's a space or punctuation, ignore it. Otherwise, it's a letter and we should this increment.
Every word should have a space after it unless it is the last word of the sentence. To get the number of words, track the number of spaces + number of sentences. To get number of sentences, find the number of ! ? and .
I would do that by looking at the ascii value of each character.
int numSentences = 0;
int numWords = 0;
while (line = ...){
for(int i = 0; i <line.length(); i++){
int curCharAsc = (int)(line.at(i)) //get ascii value by casting char to int
if((curCharAsc >= 65 && curCharAsc <= 90) || (curCharAsc >= 97 && curCharAsc <= 122) //check if letter is uppercase or lowercase
numLetters++;
if(curCharAsc == 32){ //ascii for space
numWords++;
}
else if (curCharAsc == 33 || curCharAsc == 46 || curCharAsc == 63){
numWords++;
numSentences++;
}
}
}
double avgWordLength = ((double)(letters))/numWords; //cast to double before dividing to avoid round-off
Your code as presented works fine, it loads a file and prints out the contents line by line. What you probably need to do is capture each of those lines. Java has two useful classes for this StringBuilder or StringBuffer (pick one).
BufferedReader input = new BufferedReader(new FileReader(args[0]));
String line;
StringBuffer buffer = new StringBuffer();
while ((line = input.readLine()) != null) {
System.out.println(line);
buffer.append(line+" ");
}
input.close();
performOperations(buffer.toString());
The only other possibility is (if your own code is not running for you) - possibly you aren't passing the input file name as a parameter when you run this class?
UPDATE
NB - I've modified the line
buffer.append(line+"\n");
to add a space instead of a line break, so that it is compatible with algorithms in the #faraza answer
The method performOperations doesn't exist yet. So you should / could add something like this
public static void performOperations(String data){
}
You method could in turn make calls out to separate methods for each operation
public static void performOperations(String data){
countWords(data);
countLetters(data);
averageWordLength(data);
}
To take it to the next level, and introduce Object Orientation, you could create a class TextStatsCollector.
public class TextStatsCollector{
private final String data;
public TextStatsCollector(final String data) {
this.data = data;
}
public int countWords(){
//word count impl here
}
public int countLetters(){
//letter count impl here
}
public int averageWordLength(){
//average word length impl here
}
public void performOperations(){
System.out.println("Number of Words is " + countWords());
System.out.println("Number of Letters is " + countLetters());
System.out.println("Average word length is " + averageWordLength());
}
}
Then you could use TextStatsCollector like the following in your main method
new TextStatsCollector(buffer.toString()).performOperations();

Finding Palindromes in a word list

I'm working on a program for Java on how to find a list of palindromes that are embedded in a word list file. I'm in an intro to Java class so any sort of help or guidance will be greatly appreciated!
Here is the code I have so far:
import java.util.Scanner;
import java.io.File;
class Palindromes {
public static void main(String[] args) throws Exception {
String pathname = "/users/abrick/resources/american-english-insane";
File dictionary = new File(pathname);
Scanner reader = new Scanner(dictionary);
while (reader.hasNext()) {
String word = reader.nextLine();
for (int i = 0; i > word.length(); i++) {
if (word.charAt(word.indexOf(i) == word.charAt(word.indexOf(i)) - 1) {
System.out.println(word);
}
}
}
}
}
There are 3 words that are 7 letters or longer in the list that I am importing.
You have a few ways to solve this problem.
A word is considered a palindrome if:
It can be read the same way backwards as forwards.
The first element is the same as the last element, up until we reach the middle.
Half of the word is the same as the other half, reversed.
A word of length 1 is trivially a palindrome.
Ultimately, your method isn't doing much of that. In fact, you're not doing any validation at all - you're only printing the word if the first and last character match.
Here's a proposal: Let's read each end of the String, and see if it's a palindrome. We have to take into account the case that it could potentially be empty, or be of length 1. We also want to get rid of any white space in the string, as that can cause errors on validation - we use replaceAll("\\s", "") to solve that.
public boolean isPalindrome(String theString) {
if(theString.length() == 0) {
throw new IllegalStateException("I wouldn't expect a word to be zero-length");
}
if(theString.length() == 1) {
return true;
} else {
char[] wordArr = theString.replaceAll("\\s", "").toLowerCase().toCharArray();
for(int i = 0, j = wordArr.length - 1; i < wordArr.length / 2; i++, j--) {
if(wordArr[i] != wordArr[j]) {
return false;
}
}
return true;
}
}
I'm assuming that you're reading in strings. Use string.toCharArray() to convert each string to a char[]. Iterate through the character array using a for loop as follows: on iteration 1, if the first character is equal to the last character, then proceed to the next iteration, else return false. On iteration 2, if the second character is equal to the second-to-last character then proceed to the next iteration, else return false. And so on, until you reach the middle of the string, at which point you return true. Be careful of off-by-one errors; some strings will have an even length, some will have an odd length.
If your palindrome checker is case insensitive, then use string.toLowerCase().toCharArray() to preprocess the character array.
You can use string.charAt(i) instead of string.toCharArray() in the for loop; in this case, if the palindrome checker is case insensitive then preprocess the string with string = string.toLowerCase()
Let's break the problem down: In the end, you are checking if the reverse of the word is equal to the word. I'm going to assume you have all of the words stored in an array called wordArray[].
I have some code for getting the reverse of the word (copied from here):
public String reverse(String str) {
if ((null == str) || (str.length() <= 1)) {
return str;
}
return new StringBuffer(str).reverse().toString();
}
So, now we just need to call that on every word. So:
for(int count = 0; count<wordArray.length;count++) {
String currentWord = wordArray[count];
if(currentWord.equals(reverse(currentWord)) {
//it's a palendrome, do something
}
}
Since this is homework, i'll not supply you with code.
When i code, the first thing i do is take a step back and ask myself,
"what am i trying to get the computer to do that i would do myself?"
Ok, so you've got this huuuuge string. Probably something like this: "lkasjdfkajsdf adda aksdjfkasdjf ghhg kajsdfkajsdf oopoo"
etc..
A string's length will either be odd or even. So, first, check that.
The odd/even will be used to figure out how many letters to read in.
If the word is odd, read in ((length-1)/2) characters.
if even (length/2) characters.
Then, compare those characters to the last characters. Notice that you'll need to skip the middle character for an odd-lengthed string.
Instead of what you have above, which checks the 1st and 2nd, then 2nd and 3rd, then 3rd and fourth characters, check from the front and back inwards, like so.
while (reader.hasNext()) {
String word = reader.nextLine();
boolean checker = true;
for (int i = 0; i < word.length(); i++) {
if(word.length()<2){return;}
if (word.charAt(i) != word.charAt(word.length()-i) {
checker = false;
}
}
if(checker == true)
{System.out.println(word);}
}

Is this a good way of parsing a string?

My program reads lines from a plain text file w/ lines formatted: <integer>;<integer>%n, where ; is the delimiter. It compares the two parsed integers against 2 other known values and increments tallyArray[i] if they match.
I currently use:
try {
scan = new Scanner(new BufferedReader(new FileReader("LogFileToBeRead.txt")));
for (int i = 0; i < tallyArraySize; i++) {
explodedLogLine = scan.nextLine().split(";");
if (IntReferenceVal1 == Integer.parseInt(explodedLogLine[0]) && IntReferenceVal2 == Integer.parseInt(explodedLogLine[1])) {
tallyArray[i]++;
}
}
} finally {
if (scan != null) { scan.close(); }
}
I was wondering if there were any serious faults with this method. It does not need to be production-quality.
Also, is there a standard way of parsing a string like this?
EDIT: We can assume the text file is perfectly formatted. But I see the importance for accounting for possible exceptions.
You are not handling NumberFormatExceptions thrown by the Integer.parseInt() method calls. If there's one bad line, execution exits your for loop.
You aren't vetting the integrity of the file you are reading from. If there isn't a ; character or if the Strings aren't actually numbers, execution simply exits the code block you posted.
If you can assume the file is perfectly formatted, and you're set on using a Scanner, you can add ; as a delimiter to the Scanner:
scan = new Scanner(new BufferedReader(new FileReader("LogFileToBeRead.txt")));
scan.useDelimiter(Pattern.compile("(;|\\s)"));
for (int i = 0; i < tallyArraySize; i++) {
int ref1 = scan.nextInt();
int ref2 = scan.nextInt();
if (IntReferenceVal1 == ref1 &&
IntReferenceVal2 == ref2) {
tallyArray[i]++;
}
}
And simply call Scanner.nextInt() twice for each line.
According to me There are three flaws in the program.
Delimiter ; what if there is delimiter is removed by accident or added by accident
There should be check on explodedLogLine that it is of length 2 and it is not null otherwise it will result in unexpected runtime error
You should catch NumberFormatException format exception since you can never be sure that Input is always a number
A simple illustration below gives you idea how things will go wrong.
String str = "3;;3";
System.out.println(Arrays.toString(str.split(";")));
This code will print [3, , 3] in such case your program will produce NumberFormatException as "" string can not be parsed to Integer.

Categories

Resources