Variable Scope and Visibility in Java - java

I am making a vacation and vacationdriver. The vacation file will serve as my blueprint and the driver will be the interactive portion of the program creating instances of vacation. I have everything working perfectly, but when I add in the one value I am missing to my print statement of line 47 of the vacation driver class I break the program.
I need to call the value for numSales which I thought is declared in line 42. When I type in numSales on line 47 at the beginning and in the middle of the output as shown I get a red line underneath and Eclipse tells me "numSales cannot be resolved into a variable". What do I need to do to get the value of numSales to be actively output in the print statement on line 47 of the vacation driver?
Here is the vacation class:
package cbrownmod4;
import java.text.NumberFormat;
public class Vacation {
// money formatting
NumberFormat money = NumberFormat.getCurrencyInstance();
// instance variables
private String vacationName;
private int numSold;
private Double priceEach;
// empty constructor
public Vacation() {
}
// partial constructor
public Vacation(String n, int s, double e) {
vacationName = n;
numSold = s;
priceEach = e = 0;
}
// updatSales method
public int updateSales() {
int updateSales = 0;
updateSales = updateSales + numSold;
return updateSales;
}
// totalValue method
public double totalValue() {
double totalValue = 0;
totalValue = totalValue + (numSold * priceEach);
return totalValue;
}
// toString method
public String toString() {
return vacationName + " has been sold " + numSold + " times for " + money.format(priceEach) +
" each for a total value of " + money.format(numSold*priceEach);
}
// getters and setters
public String getVacationName() {
return vacationName;
}
public void setVacationName(String vacationName) {
this.vacationName = vacationName;
}
public int getNumSold() {
return numSold;
}
public void setNumSold(int numSold) {
this.numSold = numSold;
}
public Double getPriceEach() {
return priceEach;
}
public void setPriceEach(Double priceEach) {
this.priceEach = priceEach;
}
}
Here is the vacation driver:
package cbrownmod4;
import java.text.NumberFormat;
import java.util.Scanner;
public class VacationDriver {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
NumberFormat money = NumberFormat.getCurrencyInstance();
// ask for the number of vacations and read it into numVacations
System.out.println("How many vacations are there?:");
int numVacations = input.nextInt();
// ask for the number of sales people and read it into numPeople
System.out.println("How many sales people are there?: ");
int numPeople = input.nextInt();
// beginning of loop for number of vacations
for(int i = 0; i < numVacations; i++) {
//ask for the name and price and read these into variables
System.out.println("What is the name of vacation #" + Integer.toString(i+1) + "?:");
String name = input.next();
System.out.println("How much does " + name + " cost?: ");
Double price = input.nextDouble();
// create a Vacation instance using the data obtained above
Vacation vacay = new Vacation (name, i, price);
// loop through the sales people
for(int j = 0; j < numPeople; j++) {
// ask for the sales for the current vacation and read it in
System.out.println("What are the sales for the current vacation by person #" + Integer.toString(j+1) + "?:");
int numSales = input.nextInt(); // line 42
// call updateSales with this number
numSales = vacay.updateSales();
} //end of inner loop
//where line 47 begins
//print out this vacation info
System.out.println(numSales + " trips to " + name + " were sold for " + money.format(price) + " for a total of " + money.format(numSales * price));
} //end of outer for loop
} //end of main
}
Due to requests to provide a snippet of the portion of the code not working here is the bit thats proving me problems:
//print out this vacation info
System.out.println(numSales + " trips to " + name + " were
sold for " + money.format(price) + " for a total of " +
money.format(numSales * price));
NOTE: If you take out the numSales in the snippet of the vacation driver, the program executes correctly but does not have the correct output because it is missing the necessary output variable
The clear concise question would be - why doesn't numSales work when I use it like shown in the short snippet. Again my problem is that Eclipse says "numSales cannot be resolved into a variable."

The problem is that you declare numSales inside a for {} block.
You need to declare it before the for block:
int numSales = 0; // set initial value in case numPeople is 0 and the loop never runs
// loop through the sales people
for(int j = 0; j < numPeople; j++) {
// ask for the sales for the current vacation and read it in
System.out.println("What are the sales for the current vacation by person #" + Integer.toString(j+1) + "?:");
numSales = input.nextInt(); // line 42; this value is never used? it is overwritten below
// overwrite the never-used value from line 42??
numSales = vacay.updateSales();
} //end of inner loop
// now numSales is still visible, because it was declared on this same 'level' and not in an inner block
System.out.println("numSales: " + numSales);
The value set in line 42 is never used, and is overwritten in line 45, so you might as well call input.nextInt(); without setting the value to numSales.

Related

Need a way to associate strings with individual array elements

I am a complete beginner in programming and I'm working on a program for my mother that tracks her employee's monetary intake through a "horse race", with each employee having a horse and the program tracking their input to a UI made to look like a racetrack. After the help from my last inquiry, I've greatly simplified my mess of code but I am now faced with a new problem in that, after sorting the values largest to smallest, I have no way of associating the sorted values with the correct horse. I understand this explanation is confusing so I hope my code will do most of the talking for me here.
I honestly have no idea where to start with this. As I said in my last inquiry, I'm a complete beginner and severely lack the terminology or knowledge to find an answer here.
public class HorseRace {
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String horse1 = "#5 Gitty-Up";
String horse2 = "#7 Lady Simmons";
String horse3 = "#6 Burning Peanutbutter";
String horse4 = "#10 White Lightning";
String horse5 = "#3 Bella";
String horse6 = "#1 Meg The Stallion";
float h1val;
float h2val;
float h3val;
float h4val;
float h5val;
float h6val;
System.out.println("Input amount for " + horse1 + ":");
h1val = sc.nextFloat();
System.out.println("Input amount for " + horse2 + ":");
h2val = sc.nextFloat();
System.out.println("Input amount for " + horse3 + ":");
h3val = sc.nextFloat();
System.out.println("Input amount for " + horse4 + ":");
h4val = sc.nextFloat();
System.out.println("Input amount for " + horse5 + ":");
h5val = sc.nextFloat();
System.out.println("Input amount for " + horse6 + ":");
h6val = sc.nextFloat();
Float[] values = new Float[]{h1val, h2val, h3val, h4val, h5val, h6val};
Arrays.sort(values, Collections.reverseOrder());
//currently displays horses with the wrong number. Need a way to tie the horse name strings to their respective float elements
System.out.println("The current race progress is :");
System.out.println(horse1 + " with $" + values[0]);
System.out.println(horse2 + " with $" + values[1]);
System.out.println(horse3 + " with $" + values[2]);
System.out.println(horse4 + " with $" + values[3]);
System.out.println(horse5 + " with $" + values[4]);
System.out.println(horse6 + " with $" + values[5]);
}
}
my desired result is printing the correct horse with the correct value. For example, if I put that #5 brought in $11 and #7 brought in $14, the program would print that #7 is in the lead with $14 and #5 is in second place with $11.
Currently, the program always prints #5 as being in the lead with the highest value, #7 being in second with the second highest, etc.
I understand this is because I am hard calling the horse1-horse6 values meaning they don't change, but these are acting more as placeholders while I figure out how to associate the right horse with the right value
This is where you should create a Horse class and store the data as instances of Horse.
class Horse {
private String name;
private float value;
public String getName() { return name; }
public float getValue() { return value; }
public void setName(String name) { this.name = name; }
public void setValue(float value) { this.value = value; }
}
And then in your main method:
Horse[] horses = new Horse[6] {
new Horse(), new Horse(), new Horse(), new Horse(), new Horse(), new Horse()
};
horses[0].setName("#5 Gitty-Up");
horses[1].setName("#7 Lady Simmons");
horses[2].setName("#6 Burning Peanutbutter");
// and so on...
// you should use a for loop here instead of writing similar lines over and over again!
for (int i = 0 ; i < 6 ; i++) {
System.out.println("Input amount for " + horses[i].getName() + ":");
horses[i].setValue(sc.nextFloat());
}
Arrays.sort(horses, Comparator.comparingDouble(Horse::getValue).reversed());
System.out.println("The current race progress is :");
for (int i = 0 ; i < 6 ; i++) {
System.out.println(horses[i].getName() + " with $" + horses[i].getValue());
}
By using a class, you are essentially grouping data that belongs together, together. On the line Arrays.sort(horses, Comparator.comparingDouble(Horse::getValue).reversed());, I am sorting the whole array of horses together, by their values.
If the concepts of classes and objects are new to you, that just means it's time to learn about some new concepts. Classes and objects are very important.
Step 1, create a Horse class. It should have two fields, amount and name. It should implement Comparable because you want to sort it. And looking at your desired output, I would override toString().
class Horse implements Comparable<Horse> {
private String name;
private float amount;
public Horse(String name, float amount) {
this.name = name;
this.amount = amount;
}
#Override
public String toString() {
return String.format("%s with $%.2f", name, amount);
}
#Override
public int compareTo(Horse o) {
return Comparator.comparing((Horse h) -> h.amount)
.thenComparing((Horse h) -> h.name).compare(this, o);
}
}
Step 2, create an array of horseNames and iterate that populating an array of Horses (with amounts). Then sort it, and I would prefer Comparator.reverseOrder() to Collection.reverseOrder() when sorting an array.
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String[] horseNames = { "#5 Gitty-Up", "#7 Lady Simmons",
"#6 Burning Peanutbutter", "#10 White Lightning",
"#3 Bella", "#1 Meg The Stallion" };
Horse[] horses = new Horse[horseNames.length];
for (int i = 0; i < horseNames.length; i++) {
System.out.printf("Input amount for %s:%n", horseNames[i]);
float amt = sc.nextFloat();
horses[i] = new Horse(horseNames[i], amt);
}
Arrays.sort(horses, Comparator.reverseOrder());
System.out.println("The current race progress is :");
for (int i = 0; i < horses.length; i++) {
System.out.println(horses[i]);
}
}

Value stored in accessor method used in a for loop?

Essentially, I need to use the value from the getOriginalPrice method in a module.
When I simply put item.getOriginalPrice * .1, my code still compiles.
Not sure whats going on with this one.
Here is my code (not pasting the original class code unless needed).
import java.util.Scanner;
class InventoryApp {
public static void main(String[] args) {
String invNum = " ";
double ogPrice = 1;
int finishItems;
Inventory saleItem;
saleItem = new Inventory();
Scanner keyb = new Scanner(System.in);
System.out.println("Input the item numbers and original price for each item");
System.out.println("and I will show you the discounted price of each item");
System.out.println("for each day of the sale this week.");
System.out.println("Enter stop at the first prompt to end your list.");
System.out.println("Enter the item number of the item (Ex. 2b)");
invNum = keyb.next();
saleItem.setItemNumber(invNum);
while (!invNum.equals("stop")) {
System.out.println("Enter the item's original price (Ex 23.50");
ogPrice = keyb.nextDouble();
saleItem.setOriginalPrice(ogPrice);
printSaleData(saleItem);
System.out.println("Enter the item's item number");
invNum = keyb.next();
saleItem.setItemNumber(invNum);
}//end While
}//end main
public static void printSaleData(Inventory item) {
System.out.println("Item Number: " + item.getItemNumber());
for(int x = 1; x < 7; x = x + 1) {
item.getOriginalPrice() = item.getOriginalPrice -
(item.getOriginalPrice * .1);
System.out.println("Day: " + x + "\t" + "Price: $" + item.getOriginalPrice());
}//end for
}
}//end Class
Your printSaleDate method is not valid java. From your posted info, it's not clear what's your expected output.
But strictly speaking this is your posted method once fixed:
for (int x=1; x<7; x++) {
double discountedPrice = item.getOriginalPrice() * 0.1;
System.out.println("Day: " + x + "\tPrice: $" + discountedPrice);
}

School Assignment Multidimensional Array Trouble

I am currently working on an assignment for my Java programming class. I seem to have got myself in a bit of a bind. Any assistance in helping me realize what I am doing wrong would be greatly appreciated.
Assignment
Write a program that does the following:
Put the data below into a multi-dimensional array
Prompts the user for the company they would like employee salary statistics.
Write a method that returns the average employee salary as a double. Pass the company number and employee Wages to this method.
Write a method that returns the total employee salary as an int. Pass the company number and employee Wages to this method.
Write a method that returns the number of employees as an int. Pass the company number and employee Wages to this method.
In the main method call the other methods and out put the results.
Keep in mind that I am still new and struggling to understand some of the principles of programming.
When I run the program I am getting locations instead of method calculations (bad output):
Here is what I have so far:
package salaries;
import java.util.Scanner;
public class Salaries {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//declare, instantiate, and define value of multi array [3] [12]
double [][] mSalary = { { 49920, 50831, 39430, 54697, 41751, 36110,
41928, 48460, 39714, 49271, 51713, 38903},
{ 45519, 47373, 36824, 51229, 36966, 40332,
53294, 44907, 36050, 51574, 39758, 53847},
{ 54619, 48339, 44260, 44390, 39732, 44073,
53308, 35459, 52448, 38364, 39990, 47373}};
//declare, instantiate, and define value
//of single array for company names
//and output values to user for selection
String [] company = { "Alhermit", "Logway", "Felter" };
for( int i = 0; i < company.length; i++ )
System.out.println( "Company " + i + " : " +company[i] );
Scanner scan = new Scanner( System.in );
int cCompany;
do{
//ouput for user to select a company
System.out.print("Select company: (0)" +company[0]+ ", (1)"
+company[1]+ "; (2)" +company[2]+ " > ");
//scan user input into cCompany
cCompany = scan.nextInt();
//call number method
num nums = new num();
nums.number(mSalary, cCompany);
//call total method
total sum = new total();
sum.total(mSalary, cCompany);
//call average method
avg cAvg = new avg();
cAvg.average(mSalary, cCompany);
//output statistics to user on selected company
System.out.println( "You have selected the company " + company[cCompany] + ". " );
System.out.println( company[cCompany] + " has " + nums + " of employees." );
System.out.println( "A total employee salary of " + sum + "." );
System.out.println( "The average employee salary is " + cAvg );
}
while( cCompany < 0 || cCompany > 2);
}
}
//total class to calculate
//salary of user selected company
class total {
public static int total( double [][] mSalary, int cCompany ){
//assign variables
int sum = 0;
//for loop to calculate salary total of user input company
for( int j = 0; j < mSalary[cCompany].length; j++ ){
sum += mSalary[cCompany][j];
}
//return statement
return sum;
}
}
//average class to calculate
//average of user selected company
class avg {
public static double average( double [][] mSalary, int cCompany){
//assign variables
int cAvg = 0;
int sum = 0;
int count = 0;
//totals the values for the selected company by
//iterating through the array with count.
while( count < mSalary[cCompany].length){
sum += mSalary[cCompany][count];
count +=1;
}
cAvg = sum / mSalary[cCompany].length;
return cAvg;
}
}
//number class to calculate amount of
//employees in user selected company
class num {
public static int number( double [][] mSalary, int cCompany){
//assign variables
int nums = 0;
//number of employees based on length of colomn
nums = mSalary[cCompany].length;
return nums;
}
}
nums, sum, and cAvg are all instances of classes that you have, you're printing out the instances of those classes.
(By the way - you should change the name of these classes. Classes start with a capital letter. It differentiates them from variables.)
There are two things wrong with this.
You are instantiating a class which contains no data and has no toString method.
You're instantiating a class which only has static methods to return the data from. You don't need to instantiate the class at all; instead, just print the result of the method call.
That would change at least one of these calls to something like:
System.out.println( company[cCompany] + " has " + num.number(mSalary, cCompany); + " of employees." );
I leave the rest as an exercise for the reader.

I don't know why the variables are not initializing, all variables declared inside if statements aren't recognized

I can't figure out why the variables aren't being able to be printed
import java.text.*;
import java.io.*;
public class CoffeeBags
{
//CONSTANTS
public static final double SINGLE_PRICE = 5.5;
public static void main( String[]args)
throws IOException
{
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
//Display Message "Enter Number of Bags Ordered: "
System.out.print("Enter Number of Bags Ordered: ");
//Save input as string
String inputStr = br.readLine();
//Verify that input is integer
int numBags = Integer.parseInt(inputStr);
//Make sure number is above 0
if (numBags <= 0)
System.out.print("Please purchase at least one bag.");
if (numBags <= 0)
System.exit(0);
//Calculate purchase price
double purchasePrice = SINGLE_PRICE * numBags;
//Set numBagsLeft to numBags
int numBagsLeft = numBags;
//Determine Number of Large Boxes needed
if (numBagsLeft >= 20) {
int largeBoxCount = numBagsLeft / 20;
}
//Reinitialize Number of Bags to the remainder
int numBagsLeft2 = numBagsLeft % 20;
if (numBagsLeft2 >= 10) {
int mediumBoxCount = numBagsLeft2 / 10;
};
int numBagsLeft3 = numBagsLeft2 % 10;
if (numBagsLeft3 > 0 && numBagsLeft3 <= 5){
int smallBoxCount = 1;
} else {
int smallBoxCount = 2;
}
//Display
System.out.print("\n\nNumber of Bags ordered: " + numBags + " - " + purchasePrice
+ "\nBoxesUsed: "
+ "\n "+largeBoxCount+" Large - $+largeBoxCount*1.80
+ "\n "+mediumBoxCount+" Medium - $"+mediumBoxCount*1.00
+ "\n "+smallBoxCount+" Small - $"+smallBoxCount*.60
+ "\n\nYour total cost is: $"+largeBoxCount*1.80+mediumBoxCount*1.00+smallBoxCount*.60+purchasePrice;;)
}
}
Okay. So the code is supposed to take in a number of "Coffee Bags", and then, using a system of if statements, filter down through in order to find out how many boxes you will need to purchase in order to best save money. The problem I'm having is that the variables such as largeBoxCount and mediumBoxCount are not being initialized, and thus aren't able to be called when I go to print them.
I see some scoping issues. Variables declared inside of an if block are visible only inside the if block and not outside of it. Declare those variables before the if blocks and in the main method.
bar = 0; // declared before the if block, visible inside and out
if (foo) {
bar = 1; // this variable is visible outside of the if block
int baz = 1; // this variable is not visible outside of the if block
}
System.out.println("bar = " + bar); // legal
System.out.println("baz = " + baz); // illegal
You are declaring the variables inside the if statements, when the scope ends they are removed.

How to find average mark of an array list that comes from a csv file (JAVA) [closed]

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
I have a csv file that has a list with student id's, lastname, firstname, marks, phone number, etc. I have organized them into an array list so when you call stu[100].mark it will find the mark of the 100th student on the list of the csv file. There are 1000 students. I need to calculate the total overall average mark for all the students (each student only has one mark) I have put it in a loop, but it just prints out their mark. If you need more details, than I apologize.
Here is the code:
public class StudentRecs {
public static String user;
public int StuRec;
public static int numstu;
public static double average;
//public static StuRec[] stu;
static StuRec[] stu = new StuRec[1000];
public static void main(String[] args) throws IOException {
for (int i = 0; i < 1000; i++) {
stu[i] = new StuRec();
}
StuRec stu = new StuRec();
readFile(user);
menu();
}
public static String filename;
Scanner reader = new Scanner(filename);
public static Boolean readFile(String filename) throws IOException { //Constructor for filename
try {
Scanner userInput = new Scanner(System.in);
System.out.println("Type R To Read a File or Type Default for the default file");
user = userInput.nextLine();
if (user.equalsIgnoreCase("r")) {
user = userInput.nextLine();
}
filename = user;
if (user.equalsIgnoreCase("default")) {
filename = "newreg2.csv";
}
Scanner input = new Scanner(new FileReader(filename));
while (input.hasNext()) {
in(input.nextLine());
numstu++;
}
input.close();
return true;
} catch (IOException e) {
System.err.println(e.getMessage());
}
return false;
}
public static void in(String reader) {
String splitter[];
splitter = reader.split(",");
stu[numstu] = new StuRec();
stu[numstu].studentID = splitter[0];
stu[numstu].lastName = splitter[1];
stu[numstu].firstName = splitter[2];
stu[numstu].phoneNumber = splitter[3];
stu[numstu].courseCode = splitter[4];
stu[numstu].periodNumber = Integer.parseInt(splitter[5]); // parseInt turns a string of digits into an integer
stu[numstu].mark = Integer.parseInt(splitter[6]);
}
public static boolean menu() {
int total = 0;
String choice;
Scanner userInput = new Scanner(System.in);
System.out.println("=============================================");
System.out.println("Type R To Read Another File");
System.out.println("Type L To Print all File Records");
System.out.println("Type AA To Print The Average Of All The Marks");
choice = userInput.nextLine();
for (int i = 0; i < numstu; i++) {
if (choice.equalsIgnoreCase("L")) {
System.out.println(stu[i].lastName + ", " + stu[i].firstName + ", " + stu[i].studentID + ", " + stu[i].phoneNumber + ", " + stu[i].courseCode + ", " + stu[i].periodNumber + ", " + stu[i].mark);
}else if (choice.equalsIgnoreCase("R")){
} else if (choice.equalsIgnoreCase("AA")) {
total = total + stu[i].mark;
} else {
System.err.println("Unknown Key Try Again...");
}
average = total / 1000; // compute the average.
System.out.println(average);
} return menu();
}
}
Your average routine is computing incorrectly. It's simply taking the n'th mark and adding it to itself, divided by 1000. Since you're using integers, it will just round down, effectively giving you n'th mark + 0 for average on each iteration, leaving you with the last mark on the loop completion.
You need to keep adding to average, and divide by 1000 when you are done to get the value.
public static boolean menu() {
String choice;
Scanner userInput = new Scanner(System.in);
System.out.println("=============================================");
System.out.println("Type R To Read Another File");
System.out.println("Type L To Print all File Records");
System.out.println("Type AA To Print The Average Of All The Marks");
choice = userInput.nextLine();
for (int i = 0; i < numstu; i++) {
if (choice.equalsIgnoreCase("L")) {
System.out.println(stu[i].lastName + ", " + stu[i].firstName + ", " + stu[i].studentID + ", " + stu[i].phoneNumber + ", " + stu[i].courseCode + ", " + stu[i].periodNumber + ", " + stu[i].mark);
}else if (choice.equalsIgnoreCase("R")){
} else if (choice.equalsIgnoreCase("AA")) {
average += stu[i].mark; // keep adding to average
} else {
System.err.println("Unknown Key Try Again...");
}
}
// divide by zero protection
if ( numstu > 0 ) {
average = average/numstu; // compute the average. Always use the size in terms of a variable whenever possible.
System.out.println(average); // as noted below, if this is an integer value, < #of students computations will eval to 0.
// might be better to use double
}
else {
System.out.println("Oops! No students! :(");
}
return menu();
}
Note that your menu is a little inefficient, but the problem at hand should be solved.
Others have already pointed out the issue with not correctly calculating the sum of the scores, the numerator of the average calculation. I want to focus on the issue of the number of scores, the denominator of the average calculation.
Think real world. As others have mentioned, you cannot depend on the number of students in the file being fixed. File/class size can vary, so you cannot divide by a fixed number.
But neither can you depend on the number of scores being the same as the number of students, so you cannot simply divide by the number of students in that file. A student might not have a mark for a particular assignment (sickness, excused absence, or whatever). A good routine will account for the possibility of blanks (as well as invalid values), and thus I would expect you to need to count the valid, non-blank marks at the same time that you total them so that you can take the appropriate quotient at the end.
This statement is the problem
average = stu[i].mark + stu[i].mark / 1000;
This does not accumulate a total. Instead try
total = total + stu[i].mark;
And then at the end, outside the loop
average = total / 1000;

Categories

Resources