Behavior of foreach when setting new chars in a String - java

I just read a question about chars and I had a doubt about it so I started to try some code... I'm trying to set all chars from a String one by one using a loop, I've tried with for and the "forEach" version of it, these are my tests:
String testString = "testing";
char[] array = testingString.toCharArray();
Then the loops:
for(int i = 0; i < array.length; i++) {
array[i] = 'x';
}
And this is the output for that loop: (the expected one)
"xxxxxxx"
But then I've tried with the another "for" format:
for(char c: array) {
c = 'x';
}
And it didn't work for me.. the output was the same String ("testing"). I'm misunderstanding the behavior of the for each? Why is the 2nd loop not working the same as the first one? I've used that loop format a lot of times but I can't understand why is not working in this case. I'm not familiar with the char type, maybe I'm missing something about it.

As documented in JLS ยง14.14.2. The enhanced for statement, the following loop:
for(char c: array) {
c = 'x';
}
is equivalent to the following basic for statement:
for (int #i = 0; #i < array.length; #i++) {
char c = array[#i];
c = 'x';
}
As you can see, changing c will not affect the array.

That's because you are edditing the character, not the corresponding charAt the inception String.
Probably, you should take the position of these char at the string and setting it up.

Related

Replace entire char array with different char

I'm very new to programming and I've spent some time looking for a way to do this that I can understand. I'm making a hangman game in java, it's all text based, and I've got almost the entire thing done. All I need is to replace a character array that holds the value of a random word to be replaced with dashes. So if the word was "java" I need to change that character array to "----". Since the word is chosen at random from a list, I have to find a way to use the length of the word to apply those dashes, but I'm not sure how.
Any help is appreciated!
A simple way to replace all the characters by '_' would be :
char[] charArray = {'W','O','R','D'};
Arrays.fill(charArray, '_');
I will give you an example based on what you have provided so far with java and ----:
public class Program {
public static void main(String[] args) {
String value = "java";
char[] array = value.toCharArray();
// Convert string to a char array.
for(int i = 0; i < value.length(); i++)
{
array[i] = '-';
}
// Loop over chars in the array.
for (char c : array) {
System.out.print(c);
}
}
}
OK, a few things that may be helpful in solving this task:
If you have a String you can easily get the length of that String like this:
String word = "java";
int lengthOfWord = word.length();
You can easily edit the contents of an array by accessing the individual elements:
char[] array = new char[4];
array[0] = '-';
array[1] = '_';
array[2] = '-';
array[3] = '_';
If you want to do something repeatedly and know how often you want to do that, using a for-loop is often a great idea. And you can use the counter within the loop. So for example:
int sum = 0;
for(int i = 0; i < 10; i++) {
sum += i;
}
So, combine those pieces of information and you can replace every element of that array. :-)

Replacing characters in Strings Java [duplicate]

This question already has an answer here:
String Replace not working as I think it should [duplicate]
(1 answer)
Closed 8 years ago.
I need to cycle through each character in a string, and based on the character that it is, replace it with another character from a char array.
Basically it looks like this:
for (int k = 0; k < messageToBeEncrypted.length(); k++)
{
switch(messageToBeEncrypted.charAt(k))
{
case 'a' : messageToBeEncrypted.replace('a', cryptList[0]);
break;
case 'b' : messageToBeEncrypted.replace('b', cryptList[1]);
break;
//it keeps going for each letter of the alphabet
}
System.out.println(messageToBeEncrypted);
}
The char array cryptList is a randomly generated alphabet, "fgtaixnebqwjkzumlydrovsphc" A is to be replaced by f, b by g, and so on. The problem I'm having is that this code prints the exact same message that was inputted, so if the messageToBeEncrypted was ab, instead of fg, it prints ab. How can I fix this? And if theres a clearer more concise way to accomplish this, do tell me. I realize 26 case statements probably isn't the best way to achieve my goal.
If you want to google it the keyword is Substitution cipher.
Here a short help:
String messageToBeEncrypted = "HelloWorld".toLowerCase();
String alphabet = "fgtaixnebqwjkzumlydrovsphcab";
StringBuilder sb = new StringBuilder();
int pos;
for (int k = 0; k < messageToBeEncrypted.length(); k++)
{
pos = (messageToBeEncrypted.charAt(k) - 97);
sb.append(alphabet.charAt(pos));
}
System.out.println(sb.toString());
The number 97 is the offset in the ASCII table... My example is just for small letters, but its not that hard to complete it for every letter.
This seems about what your after (minus the brutal switch statement):
public static String substitutionCipher(String str) {
//i'm assuming that this random alphabet is exactly 26 long, each unique
char[] crypt = "fgtaixnebqwjkzumlydrovsphc".toCharArray();
char[] chars = str.toCharArray();
for(int i = 0; i < chars.length; i++){
chars[i] = crypt[((int) chars[i]) - 97];
}
return new String(chars);
}
But to answer your original question, the reason it's not working is that Strings are immutable. By calling String.replace, it's not modifying your string; that's actually returning the modified version of the string and then just disappearing since you're not storing the return value.
You'd need to say:
for (int k = 0; k < messageToBeEncrypted.length(); k++)
{
switch(messageToBeEncrypted.charAt(k))
{
case 'a' :
messageToBeEncrypted = messageToBeEncrypted.replace('a', cryptList[0]);
break;
case 'b' :
messageToBeEncrypted = messageToBeEncrypted.replace('b', cryptList[1]);
break;
//etc.
}
System.out.println(messageToBeEncrypted);
}
but the way I mentioned previously is a little gentler on memory.

java.lang.ArrayIndexOutOfBoundsException error in java

So basically, I've created a contains method and it prints out the correct output I need but after it does this it gives me an error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at MethodTesting.main(MethodTesting.java:90)
Not sure why when it displays the output no worries? If anyone can give me an idea of what i'm doing wrong?? My code is below, i've tried adjusting the length to just length and length-1 as seen below. I've written the code in strings as opposed to char arrays however it wouldn't give me the right result. Hoping someone can shed some light perhaps?
//contains method
char[] st = "Hello World".toCharArray();
char[] substr = "llo".toCharArray();
for(int contains=0; contains<st.length-1; contains++){
if(substr[contains] == st[contains]){
for(int j=contains; j<st.length-1; j++){
if(st[j] == substr[j]){
}
else{
contains = -1;
}
}
}
System.out.println("CONTAINS");
System.out.println(contains);
}
Thanks, in advance!
Assuming that you are trying to search a substring of a string, this can be done in String.contains() method. If you are trying to implement the method yourself, then you have to change your code like this:
public static void main (String[] args)
{
char[] st = "Hello World".toCharArray();
char[] substr = "llo".toCharArray();
for(int contains = 0; contains < st.length - substr.length; contains++) {
int j;
for(j = 0; j < substr.length; j++) {
if(st[contains + j] != substr[j]) { // mismatch
break;
}
}
if (j == substr.length) // Every character in substr has been matched
System.out.println("Contains");
}
}
Your arrays aren't of equal length, yet in your second loop, you make an assumption that they are. contains can be a value higher than substr.length, and consequently, j will be, too.
To ensure that you don't step off the array while iterating, fix your bounds in your second loop.
Change for(int j=contains; j<st.length-1; j++) to for(int j=contains; j<substr.length; j++). This will ensure that your second loop is never executed if contains > substr.length, whereas it was executing as long as j < st.length()-1.
st array length and substr lengths are different.So the line
j<st.length-1; should be j<substr.length-1;

Java cannot find symbol for loops, logic problems?

Ok, my program in this specific section takes a line of data from a studentAnswer string array, the value of which would be something like TTFFTFTFTF. I am supposed to take this, and compare it against a key array, which might look like TFFFTFTFTF. A student takes a quiz, and my program calculates the points correct.
My intention is to use a separate points array to find the numeric grade for the student. The index of studentAnswer refers to a specific student. So studentAnswer[i] is TTFFTFTFTF. I use substrings to compare each individual T/F against the correct answer in key[], which would have a single T/F in each index. Then, if they are correct in their answer, I add a 1 to the correlating index in points[] and will later find the sum of points[] to find the numeric grade out of ten.
My problem here is that String origAns, used to define the student's original answer string, is getting a Java Error cannot find Symbol. I have tried placing the instantiation of origAns within each different for loop, but I can't get the program to work. Int i is meant to follow each specific student- I have four parallel arrays that will all log the student's ID number, numeric grade, letter grade, and original answers. So that is the intention of i, to go through each student. Then j should be used to go through each of these original student answer strings and compare it to the correct answer...
Logically, it makes sense to me where I would put it, but java doesn't agree. Please help me to understand this error!
for (int i = 0; i < studentAnswer.length; i++){
String origAns = studentAnswer[i];
for (int j = 0; j < key.length; j++){
if (origAns.substring[j] == key[j]){
//substring of index checked against same index of key
points[j] = 1;
}
if (origAns.substring[j] != key[j]){
points[j] = 0;
}
}
}
It sounds like you're trying to call the substring method - but you're trying to access it as if it were a field. So first change would be:
if (origAns.substring(j) == key[j])
Except that will be comparing string references instead of contents, so you might want:
if (origAns.substring(j).equals(key[j]))
Actually, I suspect you want charAt to get a single character - substring will return you a string with everything after the specified index:
if (origAns.charAt(j) == key[j])
... where key would be a char[] here.
You can also avoid doing the "opposite" comparison by using an else clause instead.
You should also indent your code more carefully, for readability. For example:
for (int i = 0; i < studentAnswer.length; i++) {
String origAns = studentAnswer[i];
for (int j = 0; j < key.length; j++) {
if (origAns.charAt(j) == key[j]) {
points[j] = 1;
} else {
points[j] = 0;
}
}
}
And now, you can change that to use a conditional expression instead of an if/else:
for (int i = 0; i < studentAnswer.length; i++) {
String origAns = studentAnswer[i];
for (int j = 0; j < key.length; j++) {
points[j] = origAns.charAt(j) == key[j] ? 1 : 0;
}
}
When you call a method in Java, you use parentheses () instead of brackets [].
Since substring is a method, you should call it like so
if (origAns.substring(j) == key[j])
A few other notes, you should use the equals method for comparisons (especially those comparisons involving Strings.)
if (origAns.substring(j).equals(key[j]))
Also, you should use charAt to extract a single character at some position in a string. substring(j) will return a string of characters starting at position j.
if (origAns.charAt(j).equals(key[j]))
Your explanation is very long and I have not read it from the beginning to end. But I can see at least one problem in your code:
if (origAns.substring[j] == key[j])
You are comparing strings using == instead of using method equals():
if (origAns.substring[j].equals(key[j]))
Substring is a function, not a member, of String objects. Check out the example at the top of this page:
http://docs.oracle.com/javase/6/docs/api/java/lang/String.html
Notice the use of parenthesis instead of brackets.
If you are using a String use charAt function
String studentAnswer = "TTFFTFTFTF";
for (int i = 0; i < studentAnswer.length(); i++)
{
char origAns = studentAnswer.charAt(i);
}
Else if you are using an char array then
char studentAnswer[] = "TTFFTFTFTF".toCharArray();
for (int i = 0; i < studentAnswer.length; i++){
char origAns = studentAnswer[i];
}

Which is a faster approach when iterating over strings in Java and why?

I was going through this question and one of the answers gave 2 options and said the first one is probably faster.
I would like to know why?
The 2 options mentioned in the answer are
for(int i = 0, n = s.length() ; i < n ; i++) {
char c = s.charAt(i);
}
or
for(char c : s.toCharArray()) {
// process c
}
The second answer suggested creates a char array and iterates over that. This mechanism is probably slower because of the additional overhead in creating the array prior to iterating over it; this overhead correlates with the length of the String.
A third method not mentioned in the answer you've referenced involves using a StringCharacterIterator; e.g.
CharacterIterator it = new StringCharacterIterator("Hello, World");
char c;
while ((c = it.next()) != CharacterIterator.DONE) {
System.err.println("Char: " + c);
}
However, my personal preference would be to use the first index-based solution in the answer you reference.
This is slow:
for(int i = 0, n = s.length() ; i < n ; i++) {
char c = s.charAt(i);
}
but can be faster like this:
int length = s.length();
for(int i = 0, n = length ; i < n ; ++i) {
char c = s.charAt(i);
}
where the differences:
- extracted the length to a variable to prevent recalculate this again and again.
- ++i is faster the i++ because does not need a temporal variable and garbage collection for it.
This is faster:
for(char c : s.toCharArray()) {
// process c
}
because it uses an iterator, and can be optimized well by Java compiler.
Iterators are always faster than simple loop (except some strange cases, where iterators do complex logic or resource hungry work)
But best to use that character iterator class in the other post here.
regards

Categories

Resources