Last line of for loop executed twice? - java

I'm a Java beginner and this is my first post.
I couldn't find anything exactly like my problem although this post seemed similar:
Why is this print line command executing twice?
but the answers didn't help me solve it.
I know it's probably something stupid but was hoping one of you folks might be able to point out to me why the last entry in the array named "matches" prints out twice.
Thanks in advance,
Robert.
Here is my code:
public String buildMatchList(Match[] matches)
{
fixtures = "";
int i = 0;
for ( i = 0; i < numMatches; i++)
{
if (matches[i] != null)
{
fixtures += String.format("\n%-10.10s %10.9s %15.14s", matches[i].getTeamA(), " Vs ", matches[i].getTeamB());
}
}
System.out.println(fixtures);
}
// -EDIT -
// numMatches set in this method
public void fillMatchArray(Team[] sortedTeams, int numTeams)
{
int homeTeam = 0;
int awayTeam = 0;
goalsA = 0;
goalsB = 0;
fixtures = "";
boolean played = false;
matches = new Match[MAX_NUM_GAMES];
for (homeTeam = 0; homeTeam < sortedTeams.length; homeTeam++)
for (awayTeam = homeTeam+1; awayTeam < sortedTeams.length; awayTeam++ )
{
String teamA = sortedTeams[homeTeam].getTeamName();
String teamB = sortedTeams[awayTeam].getTeamName();
matchFixtures = new Match(teamA, teamB, goalsA, goalsB, played);
{
fixtures += String.format("\n%-10.10s %10.9s %15.14s",
matchFixtures.getTeamA(), " Vs ", matchFixtures.getTeamB());
}
int i = 0;
matches[i] = matchFixtures;
numMatches++;
buildMatchList(matches);
}
}

If it prints out twice, the most likely explanation is that the last two entries are the same. There is a common bug where you add a mutable objects to a collection twice and while you think they are different, they are not.
I suggest you try stepping through the code in your debugger to see what it doing?
this is where stepping through the code would be helpful. You are setting the first element of the array each time as i is always 0
int i = 0;
matches[i] = matchFixtures;
numMatches++;
change it to
matches[numMatches++] = matchFixtures;

Match is an object, so matches is a called a reference type. When you compare those to null, it will compare the reference to null, which it never is, so it will always return true.
If you want it to compare the contents of the object to null, you should replace matches[i] != null with matches[i].equals(null).

Related

Creating new object sets all existing ones to null (Java)

I have this method which is supposed to cut a String when it finds a symbos of + or - (it is part of a derivative calculator, so the idea is to get a bunch of small strings separated by + or - and then derivate them one by one. That's why i have that search for opened and closed parenthesis)
The problem is: When calling res = new String(); it will create a new String, but it will also set all the existing String objects in the array to null, which means the return of the method will always be an array with everything set to null (unless it does not find a + or - in the function).
Is there a way around this?
public static String[] cutString(String func)
{
int number_strings_res = 0;
int number_parenthesis = 0;
String[] res = new String[1];
res[0] = new String(func);
for(int i = 0; i < func.length(); i++)
{
if(func.charAt(i) == '+' || func.charAt(i) == '-')
{
for(int j = 0; j < i; j++)
{
if(func.charAt(j) == '(')
number_parenthesis++;
if(func.charAt(j) == ')')
number_parenthesis--;
}
if(number_parenthesis == 0)
{
res[number_strings_res] = "";
for(int j = 0; j < i; j++)
{
res[number_strings_res] += func.charAt(j);
}
number_strings_res++;
res = new String[number_strings_res + 1];
res[number_strings_res] = new String(Character.toString(func.charAt(i)));
number_strings_res++;
res = new String[number_strings_res + 1];
res[number_strings_res] = new String();
}
}
}
return res;
}
res = new String[number_strings_res + 1] allocates a new array and stores it to res. So that's the source of the immediate problem. You should probably be using a List, like ArrayList, instead if you don't know how long the collection will be.
When calling res = new String() ...
You have no such call, and it would not compile anyway.
'res' is declared as variable referring to a String array. When you execute res = new String[...] you naturally replace the entire array of Strings.
But I can't really figure out what you intend? Are you trying to extend the array? You can't, directly.
If you must use an array, look into Arrays.copyFrom. But an ArrayList would be easier.

Cannot update an array in Main from nested loops inside of Main. How can I assign it's value?

So, I am writing my program when suddenly, I run into a problem in which my three arrays print as null, 0 and null.
The program reads values from a file, and assigns them to the three arrays based on the iteration number.
Here is my code:
String mushroom []= new String [10];
int weight [] = new int [10];
String cooking[] = new String [10];
FileReader fr = new FileReader ("7J_Mushrooms.csv");
BufferedReader br = new BufferedReader (fr);
System.out.println("Mushroom\t\tWeight\t\tCooking\n=======================================================");
String line = "";
while ((line = br.readLine()) != null){
String [] temp = line.split(",");
for (int i = 0; i < temp.length; i++){
if(i == 0){
mushroom[i] = temp[i];
}
else if (i == 1){
weight[i] = Integer.parseInt(temp[i]);
}
else{
cooking[i] = temp[i];
}
}
}
// This bit just sorts them by weight in ascending order like a parallel array
for (int i = 0; i < weight.length-1; i++){
for (int j = 0; j < weight.length-1;j++){
if (weight[j] > weight[j+1]){
int temp = weight [j];
String tempMush = mushroom [j];
String tempCook = cooking [j];
weight[j] = weight[j+1];
mushroom[j] = mushroom[j+1];
cooking[j] = cooking[j+1];
weight[j+1] = temp;
mushroom[j+1] = tempMush;
cooking[j+1] = tempCook;
}
}
}
for (int i = 0; i < weight.length; i++){
System.out.print(mushroom[i] + "\t\t" + weight[i] + "\t\t" + cooking[i] + "\n");
}
When I print the values of the arrays inside of the for loop, the values are correct, however outside of the while loop the code is printed as null, null and 0. However, the last three values are printed but I am sure that is something to do with my problem.
Anyway, I believe it is to do with scope.
After some searching, I discovered that java is "Pass by Value" instead of "Pass by Reference". I do not really understand this principal, but to my understanding it affects methods in particular, but all of my code is under a single method -- main. I tried to use return inside the for loop and outside but it does not work either!
The way you are initially reading the values in seems quite off: you are placing the corresponding weight and cooking into different indices than the actual mushroom and you are using the index i in completely the wrong way. It should probably be
int i = 0;
while ((line = br.readLine()) != null){
String[] temp = line.split(",");
if(temp.length == 3)
mushroom[i] = temp[0];
weight[i] = Integer.parseInt(temp[1]);
cooking[i] = temp[2];
} else {
// some error handling
}
i++;
}
"When I print the values of the arrays inside of the for loop, the values are correct" is wrong - if you inspect temp the values are correct but mushroom, weight and cooking are never being filled correctly with your code.
Further note:
try using a custom class to hold the associated values instead of dealing with 3 arrays which magically have something to do with each other. Then sort an array of instances of that class
You are writing/over-writing only first three elements in each mushroom, cooking and weight.
As
i < temp.length, i <= 3

null pointer exception in java . [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Getting NullPointerException when it tries to access stones[0].length.
Please Help. I have already Initialized Stones Object.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Solution
{
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Scanner sc = new Scanner(System.in);
int times = sc.nextInt();
String stones[] = new String[times];
int score = 0;
int counter;
for(int tcase = 0; tcase < times; tcase++)
stones[tcase] = br.readLine();
int s = stones[0].length();
for (int i = 0; i < s ; i++) {
char j = stones[0].charAt(i);
counter = 0;
for (int k = 1; k < times; k++) {
char aa[] = stones[k].toCharArray();
for (int l = 0; l <aa.length ; l++) {
if(aa[l]==j)
{
counter++;
break;
}
}
if (counter==times-1) {
score++;
}
}
}
System.out.println(score);
}
}
Getting NullPointerException when I try to access stones[0].length(). Please help
When you submit your code through some automated service, it's running your code and it's failing because there's no System.in stream to provide any valid data. If you attempt to check for valid data before doing anything, it will catch this condition, and should let you submit, while still working properly on your laptop.
Try this:
Scanner sc = new Scanner(System.in);
int times = 0;
if ( sc.hasNext() ) { // check to make sure there's valid input first
times = sc.nextInt();
String stones[] = new String[times];
int score = 0;
int counter;
for(int tcase = 0; tcase < times; tcase++)
stones[tcase] = br.readLine();
if ( stones[0] != null ) { // check to make sure your array object exists
int s = stones[0].length();
for (int i = 0; i < s ; i++) {
char j = stones[0].charAt(i);
counter = 0;
for (int k = 1; k < times; k++) {
char aa[] = stones[k].toCharArray();
for (int l = 0; l <aa.length ; l++) {
if(aa[l]==j)
{
counter++;
break;
}
}
if (counter==times-1) {
score++;
}
}
}
}
}
The best way to make sense of these sort of problems is to use a debugger. But just for fun, let's do some code analysis...
int s = stones[0].length();
What can be generating a NullPointerException on this line? Well, the stones variable could be referring to null. We can easily rule this out, however, as the stones variable was assigned a new array instance further up in the code, and was never reassigned before reaching the problem line. The only other possibility is that the array component variable stones[0] refers to null.
Why might stones[0] be null? Well, for starters, it's initialized that way, so if you never assign to that component, then it will be null. However, the for loop that you have between array initialization and the problem line is iterating over all of the array components and initializing them, so every component will be assigned to. What else might be the problem?
The loop is assigning to each array component the value returned by br.readLine(). Could that return value possibly be null? Let's take a look at the javadocs...indeed, we find (emphasis added):
Returns: A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
And there you have it, it is certainly possible for stones[0] to be null! Now, if that is true, what does it mean? Well, it means that the very first call to br.readLine() returned null, signalling that it had reached the end of the stream. Which fits with what other answerers have noted - if System.in() is not available to provide any data, it would make sense to encounter the 'end of stream' condition right out of the gate.
It works with me, although I would not use two stream readers(a Scanner and a BufferedReader) for the same input.
What is the input that causes the exception?
PS. You should close the Scanner when it is not used.

Automaticly assigning values to array

Example:
wordsUsed[0][0] = "Word 1";
wordsUsed[0][1] = "0";
wordsUsed[1][0] = "Word 2";
wordsUsed[1][1] = "0";
String wordsCopy[][] = new String[2][2]
What I want is that wordsCopy[][] contains "Word 1" 2 times and "Word 2" also 2 times.
what I don't want is random amount of times of "Word 1" and random amount of times "Word 2"
wordsUsed[x][0]
^is a string with a word in it // x meaning 'any value'
wordsUsed[x][1]
^is standard "0"
wordsCopy[][]
^is a new array that will store 2 of each string in kleurGebruikt[x][0]
Basicly what I'm trying to accomplish is that the same string from [x][0] is never stored more than 2 times in the new array
What I got so far is that it will check the counter and if it is 0 it will copy the string over and then change the 0 to 1. if it gets the same string later it will see that it is already used once and copy it once more. Now my problem is that when it is copied twice, I'm unsure of how to make it skip this string and try a different one. Any help is appreciated
public void randomWords() {
Random r = new Random();
int rndm = 0;
for(int i=0; i<4; i++){
for(int j=0; j<5; j++){
rndm = r.nextInt(wordsUsed.length);
if (wordsUsed[rndm][1].equals("0")){
wordsCopy[i][j] = wordsUsed[rndm][0];
wordsUsed[rndm][1] = "1";
}
else if (wordsUsed[rndm][1].equals("1")){
wordsCopy[i][j] = wordsUsed[rndm][0];
wordsUsed[rndm][1] = "2";
}
else if (wordsUsed[rndm][1].equals("2")){
// at this point I need to go back to the start of the current
// if loop and make it so that a new random string is searched for
// without leaving a null element in the array.
}
}
Btw I'm sorry if the title isn't really good. I wasn't really sure how to explain myself in just a few words
Thanks
Use equals to compare strings. So, instead of-
if (kleurGebruikt[rndm][1] == "0"){
...
}
Should be-
if("0".equals(kleurGebruikt[rndm][1])){
...
}
EDIT:
I had hard time understanding your code because of those variable names and the design. Here's a way you can do it. If I were you I wouldn't use array for this task though-
Random r = new Random();
int rndm = 0;
String[][] wordsUsed = new String[2][2];
wordsUsed[0][0] = "Word 1";
wordsUsed[0][1] = "0";
wordsUsed[1][0] = "Word 2";
wordsUsed[1][1] = "0";
String wordsCopy[][] = new String[2][2];
int ctrR = 0;
int ctrC = 0;
boolean isDone = false;
while(!isDone) {
rndm = r.nextInt(wordsUsed.length);
if (wordsUsed[rndm][1].equalsIgnoreCase("0")
|| wordsUsed[rndm][1].equalsIgnoreCase("1")){
if (wordsUsed[rndm][1].equalsIgnoreCase("0")){
wordsCopy[ctrR][ctrC] = wordsUsed[rndm][0];
wordsUsed[rndm][1] = "1";
} else {
wordsCopy[ctrR][ctrC] = wordsUsed[rndm][0];
wordsUsed[rndm][1] = "2";
}
if(ctrC == wordsCopy.length - 1){
ctrR++;
ctrC = 0;
} else {
ctrC++;
}
}
if(ctrR == wordsCopy.length){
// If ctrR reached the length, we have successfully completed copying
isDone = true;
}
}
///////////////// RESULTS /////////////////
// Values of wordsUsed array
for(int i = 0; i < wordsUsed.length; i++){
for(int j = 0; j < wordsUsed.length; j++){
System.out.print(wordsUsed[i][j] + "\t");
}
}
System.out.println("\n");
// Values of wordsCopy array
for(int i = 0; i < wordsCopy.length; i++){
for(int j = 0; j < wordsCopy.length; j++){
System.out.print(wordsCopy[i][j] + "\t");
}
}
If I understood correctly, I think your problem is much easily solved if you use a Map. As the key you store the word ("Word1", "Word2", etc...) and as the value the number of times. For example (Java 7):
final Map<String, Integer> wordsUsed = new HashMap<>();
// Put word
final String curUsed = wordsUsed.get(wordToPut);
if (curUsed == null) { // New word, put counter to 1
wordsUsed.put(wordToPut, 1);
} else { // Old word, increase previous counter
wordsUsed.put(wordToPut, ++curUsed);
}
If you want to preserve insertion order, you can use a LinkedHashMap instead.
As a side note, arrays in Java are rarely the solution to your problem. JDK data structures provide almost always a much better and faster (code-writing speaking) solution.

Accurately retrieving data from a string

I have written a function in my program that allows me to retrieve strings and a separate string. ie, the string:
'copy "C:\Users\USERNAME\Desktop\file.bat" "C:\Users\"'
would result in having a string like: 'C:\Users\USERNAME\Desktop\file.bat' with the function getArgs(command, 0), and the other 'C:\Users\' with the function getArgs(command, 1).
The problem is that the function always seems to retrieve an empty string. Please be lenient on me, this is my first time using string manipulation functions in Java.
Notice: When I say empty I do not mean NULL, I mean "".
static String getArgs(String command, int argumentIndex) {
int start = 0;
int end = 0;
for (int i = 0; i <= argumentIndex; i++) {
start = command.indexOf("\"", end);
end = command.indexOf("\"", start);
if (i == argumentIndex) {
return command.substring(start, end);
}
}
return null;
}
Any ideas? Thanks.
#Darestium
According to your string it is clear that you've an empty space in between your paths. And also you've a problem with empty space.
To make it simple just split the string with space and the use the last 2 in the output.
Use `split(String arg)` in your case it is
String[] words=YOUR_STRING.split(" ");
for(int i=0;i<llength;i++)
{ if(words[i].startsWith("\"") && words[i].endsWith("\"")
{
word[i];YOUR DESIRED OUTPUT
}
}
Try the following correction. Keep in mind that your solution while work only if all the arguments in the command string are wrapped in quotes, even the ones without spaces. In the example you provided the first argument ('copy') must be also wrapped in quotes since you are using the quotes as delimiters.
static String getArgs(String command, int argumentIndex) {
int start = 0;
int end = -1;
for (int i = 0; i <= argumentIndex; i++) {
start = command.indexOf("\"", end+1)+1;
end = command.indexOf("\"", start+1);
if (i == argumentIndex) {
return command.substring(start, end);
}
}
return null;
}
Try this for a more generic solution which accepts arguments without quotes also
static String getArgs(String command, int argumentIndex) {
int start = 0;
int end = -1;
String delimiter = " ";
for (int i = 0; i <= argumentIndex && !command.equals(""); i++) {
if (command.startsWith("\"")) {
delimiter = "\"";
start = 1;
} else {
delimiter = " ";
start = 0;
}
end = command.indexOf(delimiter, start+1);
if (i == argumentIndex) {
end = (end==-1?command.length():end);
return command.substring(start, end).trim();
} else {
end = (end==-1?command.length():end+1);
command = command.substring(end).trim();
}
}
return null;
}

Categories

Resources