Hallmark Problem [Please help]

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

35 Replies - 2671 Views - Last Post: 02 February 2013 - 12:13 PM Rate Topic: -----

#31 k3y  Icon User is offline

  • D.I.C Head

Reputation: 36
  • View blog
  • Posts: 205
  • Joined: 25-February 12

Re: Hallmark Problem [Please help]

Posted 01 February 2013 - 06:07 PM

The code has been completed. I want to thank every person that was involved in helping me with this code. As I promised I will break down my code to show that I have truly learned from this experience.

import java.util.*;
public class Hallmark



//line 1 This will make all classes in the java.util package available to me and if I want to I can use any of them. For example Arrays.sort() could have been since Arrays is a class in the java.util package
//line 2 This will make a public class, meaning that everything declared in here will be available to all of the other
classes. In this case the Scanner console.

{
  static Scanner console = new Scanner(System.in);



// This will create a Scanner object that will in this case watch out for all inputted data streams.
  public static void main(String[] args)
  {
// variable declaration
    boolean isInt = true;
    Card userCard;
    int iUserInput;
    int iInputCounter = 1;
    String sSender = toPerson();
    String sRecipient = fromPerson();



These are a number of variables that will be available to all of the classes in this area, as can be seen by the public access modifier and the static makes it so the class is global and anything that happens in it is available to all other classes/subclasses. The Card userCard is a userdefined datatype and userCard is the object of the Card class that includes the abstract makeCard(); method that was used to create the various cards.

            case 1: 
              userCard = new Christmas(sSender, sRecipient);
              break;


This case and the others all do the same thing (even though the number of parameters may differ). They all assign userCard(object) to a certain subclass of Card and will pass the user input to the class's constructor.

          //generic information
          userCard.makeCard();



This calls our makeCard(); method however; it is dependent on the type of card, and the number of parameters. Generally userCard could be say Christmas, and this access the makeCard() method in the Christmas class and pass the information stored in userCard (sSender, sRecipient) and will create the custom card.

public static String sMessage()
{
  System.out.println("Please enter your message to the recipient: ");
  // clear buffer
  console.nextLine();
  String sMessageToRecipient = console.nextLine();
  return sMessageToRecipient;
  }
}



This method is similar to the other methods however; seeming as it is dealing with String you should clear the buffer to make sure no hooplah is in the way to making the code work.

Thank you: Jon.Kiparsky and CasiOo for all the help you have provided for me. Now for the final code in one piece
import java.util.*;
public class Hallmark
{
  static Scanner console = new Scanner(System.in);
  public static void main(String[] args)
  {
// variable declaration
    boolean isInt = true;
    Card userCard;
    int iUserInput;
    int iInputCounter = 1;
    String sSender = toPerson();
    String sRecipient = fromPerson();
    
//menu, point 3
    String sMenu = "Please select your card:" + 
      "\n\t1) Christmas" + 
      "\n\t2) Valentines" +
      "\n\t3) Birthday" +
      "\n\t4) Get well soon" +
      "\n\t5) Anniversary" +
      "\n\t6) New Baby" +
      "\n\t7) Thank You" +
      "\n\t8) Congratulations" + 
      "\n\t9) Blank Card\n";
    
//print menu
    System.out.print(sMenu);
 
//confirm input
    do
    {
      System.out.println("Please enter a valid choice");
      try
      {
        iUserInput = console.nextInt();
        if ((iUserInput >= 0) && (iUserInput <= 9))
        {
//decrease counter if successful range
          iInputCounter--;
                 
          switch(iUserInput)
          {
//christmas card, point 1
            case 1: 
              userCard = new Christmas(sSender, sRecipient);
              break;
              
//valentines card, point 1
            case 2: 
              userCard = new Valentines(sSender, sRecipient);
              break;
            
//birthday card, point 1
            case 3: 
              int iAge = agePerson();
              userCard = new Birthday(sSender, sRecipient, iAge);
              break;
         
//getwellsoon card, point 1
            case 4: 
              userCard = new GetWellSoon(sSender, sRecipient);
              break;
            
//anniversary card, point 1
            case 5: 
              userCard = new Anniversary(sSender, sRecipient);
              break;
            
//newbaby card, point 1
            case 6: 
              userCard= new NewBaby(sSender, sRecipient);
              break;
            
//thankyou card, point 1
            case 7: 
              userCard = new ThankYou(sSender, sRecipient);
              break;
            
//congratulations card, point 1
            case 8: 
              userCard = new Congratulations(sSender, sRecipient);
              break;
            
//blank card, point 1
            default:
              String sMessageToRecipient = sMessage();
              userCard = new BlankCard(sSender, sRecipient, sMessageToRecipient);
              break;
          }
          //generic information
          userCard.makeCard();
        }
        else
        {
          System.out.println("You have not entered a valid choice");
          continue;
        }
      }
      catch (InputMismatchException e)
      {
        System.out.println("You have entered an invalid input");
        console.next();
        continue;
      }
    }while(iInputCounter > 0);
  }
  
  //point 2
  public static String toPerson()
  {
    System.out.println("Please enter your name");
    String sSender = console.nextLine();
    return sSender;
  }
  
//point 2
  public static String fromPerson()
  {
    System.out.println("Please enter recipients name");
    String sRecipient = console.nextLine();
    return sRecipient;
  }
  
//point 4
  public static int agePerson()
  {
    int iAge = 0;
    do
    {
      System.out.println("Please enter recipients age");
      try
      {
        iAge = console.nextInt();
        return iAge;
      }
      catch(InputMismatchException e)
      {
        System.out.println("You have entered invalid input");
        continue;
      }
  }while(true);
  }
  
//point 5
public static String sMessage()
{
  System.out.println("Please enter your message to the recipient: ");
  // clear buffer
  console.nextLine();
  String sMessageToRecipient = console.nextLine();
  return sMessageToRecipient;
  }
}



Truly thank you guys for all of your help
Was This Post Helpful? 0
  • +
  • -

#32 CasiOo  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1408
  • View blog
  • Posts: 3,123
  • Joined: 05-April 11

Re: Hallmark Problem [Please help]

Posted 01 February 2013 - 06:19 PM

Your agePerson method does not work correctly when the input is not a number
It will keep reading the same illegal input over and over because it doesn't remove it from the buffer when an exception is thrown
	public static int agePerson() {
		while (true) {
			System.out.println("Please enter recipients age");
			try {
				return console.nextInt();
			}
			catch (InputMismatchException e) {
				System.out.println("You have entered invalid input");
				console.next();
			}
		}
	}


This post has been edited by CasiOo: 01 February 2013 - 06:19 PM

Was This Post Helpful? 0
  • +
  • -

#33 k3y  Icon User is offline

  • D.I.C Head

Reputation: 36
  • View blog
  • Posts: 205
  • Joined: 25-February 12

Re: Hallmark Problem [Please help]

Posted 01 February 2013 - 06:31 PM

Once again thank you. Besides that everything else look okay? Because it seems to be working for me.
Was This Post Helpful? 0
  • +
  • -

#34 CasiOo  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1408
  • View blog
  • Posts: 3,123
  • Joined: 05-April 11

Re: Hallmark Problem [Please help]

Posted 02 February 2013 - 10:12 AM

Another bug
iUserInput >= 0


Should be > 0 since there is no option 0
iUserInput > 0



I just tried and apply my console IO helper class to your code, just to see how much simpler it would all get
To me it is now a lot simpler since you get rid of all the loops in your code
It is basically the same code, but where a helper class handles some of the nasty input validation for you
public class Hallmark
{
  static IOReader reader = new IOReader(System.in);
  
  public static void main(String[] args)
  {
    String sSender = toPerson();
    String sRecipient = fromPerson();
    
    String sMenu = "Please select your card:" + 
      "\n\t1) Christmas" + 
      "\n\t2) Valentines" +
      "\n\t3) Birthday" +
      "\n\t4) Get well soon" +
      "\n\t5) Anniversary" +
      "\n\t6) New Baby" +
      "\n\t7) Thank You" +
      "\n\t8) Congratulations" + 
      "\n\t9) Blank Card\n";
    
    System.out.print(sMenu);
 
    System.out.println("Please enter a valid choice");
    int iUserInput = reader.getIntInRange("You have not entered a valid choice", "You have entered an invalid input", 1, 9);
    
    //Just for testing without the Card classes
    System.out.println("Option " + iUserInput);
    System.out.println("Sender " + sSender);
    System.out.println("Recipient " + sRecipient);
    
    switch(iUserInput)
    {
      case 1: 
        break;
      case 2: 
        break;
      case 3: 
        int iAge = agePerson();
        System.out.println("Age " + iAge);
        break;
      case 4: 
        break;
      case 5: 
        break;
      case 6: 
        break;
      case 7: 
        break;
      case 8: 
        break;
      default:
        String sMessageToRecipient = sMessage();
        System.out.println("Message " + sMessageToRecipient);
        break;
    }

    //userCard.makeCard();
  }
  
  public static String toPerson()
  {
    System.out.println("Please enter your name");
    return reader.readString();
  }
  
  public static String fromPerson()
  {
    System.out.println("Please enter recipients name");
    return reader.readString();
  }
  
  public static int agePerson() {
		System.out.println("Please enter recipients age");
		return reader.readInt("You have entered invalid input");
  }

	public static String sMessage()
	{
	  System.out.println("Please enter your message to the recipient: ");
	  return reader.readString();
  }
}



And the helper class
The class is not finished, I only change it when I need new functionality ^^
Pbl doesn't like it, which makes it even more fun to use =) !
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

/**
 * 
 * @author CasiOo @ dreamincode.net
 *
 */
public class IOReader {
	private BufferedReader reader;
	private HashMap<Class<?>, IParseableType> parsers;
	
	public IOReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream));
		parsers = new HashMap<Class<?>, IParseableType>();
		parsers.put(int.class, new IntegerParser());
		parsers.put(double.class, new DoubleParser());
		parsers.put(byte.class, new ByteParser());
		parsers.put(short.class, new ShortParser());
		parsers.put(String.class, new StringParser());
	}
	
	//Helper method
	private <T> T read(Class<T> c, String illegalInputMsg) {
		IParseableType parser = parsers.get(c);
		
		while (true) {
			try {
				return (T) parser.parse(reader.readLine());
			}
			catch (NumberFormatException e) {
				printLine(illegalInputMsg);
			}
			catch (IOException e) {
			}
		}
	}
	
	public int readInt(String illegalInputMsg) {
		return read(int.class, illegalInputMsg);
	}
	
	public double readDouble(String illegalInputMsg) {
		return read(double.class, illegalInputMsg);
	}
	
	public byte readByte(String illegalInputMsg) {
		return read(byte.class, illegalInputMsg);
	}
	
	public short readShort(String illegalInputMsg) {
		return read(short.class, illegalInputMsg);
	}
	
	public String readString() {
		return read(String.class, "");
	}
	
	/**
	 * Receive input from the user, and check the input against all of the allowed inputs.
	 * 
	 * @param message The message to show the user before taking input.
	 * @param possibleInputs All of the allowed inputs.
	 * @return Returns the first allowed input made by the user.
	 */
	public String getInput(String invalidSelectionMsg, String... possibleInputs) {
		//Loop as long as the user haven't entered an allowed input
		while (true) {
			//Read input from our scanner
			String input = readString();
			
			//If the input is allowed then break out of the while loop
			if (isAllowedInput(input, possibleInputs))
				return input;
			else
				printLine(invalidSelectionMsg);
		}
	}
	
	public int getIntInRange(String invalidSelectionMsg, String invalidTypeMsg, int lowest, int highest) {
		while (true) {
			int selection = readInt(invalidTypeMsg);
			
			if (selection >= lowest && selection <= highest)
				return selection;
			else
				printLine(invalidSelectionMsg);
		}
	}
	
	/**
	 * Checks if 'input' is equal to one of the allowed inputs.
	 * 
	 * @param input Input made by the user.
	 * @param possibleInputs All allowed inputs.
	 * @return Returns true if the input is allowed.
	 */
	private boolean isAllowedInput(Object input, Object[] possibleInputs) {
		for (int i=0; i<possibleInputs.length; i++)
			if (input.equals(possibleInputs[i]))
				return true;
		return false;
	}
	
	/**
	 * Shows a message to the user through the console.
	 * 
	 * @param line The message to show.
	 */
	public void printLine(String line) {
		System.out.println(line);
	}
	
	/*
	 * Parsers
	 */
	
	private interface IParseableType {
		Object parse(String input);
	}
	
	private class IntegerParser implements IParseableType {
		@Override
		public Object parse(String input) {
			return Integer.parseInt(input);
		}
	}

	private class DoubleParser implements IParseableType {
		@Override
		public Object parse(String input) {
			return Double.parseDouble(input);
		}
	}
	
	private class ByteParser implements IParseableType {
		@Override
		public Object parse(String input) {
			return Byte.parseByte(input);
		}
	}
	
	private class ShortParser implements IParseableType {
		@Override
		public Object parse(String input) {
			return Short.parseShort(input);
		}
	}
	
	private class StringParser implements IParseableType {
		@Override
		public Object parse(String input) {
			return input;
		}
	}
}



Was This Post Helpful? 0
  • +
  • -

#35 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7898
  • View blog
  • Posts: 13,434
  • Joined: 19-March 11

Re: Hallmark Problem [Please help]

Posted 02 February 2013 - 10:34 AM

That's a pretty good overview of the code. Well done.


Ont thing that you might want to be aware of:

Quote

//line 1 This will make all classes in the java.util package available to me and if I want to I can use any of them. For example Arrays.sort() could have been since Arrays is a class in the java.util package


Many programmers feel - and I am one of them - that import java.mumble.* is a poor construction to use, and that instead you should import specifically the classes you wish to use. There are two reasons for this, neither of which is "because it's harder and therefore better for you". :)

The first reason has to do with import conflicts. People who write classes like to give them names that express their purpose. This sometimes means choosing a name that someone else has used, and when you import two classes with the same name you have an ambiguous reference. For example, if you were to import java.awt.*, you would now have an ambiguous reference, since bot util and awt have classes called "List".
This is the only such conflict that I know of in the Standard Library, but if you use other libraries it's likely that you'll run into other conflicts. By making your imports explicit, you know precisely when you've got such a conflict and that allows you to deal with that conflict.

That's not a bad reason, but it's perhaps not super convincing. After all, this happens quite rarely. The second reason is more convincing to me: explicit import statements make your code more clear, and clarity is the single most important goal of a programmer.* They're essentially a form of documentation, telling me what sorts of objects you're expecting to work with and what you expect to do with them. Wildcard imports throw away this advantage, for no gain.

There's a third reason, as well, which is more of a disciplinary effect, helping you to keep your classes focussed. You don't want your classes to sprawl: if you're representing a pet, you don't want to write the pet store in the same class. If your import statements start to feel like they're getting out of control, then it's probably a sign that your class is doing too much, and it's time to cut it back down to size.



*Yes, more important than correctness. Consider: If I know what you're trying to do, and you're not doing it correctly, I can fix it. If I don't know what you're trying to do, I can't even know whether you're doing it correctly or not!
Was This Post Helpful? 0
  • +
  • -

#36 k3y  Icon User is offline

  • D.I.C Head

Reputation: 36
  • View blog
  • Posts: 205
  • Joined: 25-February 12

Re: Hallmark Problem [Please help]

Posted 02 February 2013 - 12:13 PM

Once again Jon thank you for your help I really appreciate it. You really are awesome and, I hope I can continue to harass you with questions in the future (after I try on my own that is). I'll be on here for a longtime I feel =D
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3