So the context is, I have a CS project where input is taken in either word or sentence form, and then it is translated to what The Swedish Chef from The Muppets would say. I decided to take the input as one line of string, and send that line into a parser, which in turn would build an array out of translations of the input's letters. The conditions for what gets changed are defined within. the current error I am getting: (while using "INPUT" as input)
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 1
at java.util.ArrayList.rangeCheckForAdd(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at SwedishTranslator.parseString(SwedishTranslator.java:62)
at SwedishTranslator.main(SwedishTranslator.java:12)
Currently it is supposed to just print the array, I wanted to worry about formatting after the fact.
The code:
Sorry for the walls of text but I can't find where the issue is exactly and I figured I would give it a shot here. Thanks in advance.
ind<=in.length() goes one step too far.
Use ind < in.length() or ind <= in.length() - 1
The error arrises on line 62 which I assume is in your big if else section.
Within there you have several ind++ calls. This increments the pointer you use in the loop. So if your code must go through several of these statements it will go beyond the array index.
Additionally you have an issue in the for loop as joval mentioned
Edit
The ++ unary operator increments the variable (-- decrements). Placing the ++ after the variable name (x++) will increment before evaluation, where ++x will increment after evaluation.
This is a common test question for CS students so I suggest you do some more research and practice regarding the operator.
You're making a couple of really understandable beginner mistakes here. Instead of explicitly fixing your code, I'll tell you about a couple of things that, if considered while reviewing and editing your code, will also fix your problem.
The documentation for String.charAt http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#charAt(int) throws an error when you attempt to access out-of-bounds items in the String. Make sure that you check that you're not attempting to look beyond the length of the String before you go calling charAt all willy-nilly! If you're currently "considering" the 'T' in "INPUT" and you go trying to look at the next two characters, Java will complain.
Second, and this is more of a general thing (though it does need to be fixed in your code above); the '++' operator doesn't do what you appear to think it actually does. When you do this: in.charAt(ind++)=='H', you may think you're just checking on the value at the next index, but you're actually advancing the index at the same time! The '++' operator is very handy, but it has a side affect that trips up a lot of beginners: it assigns itself + 1 to itself! That means that if you're on the 'I' in "INPUT" and somewhere within your loop you call ind++ once, you'll be on 'P' at the next iteration of your loop! When you see '++' remember that you're changing the value of the variable.
Good luck!
Related
I have an array list with some names inside it (first and last names). What I have to do is go through each "first name" and see how many times a character (which the user specifies) shows up at the end of every first name in the array list, and then print out the number of times that character showed up.
public int countFirstName(char c) {
int i = 0;
for (Name n : list) {
if (n.getFirstName().length() - 1 == c) {
i++;
}
}
return i;
}
That is the code I have. The problem is that the counter (i) doesn't add 1 even if there is a character that matches the end of the first name.
You're comparing the index of last character in the string to the required character, instead of the last character itself, which you can access with charAt:
String firstName = n.getFirstName()
if (firstName.charAt(firstName.length() - 1) == c) {
i++;
}
When you're setting out learning to code, there is a great value in using pencil and paper, or describing your algorithm ahead of time, in the language you think in. Most people that learn a foreign language start out by assembling a sentence in their native language, translating it to foreign, then speaking the foreign. Few, if any, learners of a foreign language are able to think in it natively
Coding is no different; all your life you've been speaking English and thinking in it. Now you're aiming to learn a different pattern of thinking, syntax, key words. This task will go a lot easier if you:
work out in high level natural language what you want to do first
write down the steps in clear and simple language, like a recipe
don't try to do too much at once
Had I been a tutor marking your program, id have been looking for something like this:
//method to count the number of list entries ending with a particular character
public int countFirstNamesEndingWith(char lookFor) {
//declare a variable to hold the count
int cnt = 0;
//iterate the list
for (Name n : list) {
//get the first name
String fn = n.getFirstName();
//get the last char of it
char lc = fn.charAt(fn.length() - 1);
//compare
if (lc == lookFor) {
cnt++;
}
}
return cnt;
}
Taking the bullet points in turn:
The comments serve as a high level description of what must be done. We write them aLL first, before even writing a single line of code. My course penalised uncommented code, and writing them first was a handy way of getting the requirement out of the way (they're a chore, right? Not always, but..) but also it is really easy to write a logic algorithm in high level language, then translate the steps into the language learning. I definitely think if you'd taken this approach you wouldn't have made the error you did, as it would have been clear that the code you wrote didn't implement the algorithm you'd have described earlier
Don't try to do too much in one line. Yes, I'm sure plenty of coders think it looks cool, or trick, or shows off what impressive coding smarts they have to pack a good 10 line algorithm into a single line of code that uses some obscure language features but one day it's highly likely that someone else is going to have to come along to maintain that code, improve it or change part of what it does - at that moment it's no longer cool, and it was never really a smart thing to do
Aominee, in their comment, actually gives us something like an example of this:
return (int)list.stream().filter(e -> e.charAt.length()-1)==c).count();
It's a one line implementation of a solution to your problem. Cool huh? Well, it has a bug* (for a start) but it's not the main thrust of my argument. At a more basic level: have you got any idea what it's doing? can you look at it and in 2 seconds tell me how it works?
It's quite an advanced language feature, it's trick for sure, but it might be a very poor solution because it's hard to understand, hard to maintain as a result, and does a lot while looking like a little- it only really makes sense if you're well versed in the language. This one line bundles up a facility that loops over your list, a feature that effectively has a tiny sub method that is called for every item in the list, and whose job is to calculate if the name ends with the sought char
It p's a brilliant feature, a cute example and it surely has its place in production java, but it's place is probably not here, in your learning exercise
Similarly, I'd go as far to say that this line of yours:
if (n.getFirstName().length() - 1 == c) {
Is approaching "doing too much" - I say this because it's where your logic broke down; you didn't write enough code to effectively implement the algorithm. You'd actually have to write even more code to implement this way:
if (n.getFirstName().charAt(n.getFirstName().length() - 1) == c) {
This is a right eyeful to load into your brain and understand. The accepted answer broke it down a bit by first getting the name into a temporary variable. That's a sensible optimisation. I broke it out another step by getting the last char into a temp variable. In a production system I probably wouldn't go that far, but this is your learning phase - try to minimise the number of operations each of your lines does. It will aid your understanding of your own code a great deal
If you do ever get a penchant for writing as much code as possible in as few chars, look at some code golf games here on the stack exchange network; the game is to abuse as many language features as possible to make really short, trick code.. pretty much every winner stands as a testament to condense that should never, ever be put into a production system maintained by normal coders who value their sanity
*the bug is it doesn't get the first name out of the Name object
I have a .toUpperCase() happening in a tight loop and have profiled and shown it is impacting application performance. Annoying thing is it's being called on strings already in capital letters. I'm considering just dropping the call to .toUpperCase() but this makes my code less safe for future use.
This level of Java performance optimization is past my experience thus far. Is there any way to do a pre-compilation, set an annotation, etc. to skip the call to toUpperCase on already upper case strings?
What you need to do if you can is call .toUpperCase() on the string once, and store it so that when you go through the loop you won't have to do it each time.
I don't believe there is a pre-compilation situation - you can't know in advance what data the code will be handling. If anyone can correct me on this, it's be pretty awesome.
If you post some example code, I'd be able to help a lot more - it really depends on what kind of access you have to the data before you get to the loop. If your loop is actually doing the data access (e.g., reading from a file) and you don't have control over where those files come from, your hands are a lot more tied than if the data is hardcoded.
Any many cases there's an easy answer, but in some, there's not much you can do.
You can try equalsIgnoreCase, too. It doesn't make a new string.
No you cannot do this using an annotation or pre-compilation because your input is given during the runtime and the annotation and pre-compilation are compile time constructions.
If you would have known the input in advance then you could simply convert it to uppercase before running the application, i.e. before you compile your application.
Note that there are many ways to optimize string handling but without more information we cannot give you any tailor made solution.
You can write a simple function isUpperCase(String) and call it before calling toUpperCase():
if (!isUpperCase(s)) {
s = s.toUpperCase()
}
It might be not significantly faster but at least this way less garbage will be created. If a majority of the strings in your input are already upper case this is very valid optimization.
isUpperCase function will look roughly like this:
boolean isUpperCase(String s) {
for (int i = 0; i < s.length; i++) {
if (Character.isLowerCase(s.charAt(i)) {
return false;
}
}
return true;
}
you need to do an if statement that conditions those letters out of it. the ideas good just have a condition. Then work with ascii codes so convert it using (int) then find the ascii numbers for uppercase which i have no idea what it is, and then continue saying if ascii whatever is true then ignore this section or if its for specific letters in a line then ignore it for charAt(i)
sorry its a rough explanation
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Given a string I #eat# #hamburgers# and a StringBuilder eat: [eat, consume, like] hamburgers: [hamburgers, spinach, bananas], I want to randomly replace the words within hashmarks with randomly chosen ones from their wordbanks, so that phrases such as I like bananas and I consume spinach will be generated. Code to randomly select another word, given a token (i.e. eat, hamburgers) has been written.
I need to use this regex #[^#]+# to find words within the initial string contained by hashmarks, pass them to the replace method, and then put their random correlates back inside the initial string. I tried using StringTokenizer, but realized it's not the tool for the job.
I need to somehow extract the first word within hashmarks and pass it to the method calling for its replacement before calling the method archetypeString(#[^#]+#, replacement) in such a way so that when the loop runs again, both the word grabber&passer-to method and the replacement method are then working with the second hashed word.
tokenizer dead-end:
StringTokenizer stt = new StringTokenizer(archetype);
while(stt.hasMoreTokens()){
String temp = stt.nextToken();
if(temp.charAt(0)=='#');
}
and the getPhrase method:
public List<String> getPhrases(StringBuilder fileContent, String token) {
StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(fileContent.toString()));
List<String> list = new ArrayList<String>();
try {
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
if (tokenizer.sval.equals(token)) {
tokenizer.nextToken(); // '['
do {
tokenizer.nextToken(); // go to the number
list.add(String.valueOf(tokenizer.sval));
} while (tokenizer.nextToken() == ',');
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
I need to use this regex #[^#]+# to find words within the initial string contained by hashmarks, pass them to the replace method, and then put their random correlates back inside the initial string. I tried using StringTokenizer, but realized it's not the tool for the job.
It is not clear from your question whether this is part of some sadistic homework assignment or just the first way you thought of to solve whatever problem you're trying to solve. This is not a regular expression problem any more than it's a StringTokenizer problem.
Look at String.format(), and the formatting capabilities of Formatter. I do not understand why you would ever need to know what the last string you generated was if your object is to generate the next one at random. Just pick a new random value and format it with String.format().
--
After reading your comment to this answer and looking at the question you referred to, I'm going to make a couple of recommendations.
(1) start with a simpler coding assignment or two, something without regular expressions. Make sure you absolutely understand the following concepts: instance variables. variable scope. public methods versus private methods. passing parameters to methods, and returning values from methods. You can do quite a bit with just that much. You don't need to study inheritance until you have all of those down cold, and I recommend that you do not try.
(2) for each coding assignment for at least your first 5, make sure you have written out what your program is to be provided as data and what output it is supposed to produce. List any constraints someone has given you separately (must use class X, must display error message, whatever).
(3) Put opening braces and closing braces on lines by themselves; match each opening brace with a closing brace indented the same amount. Indent code within each pair of braces another 2 or 3 spaces further to the right. This means that brace pairs inside other brace pairs will be indented further. I know this is not the way you see most code, and plenty of people will tell you that it is "wrong". But until you get comfortable with scope and whether a given place in your code is inside or outside a method or a loop, I think it best that you give yourself these extra visual cues. For someone not familiar with other ways of doing things, this is easiest.
(4) be careful of your terms when posting here. In the other question you refer to, you say it is about inheritance, but it uses "implements", indicating that it is implementing an interface, not inheriting from a class. It is confusing to those of us trying to help you if you get the terminology wrong.
(5) when you post here: post the entire program (these early assignments should all be under 100 lines total, no reason not to post all of it). Make sure it is properly indented; use spaces instead of tabs. In text, and maybe also in comments, point out the place in the code where you seem to have the problem (if you know). If there is an error message, post the entire error message (don't tell us what it is, and don't try to interpret it for us). Work on your code until you have a specific question: why do I get a compile error here? Why do I get (or fail to get) this output? The program outputs X but I expected Y, why is that? etc.
We're not a tutorial shop; most of us need instruction to learn to program, and you need to get most of that somewhere besides here. We are willing to help with your questions, given that your questions are specific and reasonable and you aren't expecting us to provide the instruction. By itself, "I'm lost and need help" is a bit beyond StackOverflow's normal way of operating.
I am looking at somebody else's code and I found this piece of code:
for (;;) {
I'm not a Java expert; what is this line of code doing?
At first, I thought it would be creating an infinite loop, but in the very SAME class this programmer uses
while(true)
Which (correct me if I'm wrong) IS an infinite loop. Are these two identical? Why would somebody change their method to repeat the same process?
Any insight would help,
Thanks!
Remember the three clauses of the for() are [1] initialization [2] termination and [3] increment. Since the termination clause is empty the loop never terminates. This is directly taken from C syntax.
Those two lines would have the same effect. I can't think of a good reason to use the first one unless you like to confuse people. I guess it's less characters.
they are entirely the same the only real difference would be either preference (the for construct can be typed marginally faster)
or the for indicates that is is some iteration that is broken out of by a break or return and a while loop indicates a repeating section of the same thing until a meaningful result appears
Sorry if my question sounds dumb. But some time small things create big problem for you and take your whole time to solve it. But thanks to stackoverflow where i can get GURU advices. :)
So here is my problem. i search for a word in a string and put 0 where that word occur.
For example : search word is DOG and i have string "never ever let dog bite you" so the string
would be 000100 . Now when I try to convert this string into INT it produce result 100 :( which is bad. I also can not use int array i can only use string as i am concatinating it, also using somewhere else too in program.
Now i am sure you are wondering why i want to convert it into INT. So here my answer. I am using 3 words from each string to make this kind of binary string. So lets say i used three search queries like ( dog, dog, ever ) so all three strings would be
000100
000100
010000
Then I want to SUM them it should produce result like this "010200" while it produce result "10200" which is wrong. :(
Thanks in advance
Of course the int representation won't retain leading zeros. But you can easily convert back to a String after summing and pad the zeros on the left yourself - just store the maximum length of any string (assuming they can have different lengths). Or if you wanted to get even fancier you could use NumberFormat, but you might find this to be overkill for your needs.
Also, be careful - you will get some unexpected results with this code if any word appears in 10 or more strings.
Looks like you might want to investigate java.util.BitSet.
You could prefix your value with a '1', that would preserve your leading 0's. You can then take that prefix into account you do your sum in the end.
That all is assuming you work through your 10 overflow issue that was mentioned in another comment.
Could you store it as a character array instead? Your using an int, which is fine, but your really not wanting an int - you want each position in the int to represent words in a string, and you turn them on or off (1 or 0). Seems like storing them in a character array would make more sense.