/*This is a program that calculates Internet advertising rates based on what features/options you choose.
*
*
*/
import java.util.Scanner;
public class InternetAdvertising
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int numberOfWords;
//I assigned 0 values to both as Eclipse suggested
float textCost = 0;
float linkCost = 0;
float graphicCost;
//<=25 words is a flat fee of $.40 per word plus Base fee of $3.00
final float TEXT_FLAT_FEE = 0.40F;
final float TEXT_BASE_FEE = 3.00F;
//<=35 words is $.40 for the first 25 words and
//an additional $.35 per word up to and including 35 words plus Base fee of $3.00
final float LESS_OR_EQUAL_THAN_THIRTYFIVE = 0.35F;
//Over 35 words is a flat fee of $.32 per word with no base fee
final float MORE_THAN_THIRTYFIVE = 0.32F;
System.out.println("Welcome!");
System.out.print("Enter the number of words in your ad: ");
numberOfWords = in.nextInt();
if (numberOfWords <= 25)
{
textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * numberOfWords);
}
else if (numberOfWords <= 35)
{
textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * 25) + (numberOfWords - 25) * LESS_OR_EQUAL_THAN_THIRTYFIVE;
}
else if (numberOfWords > 35)
{
textCost = numberOfWords * MORE_THAN_THIRTYFIVE;
}
String addLink, advancePay;
char link, advPay;
final float LINK_FLAT_FEE = 14.95F;
final float THREE_MONTH_ADV_DISCOUNT = 0.10F;
System.out.print("Would you like to add a link (y = yes or n = no)? ");
addLink = in.next();
link = addLink.charAt(0);
link = Character.toLowerCase(link);
if (link == 'y')
{
System.out.print("Would you like to pay 3 months in advance " + "(y = yes or n = no)? ");
advancePay = in.next();
advPay = advancePay.charAt(0);
advPay = Character.toLowerCase(advPay);
switch (advPay)
{
case 'y':
linkCost = (3 * LINK_FLAT_FEE) - (3 * LINK_FLAT_FEE) * THREE_MONTH_ADV_DISCOUNT;
break;
case 'n':
linkCost = LINK_FLAT_FEE;
break;
}
}
else
{
linkCost = 0;
}
String addGraphic;
char graphic;
System.out.print("Would you like to add graphics/pictures” + “(S = Small, M = Medium, L = Large or N = None)? ");
addGraphic = in.next();
graphic = addGraphic.charAt(0);
graphic = Character.toUpperCase(graphic);
graphic = Character.toLowerCase(graphic);
switch (graphic)
{
case 's':
graphicCost = 19.07F;
break;
case 'm':
graphicCost = 24.76F;
break;
case 'l':
graphicCost = 29.33F;
break;
default:
graphicCost = 0;
}
float gst, totalBeforeGst, totalAfterGst;
final float GST_RATE = 0.05F;
totalBeforeGst = textCost + linkCost + graphicCost; //textCost & linkCost would not initialize
gst = totalBeforeGst * GST_RATE;
totalAfterGst = totalBeforeGst + (totalBeforeGst * GST_RATE);
System.out.printf("\t\t%-16s %11s\n", "Category", "Cost");
System.out.printf("\t\t%-16s %11.2f\n", "Text", textCost); //linkCost would not initialize
System.out.printf("\t\t%-16s %11.2f\n", "Link", linkCost); //textCost would not initialize
System.out.printf("\t\t%-16s %11.2f\n", "Graphic", graphicCost);
System.out.printf("\t\t%-16s %11.2f\n", "Total", totalBeforeGst);
System.out.printf("\t\t%-16s %11.2f\n", "GST", gst);
System.out.printf("\t\t%-16s %11.2f\n", "Total with GST", totalAfterGst);
}
}
I'm almost done with this code and Eclipse suggests that I assign 0 values to textCost and linkCost. Is there any other way to go around this problem. If I don't assign 0 values they get an error (The local variable XXX may not have been initialized). Can someone explain to me why this happens even though I have both variables assigned with equations?
Thanks.
EDIT: I did as suggested and declared the variables only when I'm going to need it. I also added some comments.
Three suggestions before I delve any deeper into the code:
Declare variables as late as you can to make it easier to understand the code.
Refactor this giant method - it's unreadably huge at the moment.
Make the constants static final fields. They're not related to any particular call to the method, so they shouldn't be local variables.
Now as to the actual question, the simplest way is to make sure that every possible flow actually does assign a value or throw an exception. So for textCost, change your code to:
if (numberOfWords <= 25)
{
textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * numberOfWords);
}
else if (numberOfWords <= 35)
{
textCost = TEXT_BASE_FEE + (TEXT_FLAT_FEE * 25) + (numberOfWords - 25) *
LESS_OR_EQUAL_THAN_THIRTYFIVE;
}
else // Note - no condition.
{
textCost = numberOfWords * MORE_THAN_THIRTYFIVE;
}
For linkCost, change your switch statement to something like:
switch (advPay)
{
case 'y':
linkCost = (3 * LINK_FLAT_FEE) -
(3 * LINK_FLAT_FEE) * THREE_MONTH_ADV_DISCOUNT;
break;
case 'n':
linkCost = LINK_FLAT_FEE;
break;
default:
throw new Exception("Invalid value specified: " + advPay);
}
Now you may not want to throw an exception here. You might want to loop round again, or something like that. You probably don't want to use just bare Exception - but you should think about the exact exception type you do want to use.
It's not always possible to do this. The rules by the compiler to determine definite assignment are relatively straightforward. In cases where you really can't change the code to make the compiler happy like this, you can just assign a dummy initial value. I'd recommend trying to avoid this wherever possible though. In your first case, the value really would always be assigned - but in the second case you really weren't giving a value when advPay was neither 'y' nor 'n' which could lead to a hard-to-diagnose problem later on. The compiler error helps you spot this sort of problem.
Again though, I strongly suggest you refactor this method. I suspect you'll find it a lot easier to understand why things aren't definitely assigned when there's only about 10 lines of code to reason about in each method, and when each variable is declared just before or at its first use.
EDIT:
Okay, the radically refactored code is below. I'm not going to claim it's the best code in the world, but:
It's more testable. You could easily write unit tests for each part of it. printAllCosts isn't terribly easily testable, but you could have an overload which took a Writer to print to - that would help.
Each bit of calculation is in a logical place. Links and graphics have a small set of possible values - Java enums are a natural fit here. (I'm aware they may well be beyond your current skill level, but it's good to see what will be available.)
I'm not using binary floating point numbers any more, because they're inappropriate for numbers. Instead, I'm using an integer number of cents everywhere and converting to BigDecimal for display purposes. See my article on .NET floating point for more information - it's all relevant to Java really.
The advert itself is now encapsulated in a class. You could add a lot more information here as and when you needed to.
The code is in a package. Admittedly it's all in one file at the moment (which is why only the EntryPoint class is public) but that's just for the sake of Stack Overflow and me not having to open up Eclipse.
There's JavaDoc explaining what's going on - at least for a few methods. (I would probably add some more in real code. I'm running out of time here.)
We validate user input, except for the word count - and we perform that validation in a single routine, which should be reasonably testable. We can then assume that whenever we've asked for input, we've got something valid.
The number of static methods in EntryPoint is slightly alarming. It doesn't feel terribly OO - but I find that's often the way around the entry point to a program. Note that there's nothing to do with fees in there - it's just the user interface, basically.
There's more code here than there was before - but it's (IMO) much more readable and maintainable code.
package advertising;
import java.util.Scanner;
import java.math.BigDecimal;
/** The graphic style of an advert. */
enum Graphic
{
NONE(0),
SMALL(1907),
MEDIUM(2476),
LARGE(2933);
private final int cost;
private Graphic(int cost)
{
this.cost = cost;
}
/** Returns the cost in cents. */
public int getCost()
{
return cost;
}
}
/** The link payment plan for an advert. */
enum LinkPlan
{
NONE(0),
PREPAID(1495), // 1 month
POSTPAID(1495 * 3 - (1495 * 3) / 10); // 10% discount for 3 months up-front
private final int cost;
private LinkPlan(int cost)
{
this.cost = cost;
}
/** Returns the cost in cents. */
public int getCost()
{
return cost;
}
}
class Advertisement
{
private final int wordCount;
private final LinkPlan linkPlan;
private final Graphic graphic;
public Advertisement(int wordCount, LinkPlan linkPlan, Graphic graphic)
{
this.wordCount = wordCount;
this.linkPlan = linkPlan;
this.graphic = graphic;
}
/**
* Returns the fee for the words in the advert, in cents.
*
* For up to 25 words, there's a flat fee of 40c per word and a base fee
* of $3.00.
*
* For 26-35 words inclusive, the fee for the first 25 words is as before,
* but the per-word fee goes down to 35c for words 26-35.
*
* For more than 35 words, there's a flat fee of 32c per word, and no
* base fee.
*/
public int getWordCost()
{
if (wordCount > 35)
{
return 32 * wordCount;
}
// Apply flat fee always, then up to 25 words at 40 cents,
// then the rest at 35 cents.
return 300 + Math.min(wordCount, 25) * 40
+ Math.min(wordCount - 25, 0) * 35;
}
/**
* Displays the costs associated with this advert.
*/
public void printAllCosts()
{
System.out.printf("\t\t%-16s %11s\n", "Category", "Cost");
printCost("Text", getWordCost());
printCost("Link", linkPlan.getCost());
printCost("Graphic", graphic.getCost());
int total = getWordCost() + linkPlan.getCost() + graphic.getCost();
printCost("Total", total);
int gst = total / 20;
printCost("GST", gst);
printCost("Total with GST", total + gst);
}
private void printCost(String category, int cents)
{
BigDecimal dollars = new BigDecimal(cents).scaleByPowerOfTen(-2);
System.out.printf("\t\t%-16s %11.2f\n", category, dollars);
}
}
/**
* The entry point for the program - takes user input, builds an
* Advertisement, and displays its cost.
*/
public class EntryPoint
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
System.out.println("Welcome!");
int wordCount = readWordCount(scanner);
LinkPlan linkPlan = readLinkPlan(scanner);
Graphic graphic = readGraphic(scanner);
Advertisement advert = new Advertisement(wordCount, linkPlan, graphic);
advert.printAllCosts();
}
private static int readWordCount(Scanner scanner)
{
System.out.print("Enter the number of words in your ad: ");
// Could add validation code in here
return scanner.nextInt();
}
private static LinkPlan readLinkPlan(Scanner scanner)
{
System.out.print("Would you like to add a link (y = yes or n = no)? ");
char addLink = readSingleCharacter(scanner, "yn");
LinkPlan linkPlan;
if (addLink == 'n')
{
return LinkPlan.NONE;
}
System.out.print("Would you like to pay 3 months in advance " +
"(y = yes or n = no)? ");
char advancePay = readSingleCharacter(scanner, "yn");
return advancePay == 'y' ? LinkPlan.PREPAID : LinkPlan.POSTPAID;
}
private static Graphic readGraphic(Scanner scanner)
{
System.out.print("Would you like to add graphics/pictures? " +
"(s = small, m = medium, l = large or n = None)? ");
char graphic = readSingleCharacter(scanner, "smln");
switch (graphic)
{
case 's': return Graphic.SMALL;
case 'm': return Graphic.MEDIUM;
case 'l': return Graphic.LARGE;
case 'n': return Graphic.NONE;
default:
throw new IllegalStateException("Unexpected state; graphic=" +
graphic);
}
}
private static char readSingleCharacter(Scanner scanner,
String validOptions)
{
while(true)
{
String input = scanner.next();
if (input.length() != 1 || !validOptions.contains(input))
{
System.out.print("Invalid value. Please try again: ");
continue;
}
return input.charAt(0);
}
}
}
linkCost is not initialized when link == 'y' and advPay is not 'y' or 'n'.
In other words, you get this error when the compiler can find a path through your code where a local variable is not initialized before it is used.
this happens because the assignment occurs inside a conditional, if the condition is not met, the assignment never occurs
to avoid the error you have to assign a value (the most common would be 0) outside the conditional.
The analysis Eclipse performs to determine whether the variable is assigned on every code path isn't intelligent enough to realize that the tests on numberOfWords will never all fail. Typically, because it's not possible to statically evaluate every possible condition, a compiler/syntax checker won't attempt to evaluate any of them. If you replaced the last "else if" with an "else" it should work, as at least one assignment to textCost will occur regardless of the conditions being tested.
Eclipse is warning you because your initializations are happening inside conditionals. If none of the conditions are satisfied, textCost will be uninitialized.
if (numberOfWords <= 25)
{
//assign a value to textCost
}
else if (numberOfWords <= 35)
{
//assign a value to textCost
}
else if (numberOfWords > 35)
{
//assign a value to textCost
}
Eclipse probably isn't recognizing that (numberOfWords <= 35) and (numberOfWords > 35) cover all possibilities.
You could either initialize it to 0 on declaration, or include an additional else {} which sets it to zero.
Similar explanation for the other variable.
the error message tells you, that those variables aren't always initialized. This is, because your initialization happens only under certain conditions (they are located in if-statements). Hope this helps..
Even though you know one of the 3 branches of the comparison with numberOfWords will be visited, the compiler doesn't know that. It will wrongly assume that it is possible to enter the else clause and the textCost variable will remain unitiliazed.
Similarly with the switch (advPay).
Even though you know that one of the two will be visited, the compiler doesn't.
Suggestion:
Remove the else if (numberOfWords > 35) make it just an else.
As for the switch (advPay), add a default case. Inside you can put a throw new AssertionError();.
A good way to avoid such issues is to set the to be assigned variable as final and uninitialized before the checks. This will force you to set a value before you can use/read it.
final textCostTmp;
if (condition1) {
textCostTmp = ...;
} else if (condition2) {
textCostTmp = ...;
}
// if you use textCostTmp here the compiler will complain that it is uninitialized !
textCost = textCostTmp;
To solve this DO NOT initialize the variable as you may miss the missing else case.
The only proper solution is to add an else case to cover all possible cases !
I consider it bad practice to initialize non final variables except for some rare scenarios like a counter in a loop.
The proposed approach will force you to handle all possible cases, now and in the future (easier to maintain).
The compiler is a bit stupid at times (cannot figure that numberOfWords > 35 is the else)...but the compiler is your ally not your enemy...
Related
I am trying to find out how can I check what system printed out at some point of iteration during the while loop statement.
I have this method:
/**
* This method counts how much money user inserted
* If it is not enough to buy chosen cup size it asks user to insert more
* Otherwise it checks if user does not need the change
* and collects money to machine based on cup size price
* This method gets the message from properties file by key identifies
* add.more.money - if not enough money is in machine
* user.paid.change - if user put too much to machine
* user.paid - if user paid the exact amount of money
* #param constantPrice - cup size price
* #return countMoney - how much user put to machine
*/
#Override
public String countMoneyForCupSize(double constantPrice) {
// constant - price depending on cup size
String countMoney = " ";
double sessionMoney = 0;
boolean flag = true;
while(flag) {
if(constantPrice > sessionMoney) {
System.out.println(MessageFormat.format(prop.getProperty("add.more.money"), (constantPrice-sessionMoney)));
double insertedCash;
try {
insertedCash = insertCash();
sessionMoney = sessionMoney + insertedCash;
if(insertedCash == 0) {
System.out.println(MessageFormat.format(prop.getProperty("end.procedure"), sessionMoney));
flag = false;
}
} catch (InvalidCoinException e) {
System.out.println(e.getMessage());
}
}
else {
double change = sessionMoney - constantPrice;
String makeCoffeeText = makeCoffee();
if(change > 0) {
countMoney = MessageFormat.format(prop.getProperty("user.paid.change"), makeCoffeeText, sessionMoney, change);
}
else {
countMoney = MessageFormat.format(prop.getProperty("user.paid"), makeCoffeeText, sessionMoney);
}
collectMoney(constantPrice);
flag = false;
}
}
return countMoney;
}
JUnit:
#org.junit.Rule
public final ProvideSystemProperty property1 = new ProvideSystemProperty("MoreEuro", "You need more: 0.5 euro");
#org.junit.Test
public void testCountMoneyForCupSize() {
System.out.println("---------------- Count Money For Cup Size -----------------");
double largePrice = 1.5;
double mediumPrice = 1;
double smallPrice = 0.75;
try {
when(machineSpy.insertCash()).thenReturn(1.0);
assertEquals(machineSpy.countMoneyForCupSize(largePrice), System.getProperty("MoreEuro"));
} catch (InvalidCoinException e) {
System.out.println(e.getMessage());
}
}
So I want to be clear that If user inserted 1 euro he still needs to insert half a euro more.
1) when(machineSpy.insertCash()).thenReturn(1.0);
Mocking private method invocation called by the tested public method is not necessarily a good thing as you should mock dependency and not the behavior of the object under test. If insertCash() has some specificities that have to be mocked, you should probably move out in another class.
2) About :
how to break loop at some point of iteration and check what system
printed out
Why not just executing a break instruction ?
3) machineSpy.countMoneyForCupSize(largePrice);
So I want to be clear that If user inserted 1 euro. He still need to
insert half euro more
Rather than trying to test the output written in the console that is not really testing the method behavior, I think that you should change the contract of countMoneyForCupSize(double).
In your actual version the method returns a formatted String. It should not.
Logic and rendering tasks are two distinct things.
Mixing both responsibilities violates the Single Responsibility principle (more than one reason to change a class).
Besides, it may prevent from testing the core logic of the method as in your case
Here :
if(change > 0) {
countMoney = MessageFormat.format(prop.getProperty("user.paid.change"), makeCoffeeText, sessionMoney, change);
}
else {
countMoney = MessageFormat.format(prop.getProperty("user.paid"), makeCoffeeText, sessionMoney);
}
You should rather create an instance of a custom class that contains all these data and return it rather than a String.
For example :
....
CountMoney countMoney = null;
...
if(change > 0) {
countMoney = new CountMoney(makeCoffeeText, sessionMoney, change);
}
else {
countMoney = new CountMoney(makeCoffeeText, sessionMoney);
}
...
return countMoney;
In your applicative code that invokes CountMoney countMoneyForCupSize() you could then call a rendered method (located in a rendering class) that performs the rendering, for example : String renderingCountMoney(CountMoney countMoney).
In this way your design would be better (each class and each method has well defined responsibilities) and you can unit test countMoneyForCupSize() without considerations about user text rendering.
You can check directly that insertCash was called multiple times. One way to do this is to to mock multiple calls to insertCash with thenReturn:
when(machineSpy.insertCash()).thenReturn(1.0, 0.5);
After that you can verify that insertCash was called exactly two times:
verify(machineSpy, times(2)).insertCash();
verifyNoMoreInteractions(machineSpy);
Check out this question for other options:
Using Mockito with multiple calls to the same method with the same arguments
If you still want to capture and test the output to System.out then you need to redirect standard output. This was already covered in earlier questions:
Redirect System.out.println
JUnit test for System.out.println()
My assignment is to find a way to display all possible ways of giving back change for a predetermined value, the values being scanned in from a txt file. This must be accomplished by Recursive Backtracking otherwise my solution will not be given credit. I will be honest in saying I am completely lost on how to code in the appropriate algorithm. All I know is that the algorithm works something like this:
start with empty sets.
add a dime to one set.
subtract '10' from my amount.
This is a negative number, so I discard that set: it is invalid.
add a nickel to another (empty) set.
subtract '5' from my amount.
This equals 2; so I'll have to keep working on this set.
Now I'm working with sets that already include one nickel.
add a dime to one set.
subtract '10' from my amount.
This is a negative number, so I discard that set: it is invalid.
repeat this with a nickel; I discard this possibility because (2 - 5) is also negative.
repeat this with a penny; this is valid but I still have 1 left.
repeat this whole process again with a starting set of one nickel and one penny,
again discarding a dime and nickel,
and finally adding a penny to reach an amount of 0: this is a valid set.
Now I go back to empty sets and repeat starting with a nickel, then pennies.
The issue is I haven't the slightest clue on how or where to begin, only that that has to be accomplished, or if any other solutions are apparent.
This is my code thus far:
UPDATED
import java.io.*;
import java.util.*;
import java.lang.*;
public class homework5 {
public static int penny = 1;
public static int nickle = 5;
public static int dime = 10;
public static int quarter = 25;
public static int halfDollar = 50;
public static int dollar = 100;
public static int change;
public static void main(String[] args) throws FileNotFoundException {
ArrayList<Integer> coinTypes = new ArrayList<Integer>();
Integer i;
File f = new File (args[0]);
Scanner input = new Scanner(f);
input.nextLine();
while(input.hasNextInt()) {
i = input.nextInt();
coinTypes.add(i);
}
change = coinTypes.get(coinTypes.size()-1);
coinTypes.remove(coinTypes.size()-1);
System.out.println("Found change"); //used for debugging
System.out.println("Change: " + change);
System.out.println(coinTypes);
}
boolean findChange(int change, List<Integer> coinTypes,
List<Integer> answerCoins) {
if(change == 0) {
return true;
}
if(change < 0) {
return false;
} else {
for(Integer coin : coinTypes) {
if(findChange(change - coin, coinTypes, answerCoins)){
answerCoins.add(coin);
return true;
}
}
List<Integer> answer = new ArrayList<Integer>();
boolean canFindChange = findChange(change, coinTypes, answer);
if(canFindChange) {
System.out.println(answer);
} else { System.out.println("No change found");
}
return false;
}
}
Here is the input file that I scan in
java homework5 hwk5sample1.txt
// Coins available in the USA, given in cents. Change for $1.43?
1 5 10 25 50 100
143
OUTPUT
Found change
Change: 143
[1, 5, 10, 25, 50, 100]
So using the numbers in my coinTypes ArrayList, I need a generic code algorithm to show all possible ways of receiving, for example, 143 ($1.43) back in change using the coins in the file with all pennies being the last way to show it.
Please do not think I want you to write me the algorithm, I am simply wanting help writing one otherwise I will learn nothing. Thank you all for any answers or help you can give it means a lot to me! Please let me know if i missed anything or you need more info
The example that you walk through seems to be mostly correct. The only error is this: again discarding a dime and nickel, which should be again discarding a *penny* and nickel (but I think that's just a typo.)
To write a recursive backtracking algorithm, it is useful to think of the recursive call as solving a subproblem of the original problem. In one possible implementation of the solution, the pseudocode looks like this:
/**
* findChange returns true if it is possible to make *change* cents of change
* using the coins in coinTypes. It adds the solution to answerCoins.
* If it's impossible to make this amount of change, then it returns false.
*/
boolean findChange(int change, List<Integer> coinTypes, List<Integer> answerCoins) {
if change is exactly 0: then we're done making change for 0 cents! return true
if change is negative: we cannot make change for negative cents; return false
otherwise, for each coin in coinTypes {
// we solve the subproblem of finding change for (change - coin) cents
// using the recursive call.
if we can findChange(change - coin, coinTypes, answerCoins) {
// then we have a solution to the subproblem of
// making (change - coins) cents of change, so:
- we add coin to answerCoins, the list of coins that we have used
- we return true // because this is a solution for the original problem
}
}
//if we get to the next line, then we can't find change for any of our subproblems
return false
}
We would call this method with:
List<Integer> answer = new ArrayList<Integer>();
boolean canFindChange = findChange(change, coinTypes, answer);
if(canFindChange) {
System.out.println(answer); // your desired output.
}
else {
System.out.println("Can't find change!");
}
I'm stuck on an assignment, largely due to an extreme lack of examples or even relevant diagrams from my textbook and class material.
The reason I structured the program the way I did is because I'm required to use 4 methods: a main method that executes all the other methods, a retrieve input method, a check method, and a display method. I love to hear about best practices, but I'm forced to code like this.
My main problem is the abstract classes I have. Any variables I write in one method won't be resolvable in another, I don't know how to make the variables global.
secondly, the code does not compile, the example I've found doesn't have a classic main, i don't really know how to make main implement methods, or make the compiler happy with abstraction.
also no clue on how to take my boolean result and use that to display the results in the display method. yes its asinine, I'd rather just do it in the check method.
all i know for sue is that my "logic" so far works. i think. any help to point me in the right direction would be very much appreciated. if thee is a way to do this without abstract classes i'd love to hear it, i think the abstraction is unnecessary.
well here's my monster so far:
import javax.swing.JOptionPane;
interface Palindrome {
void retrieveInput(String[] args);
boolean Check(String s);
void display();
}
abstract class Sub_Palindrome implements Palindrome {
public void retrieveInput(String[] args)
{
String Uinput;
int number1;
int digit1; // first digit
int digit2; // second digit
int digit3;
int digit4; // fourth digit
int digit5; // fifth digit
Uinput = JOptionPane.showInputDialog("Enter A 5 Digit Integer");
try { //Sanitize user input, make sure input entered is a number
number1 = Integer.parseInt(Uinput);
} catch (NumberFormatException String) {
JOptionPane.showMessageDialog(null, "Input invalid, please enter an integer",
"///-D-A-T-A---E-R-R-O-R-\\\\\\", JOptionPane.ERROR_MESSAGE);
return;
}
if (number1 < 10000 || number1 > 99999) { //Sanitize user input, make sure the given number is between 10000 and 99999
JOptionPane.showMessageDialog(null,
"The number entered must be between 10000 and 99999",
"///-D-A-T-A---E-R-R-O-R-\\\\\\", JOptionPane.ERROR_MESSAGE);
return;
}
}
public boolean Check(String s)
{
digit1 = number / 10000;
digit2 = number / 1000 % 10;
digit3 = number % 1000 / 100 % 10; // is the third digit even necessary?
digit4 = number % 10000 % 1000 % 100 / 10;
digit5 = number % 10000 % 1000 % 100 % 10;
if (digit1 == digit5 && digit2 == digit4)
return true;
else
return false;
}
public void display()
{
//display output text based upon result from IsPalinDrome
//after displaying result, start from the beginning and ask user to input data again
}
}
Move the variables outside methods and put directly in class scope
Writing main method is the first thing you learn in java. Look into your tutorial again
You can use a boolean variable boolean displayCheck = false; and set the same
And one question from my side: If your code doesn't compile what makes you feel that the logic is correct?
I'm starting to get blind looking at my code and my brain is about to overheat. I'm new when it comes to programming.
public class RecyclingSystem {
public static void main(String[] args) {
System.out.println("Please put in a valid bottle");
Scanner sc = new Scanner(System.in);
while ( sc.nextInt() != -1) {
if (sc.nextInt(char a) = getaBottle);
int bottleAcount++;
} else if { (sc.nextInt(char b) = getbBottle);
int bottleBcount++;
} else if { (sc.nextInt(char c) = getcBottle);
int bottleCcount++;
} else { throw new EmptyStackException();
System.out.println("Bottle not recognized");
}
System.out.println("The total number of bottles is " + totalBottlecount);
System.out.println();
System.out.println("The total amount returned is " + sumOfBottles );
}
sc.close();
}
}}
public class Bottle {
private static final double A_BOTTLE = 1.0;
/**
* #return the aBottle
*/
public static double getaBottle() {
return A_BOTTLE;
}
/**
* #return the bBottle
*/
public static double getbBottle() {
return B_BOTTLE;
}
/**
* #return the cBottle
*/
public static double getcBottle() {
return C_BOTTLE;
}
private static final double B_BOTTLE = 1.5;
private static final double C_BOTTLE = 3.0;
}
public class EmptyStackException extends Exception {
}
public class bottleCount {
int bottleAcount = 0;
int bottleBcount = 0;
int bottleCcount = 0;
int totalBottleCount = bottleAcount + bottleBcount + bottleCcount;
}
I have seperate classes for the getbottle, totalBottlecount and bottlecount variables.
I want to make a user-input based recycling system simulator, if that makes any sense, with 3 different types of bottles, which are assigned different values, a total bottle count and the sum of the values of the 3 bottle types combined.
I get several compiler errors and I have spend HOURS trying to resolve them all, but every time I do, new errors occur and now I get a "coders-block".
I get asked to delete the ++ tokens, the compiler cannot resolve my variables and syntax errors. I would really appreciate some insight, since I'm only ~3weeks into java programming.
UPDATED: Compiler errors exact copy pasta
Multiple markers at this line
- Syntax error, insert ")" to complete Expression
- Duplicate method nextInt(char) in type RecyclingSystem
- Syntax error, insert "}" to complete Block
- Syntax error, insert "AssignmentOperator Expression" to complete Assignment
- Return type for the method is missing
- Syntax error on tokens, delete these tokens
- The left-hand side of an assignment must be a variable
- Syntax error, insert "AssignmentOperator Expression" to complete Expression
- The left-hand side of an assignment must be a variable
- Syntax error, insert ";" to complete BlockStatements
- Syntax error on tokens, delete these tokens
- Syntax error on token ")", { expected after this token
- Syntax error, insert ";" to complete Statement
int bottleAcount++;
In java you need to declare the local variable like
type name = intial value;
then do any operation on that like increament or decrement.
In youe case declar the variable before while loop with zero as intial value like
int bottleAcount = 0;
then inside while increament it by 1, like bottleAcount++;
or
bottleAcount += 1;
So... If this is all the code there are many problems and what can I recommend in the beginning - go back to some basic Java programming course.
Let's look at one of the first lines:
if (sc.nextInt(char a) = getaBottle);
Firstly, it's a condition, and you are assigning the value of a getaBottle to the sc.nextInt(char a).
Secondly, nextInt(char a) looks like method declaring, not like a method call.
Thirdly, getaBottle is never declared before
Fourthly, you have a getaBottle() method in a Bottle class, which you probably want to use instead of getaBottle which is (should) be a variable
...etc., etc.
This code is not even valid Java code. It's hard to help you somehow in that problem, you just need to learn a bit more, which I encourage you to do.
Good luck and in case of any specific question - come and ask!
else if { (sc.nextInt(char b) = getbBottle);
int bottleBcount++;
}
Syntax is totally wrong for if.Also condition is checked using == not = It should be :
else if (sc.nextInt(char b) == getbBottle);
int bottleBcount++;
Also you cant do int bottleBcount++. Its meaningless. Since you already declared bottleBcount in another class, you have to access it using the object of that class. Before that change the declaration in the class from int bottleAcount = 0; to public int bottleAcount = 0; . Do this for all bottles.
Now you can use it as :
public static void main(String[] args) {
System.out.println("Please put in a valid bottle");
bottleCount counter = new bottleCount();
Scanner sc = new Scanner(System.in);
while ( sc.nextInt() != -1) {
if (sc.nextInt(char a) == getaBottle);
counter.bottleAcount++;
} else if (sc.nextInt(char b) == getbBottle);
counter.bottleBcount++;
else if (sc.nextInt(char c) == getcBottle);
counter.bottleCcount++;
else { throw new EmptyStackException();
System.out.println("Bottle not recognized");
}
System.out.println("The total number of bottles is " + totalBottlecount);
System.out.println();
System.out.println("The total amount returned is " + sumOfBottles );
}
sc.close();
}
Also the statement int totalBottleCount = bottleAcount + bottleBcount + bottleCcount; doesnt make sense. It won't work as you wanted it to. You need to write a function to do this addition and then call it. Or if you want this to happen just once ( which I doubt) , you can put it in a constructor.
I suggest you brush up on class and variable declaration concepts before proceeding
You just have problem in this:
else {
throw new EmptyStackException();
System.out.println("Bottle not recognized");
}
Check the proper syntax and error will be resolved.
I have started how to learn Java programming and I a got a problem while doing an asignment:
ps this is a c programming assignment, using it to do a java programming:
Consider a (potentially large commercial) room that has floor dimensions length len and width wid. The area of the floor is given by multiplying len by wid.
Carpet tiles are provided as individual squares (2 feet by 2 feet). Write, compile and run a C program, carpet.c, that
-calculates the minimum number of carpet tiles that are needed to cover a room whose dimensions (len and wid) are input from the terminal (measurements are in inches). NB: floor tiles can be cut to fit at the edges of the room - try to minimise waste.
-calculates how many carpet-tile packs are needed. The supplier only provides carpet tiles in packs of ten (i.e. individual tiles cannot be purchased separately).
-calculates how many spare tiles are left over once the minimum number of packs have been purchased.
-prints out all these results in a neat table along with the total cost of the order. (A pack of tiles costs $50 for each of the first four packs, and the price reduces to $45 for each subsequent pack.)
Think carefully about how are you going to test your program? The calculations are non-trivial and easy to get wrong. If your program doesn't work then you will waste the company a lot of money and you will probably lose the contract to supply the software.
You should write out a number of test cases (by hand) that cover all the different possibilities that could happen. Don't forget to consider various boundary cases too - these are often where errors are detected.
So far I have done:
import java.util.Scanner;
public class carpet {
public static void main (String args[]){
Scanner scanf = new Scanner (System.in);
float len, wid;
float area;
int roundTiles;
int roundPacks;
float tarea;
float tpack;
float NoOfTiles;
float NoOfPacks;
float tspares1;
float tspares2;
int packCost;
int cost;
tarea= 12* 12;
tpack= 10;
System.out.format("Enter the length of the room, Inches: ");
len = scanf.nextFloat();
System.out.format("Enter the width of the room, Inches: ");
wid = scanf.nextFloat();
area = len * wid;
NoOfTiles = area/ tarea;
NoOfPacks = NoOfTiles/tpack;
roundTiles = (int) Math.ceil(NoOfTiles);
roundPacks = (int) Math.ceil(NoOfPacks);
tspares1 = roundPacks * 10;
tspares2 = tspares1 - roundTiles;
if (roundPacks <= 4)
packCost =50;
else if(roundPacks > 4)
{
packCost = 45;
packCost = packCost + 20; *<<-----******LINE 50-----*********
}
cost =roundPacks * packCost; *<<*******---ERROR-------------*********
System.out.println(cost);
}
}
The error says: "The local variable packCost may not have been initialized"
AND the compiler says: "Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The local variable packCost may not have been initialized
at carpet.main(carpet.java:50)
"
You need to initialize the variable packCost by doing replacing the current line:
int packCost;
by
int packCost=0;
You are initializing your packCost variable in a conditional statement and the compiler is not smart enough to detect it.
Using else instead of else-if makes it clear to the compiler that one of the conditions will be executed, so packCost is always set:
if (roundPacks <= 4)
packCost = 50;
else
{
packCost = 45;
packCost = packCost + 20;
}
You need to initialise packetCost:
int packCost = 0;
In Java, local variables need to be initialized. If this was a field variable, it would have an implicit default value of 0 (zero).
Here is a link that explains this: http://www.janeg.ca/scjp/lang/defaults.html (disclaimer: not my page)
From this page:
Field variables (class members) are automatically initialized to default values
Local variables (method or constructor variables) are not automatically initialized