I have this loop that won't stop when it should and it's only happen on my production server but not on my dev server. So I'm going crazy.
//objectName can be any value from [a-}],
char objectName = 'a'; //objectName is initialized with value 'a'
//before objectName hit the line below, it was increment objectName++; until the value of
//objectName = '}'
for( char c = objectName; c <= 'z'; c++ ){
//do something
}
objectName can be any character but in my case I know that my objectName will be "}" character, which is technically more than 'z'. So what I don't understand is why is my loop being executed still.
The funny thing is we have test server which uses JAVA 1.6.0_30, and we have try testing there and it's working just fine.
My Dev Server uses : java 1.6.0_45
My Prod Server uses : java 1.6.0_30
If you see anything wrong with my logic please let me know, any circumstance that will make my loop be active even when it shouldn't feel free to let me know.
I'm no expert so I could be wrong here but using characters to iterate through a for loop looks alien to me and probably not the best thing to be doing.
I would suggest using an array/(array)List of characters and iterating through the list that way or as #Chris said by getting the numeric value of the characters
for(int i = Character.getNumericValue(objectName); i <= Character.getNumericValue('z'); i++)
{
//System.out.println("test");
}
Like I said I'm no expert but using numbers to iterate through for loops seems like a better practice or at least a more stable one.
In your question you say "I have this loop that won't stop when it should..." when should it stop? Currently the loop is exiting when the condition turns false. Basically when 10 >= 35.
First off, how is '}' "technically" more than 'z'?
'}' is equivalent to -1 and 'z' is equivalent to positive 35.
Using the code that you haven't commented you will loop 26 times, as expected (using char 'a' & char 'z').
'a' is equivalent to 10 and 'z' is equivalent to 35.
You can check these values by using Character.getNumericValue()
char objectName = 'a';
for( char c = objectName; c <= 'z'; c++ ){
//System.out.println("test");
}
Yields the same result as:
for( int i = 10; i <= 35; i++ ){
//System.out.println("test");
}
Unless I have missed something, this seems like an overly complicated way to achieve a really simple result.
I would have asked for clarification on something but I can't comment.
Related
Ok so as I plod along in my classes in Java coding I was asked to use this code to count the instances of lowercase letters that were generated by a method for a character array. I can follow the code up to the point it throws out stuff like. "counts[chars[currentIndex] - 'a']++;"
So yes, the codes says it's making a public method called countLetters, it needs to be called somewhere in the main body and needs a character array parameter to fire up, got that. It creates a integer array called counts and it's size is 26, (same size as total # of lowercase letters in alphabet, got that.) It then fires up a for function, commonly needed for arrays. Creates a variable called currentIndex, default value 0, while current index is less than the size of chars character array do the stuff below. Then it gets to what the for loop actually is DOING. and uh, what the hell is it doing? it's increasing the size of count's index? The whole thing is weird, like some array within an array and subtracting the numeric value of lowercase 'a'? It's modifying the currentIndex of count somehow. Why is subtracting the numeric value of 'a' necessary? Wouldn't - 26 suffice here?
Can somebody please explain slowly and in complete layman's terms how this is working? I'm really a novice programmer at best and this stuff is confusing the hell out of me, so please bear with me, I'm not the sharpest tool in the shed, as the Smashmouth song goes. All joking aside, I'd appreciate if you could break down what is going on.
//count the occurrences of each letter
public static int[] countLetters(char[] chars){
//declare and create an array of 26 int
int[] counts = new int[26];
//for each lowercase letter in the array, count it
for (int currentIndex = 0; currentIndex < chars.length; currentIndex++)
counts[chars[currentIndex] - 'a']++;
return counts;
}
Alrightey so this line:
counts[chars[currentIndex] - 'a']++;
Is short for all of this:
// Get the current character from the array:
char character = chars[currentIndex];
// Characters are just numbers. Check out e.g. an "ASCII table".
// So, let's start treating them like numbers and take 'a' from that.
int indexInCounts = character - 'a';
// Increase the count for that letter:
counts[indexInCounts] = counts[indexInCounts] + 1;
Why 'a'?
Arrays start at 0 - you mentioned that in your question so it looks like you've got the hang of those so far. So, if we want counts[0] to represent the number of a's in the input, then we'll need to put 'a' at 0.
'a'-'a' is 0.
'b'-'a' is 1.
etc.
So, conveniently, taking away 'a' from our input character gives us a number that'll work great for our array index.
Letters taking away letters is so weird!
Computers only really deal with numbers. Pull up an ASCII table, and you get an easy way to see how letters map to the underlying numbers (in the ASCII encoding scheme):
97: Lowercase 'a'
98: Lowercase 'b'
99: Lowercase 'c'
.. And so on!
Hopefully you can see where that's going!
98 (b) - 97 (a) gives us that index of 1, for example.
Try it out, but don't forget those brackets!
If you want to experiment, you could swap out that line for the ones above, but don't forget the brackets of your for loop!
for(int a=...)
doSomething(); // Only this first line is looped
doSomethingElse(); // This happens *once*!
This is called implicit brackets and is also just a convenience thing. So, here's the full, expanded version:
for (int currentIndex = 0; currentIndex < chars.length; currentIndex++)
{
// Everything in those brackets will be repeated.
// Get the current character from the array:
char character = chars[currentIndex];
// Characters are just numbers. Check out e.g. an "ASCII table".
// So, let's start treating them like numbers and take 'a' from that.
int indexInCounts = character - 'a';
// Increase the count for that letter:
counts[indexInCounts] = counts[indexInCounts] + 1;
}
Am I supposed to write stuff like that straight away?
Not really, no! In reality, you'd typically start out with the expanded version seen above (although most would immediately use counts[indexInCounts]++;). When a variable is only used once it's often easier to then substitute the actual value in - like this, without all those comments:
char character = chars[currentIndex];
int indexInCounts = character - 'a'; // Character is only used once.
counts[indexInCounts]++; // indexInCounts is only used once.
Step 2:
char character = chars[currentIndex];
counts[character - 'a']++; // Character is only used once.
Finally, the magical line is back:
counts[chars[currentIndex] - 'a']++;
Predicting errors
If you think you've got the hang of it then try and predict what error you'll get if you chuck an evil space character into the input.
Here's a spoiler:
You'll get an index out of range exception. Space is 32 on that ASCII table. 32 - 97 is very much a negative number, and very much out of range of the acceptable 0-25 of your counts array!
P.s. I'm not the sharpest tool in the shed - I will forever and always disagree (except about the song; that's great) :) Everybody has to start somewhere and you're giving it a try so I wish you all the best!
I'm attempting to write a Java program that searches for a specific substring (xyz) within a user-entered string, and keeping a running count, unless that substring is preceded by a period. At this point in the class, we've only used charAt and length, so if possible I need to stick to that. Additionally, we haven't used regular expressions at all, so that's out the window too.
I've managed to get the program working as desired, with one notable exception: if the String entered begins with a period, it fails to count any successive matches. This is what I've got so far:
System.out.println("Give me a String:");
String s1 = kb.nextLine();
int index = 0;
int count = 0;
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
System.out.println(count);
You can simply check the input string whether it starts with period. If so then you can use the following piece of code to handle the validation.
if(s1.charAt(0)!='.')
{
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
}
else
{
index=1;
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
}
System.out.println(count);
}
As this seems like a homework type of question I will attempt to guide you in the right direction first and provide a solution at a later time. I strongly encourage you to work through the problem on your own first to the best of your ability before you look at my solution (once I post it) and to read this page before going ANY further
First, consider the kinds of inputs you could receive. Since you didn't specify any limitations you could get things like:
"" (empty string)
"\n" (whitespace)
"x" (a single character)
"xx" (two characters string)
"abc" (string of correct length, but not containing your substring)
".xyz" (the substring to be ignored)
I could go on, but I'm sure you can come up with all the various combinations of weird things you might receive. These are just a few examples to get you started (along with those I posted in the comments already)
Next, think about what you need your algorithm to do. As I said in the comments it sounds like you want to count the occurrences of the substring "xyz" while ignoring the occurrences of the substring ".xyz". Now consider how you're going to look for these substrings - you're going to advance one character at a time from left to right across the String looking for a substring that matches one of these two possibilities. When you find one of them you'll either ignore it or count it.
Hopefully this helps and as I said, I will post a solution later after you've had some time to wrestle with the code. If you do solve it go ahead and post your solution (maybe edit your question to add the new code or add an answer) Finally I once again strongly urge you to read this page if you have not already.
EDIT #1:
I wanted to add a little more information and that is: you already have a pretty good idea of what you need to do in order to count your "xyz" substring at this point - despite the small flaw in the logic for inputs like "xaz", which is easily fixable. What you need to focus on is how to ignore the substring ".xyz" so think about how you could implement the ignore logic, what does it mean to ignore it? Once you answer that it should start coming together for you.
EDIT #2:
Below you will find my solution to the problem. Once again it's important to understand how the solution works not just copy and paste it. If you simply copy my code without understanding it you're cheating yourself out of the education that you're trying to gain. I don't have time at the moment to describe in detail why and how this code works, but I do plan to edit again later to add those details.
import java.util.Scanner;
public class Main {
private static Scanner scan = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("Give me a String:");
String s1 = scan.nextLine();
System.out.println(countSubstrings(s1));
}
public static int countSubstrings(String s1){
int index = 0;
int count = 0;
while (index < s1.length()-2) {
if(s1.charAt(index) == '.' && s1.charAt(index+1) != '.'){
index++;
}
else if (index+2 < s1.length() && s1.charAt(index) == 'x' && s1.charAt(index + 1) == 'y'
&& s1.charAt(index + 2) == 'z') {
count++;
index+=2;
}
index++;
}
return count;
}
}
EDIT #3:
Here is the nuts and bolts of why the above code does what it does. First, we think about the fact that we're looking for 3 items (a triple) in a specific order within an array and if we see a fourth item (a period) immediately preceding the first item of the triple then we need to ignore the triple.
Per my previous edit we need to define what it means to ignore. In this case what we mean is to simply not count it and move on with our search for valid substrings to count. The simplest way to do that is to advance the index without incrementing the count.
So, ask yourself the following:
When should my loop stop? Since we're looking for triples we know we can stop if the length of the input String is less than 3 or when there are less than 3 characters left in the String that we have not examined yet. For example if the input is "xyzab" by the time we get to index 3 we know there's no possible way to form a triple where "a" is the first character in the triple and that therefore our counting is done.
Is there ever a time when I would not want to skip the next 3 characters after a period? After all the goal is to look for triples so wouldn't I want to skip 3 characters not just 1? Yes there is a time when you do NOT want to skip 3 characters and that's when you have something like ".axyz" because a valid triple could start as soon as the 2nd character past the period. So in fact you want to skip only 1 character.
This, and the fact that index is always incremented by 1 at the end of the loop (more on this later), is why the first condition inside the while only advances the index by 1:
if(s1.charAt(index) == '.' && s1.charAt(index+1) != '.'){
index++;
}
Is there ever a time when I would see a period and not wish to ignore (skip) the next character? Yes, when the next character is another period because it could indicate that another triple needs to be skipped. Consider the input "..xyz" which would result in a wrong answer if you encounter the first period and skip the second period since your algorithm could see the next three characters as a valid triple but in fact it is invalid because of the second period.
This is why the second half of the above condition exists:
`&& s1.charAt(index+1) != '.'`
Now ask yourself how to identify a valid triple. I'm sure by now you can see how to do this - check the current character, the next character, and the character after that for the values you want. This logic is the latter portion of the second if condition within the while:
s1.charAt(index) == 'x' && s1.charAt(index + 1) == 'y'
&& s1.charAt(index + 2) == 'z'
Whenever you're using calculations like index +1 or index +2 inside of a loop that is incrementing the index until it reaches a boundary you have to consider the possibility that your calculation will exceed the boundary because you can't rely on the loop to check this for you as the loop will not perform that check until either the end or beginning of the loop (depending on which kind of loop it is)
Considering the above you must ask yourself: How do I prevent out of boundary scenarios when I use these index+1, index+2, etc types of calculations? The answer is to add another piece to your condition:
index+2 < s1.length()
You may be wondering - why not add two checks since we're using index+1 and index+2? We only need one check to see if the greatest index we use will exceed the boundary in this case. If index +2 is beyond the bounds we don't care if index+1 is or is not because it won't matter we can't possibly have a matching substring.
Next, inside of the second if inside the while you see there is code to increment the index by 2: index+=2; This is done for efficiency since once we have identified a triple we know there is no way to form another triple with characters that are already part of another triple. Therefore we want to skip over them and just like the first bullet point we take advantage of the loop incrementing the index so we only need to increment by 2 and let the loop add the extra 1 later.
Finally we reach the end of the logic within the loop. This part you're already familiar with and that's the index++; which simply increments the position within the String that we're currently examining. Note that this works in tandem with the first bullet point. Take the example from the first bullet point of ".axyz". There is a period in index 0 and the character in index 1 is not another period so the logic from the first bullet point will increment index by 1, making it 1. At the end of the loop index is incremented again making it 2 thereby skipping over the period - at the start of the next loop index is 2, it was never 1 at the start of the loop.
Well, I hope this helps to explain how it all works and illustrate how to think about these sorts of problems. The basic principle is to visualize where your current element is and how you can use that to achieve your goal. At the same time think about what kinds of properties the different elements of your program have and how you can take advantage of them - such as the fact that once you identify a triple it is safe to skip over those characters because they have the property of only being usable once. As with any program you always want to try to create as many test inputs as you can to test all the weird boundary cases that might occur to ensure the correctness of your code. I realize you probably are not familiar with JUnit but it is a very useful tool and you might try researching the basics of using it when you have a little spare time, and the bonus is that if you use the Eclipse IDE it has integrated JUnit functionality you can use.
thank you in advance for reading about my problem.
I am making a Hangman game where I want to print out a hidden version of the current word, but I would like to update it when a correct letter is guessed (on the right spot, too). I've been looking around StackOverflow but I just can't seem to find an explaination that I understand. If someone could help me, that would be great. :D
I'll post the for-loop that this is about. I can post more of the code if you might need it. The answerInput and guessInputString are both read from the console earlier in my code using a br.readLine() method.
for (int i = 0; i < inputAnswer.length(); i++) {
char inputAnswerChar = inputAnswer.charAt(i);
char guessInputChar =guessInputString.charAt(i);
if (inputAnswerChar == guessInputChar) {
replacementString.replace(replacementString.charAt(i), inputAnswerChar);
}
}
Thank you for any help that you can give me!
Your code is assuming that guessInputString and replacementString both have at least as many characters as inputAnswer, which is obviously wrong to assume, since your loop only guarantees that the i'th character exists for the inputAnswer String.
BTW, replacementString.replace(replacementString.charAt(i), inputAnswerChar) has no effect, since it cannot change the String it is executed for (since Strings are immutable). You must assign the new String returned by this method back to replacementString :
replacementString = replacementString.replace(replacementString.charAt(i), inputAnswerChar)
This question already has answers here:
Replace a character at a specific index in a string?
(9 answers)
Closed 8 years ago.
Can someone help me understand why I'm getting an "Unexpected Type Error"?
if(s.charAt(i-1) == ' '){
String sub = s.substring(i, s.indexOf(' ')+1);
for(int j = 0; j < sub.length()/2; j++){
char temp;
temp = sub.charAt(j);
sub.charAt(j) = sub.charAt(sub.length()-1-j);
sub.charAt(sub.length()-1-j) = temp;
sub = sub+" ";
complete = complete+sub;
}
}
I'm getting the error on lines 6 and 7. I can't figure out why and I'd appreciate the help!
charAt() returns the character. It is not a left side operand aka you cannot assign a value to it.
Strings are immutable, which means you cannot change them (this seems to be your intention).
Instead: create a new String and add to that.
If this confused you, I try to elaborate a little: the assignment operator takes whatever is on the right and tries to shove it into whatever is on the left of it.
The problem here is that some things do not like it when you try to shove other things into them. You cannot put everything on the left that you want. Well, you can try:
"everything" = 5;
but this does not work, neither does this:
"everything" = 42;
Set aside what that last snippet failing implies to the universe and everything, your problem at hand is that charAt() is also one of those things that do not like it on the left side of the assignment operator.
I'm afraid there's no way to turn charAt() into one of those things that like it on the left side. A week after stranding on a deserted island without any plants but only solar powered refrigerators filled with steaks, this probably works:
vegetarian = meat;
Even though the vegetarian doesn't like it there, he'd accept his situation being on the left side of the = operator. He eats some steaks.
This does not hold true for what you are trying, though. There's no such deserted island for charAt().
In these lines you're trying to set the value of functions' return. This is illegal
sub.charAt(j) = sub.charAt(sub.length()-1-j);
sub.charAt(sub.length()-1-j) = temp;
as far as I see you're trying to change the characters of a String, but Strings are imutable objects. So you'll need to use a StringBuffer to set the values.
I'm writing small program, and want to get access to an element in array with the loop. And I need to increment "array index" variable for next iteration.
Here is the code:
winner[turn] = subField[(int)Math.floor(i / 10.0)][i % 10].equalsIgnoreCase("O") ? false : winner[turn];
turn++;
Is it possible to make one line of code from it?
PS: I'm trying to write less lines only for myself. It's a training for brain and logic.
Well, it can be done for sure:
winner[turn] = subField[(int)Math.floor(i / 10.0)][i % 10].
equalsIgnoreCase("O") ^ winner[turn++];
Look that there is not even ternary operator there.
But not because it is shorter it is better (and certainly not clearer). So I'd recommend you do it in these many lines:
String aSubField = subField[(int)Math.floor(i / 10.0)][i % 10];
if (aSubField.equalsIgnoreCase("O"))
winner[turn] = false;
turn++;
Look, even there is no need to assign the value in case the comparison yields false.
[edit]
YAY! Just found my XOR was wrong ... that's just the problem with golf, it tooks a lot of time to figure it is wrong .... (in this case, if the cond is true but the previous value is false, it won't work).
So let me golf it other way :)
winner[turn] = !subField[i/10][i%10].equalsIgnoreCase("O") & winner[turn++];
Note the ! and the &
[edit]
Thanks to #Javier for giving me an even more compact and confuse version :) this one:
winner[turn++] &= !subField[i/10][i%10].equalsIgnoreCase("O");
Let's break it down a bit. What you have is:
winner[turn] = (some condition) ? false : (expression involving turn)
(increment turn)
Well, why not increment turn in the array access? That means it'll be incremented by the time you evaluate expressions on the right hand side, but you can easily adjust it back to its previous value as needed.
winner[turn++] = (some condition) ? false : (expression involving (turn - 1) )