Thread: Class Program: Help with Calculating Account Usage

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    5

    Class Program: Help with Calculating Account Usage

    I am hoping someone can help guide me in the right direction.
    I have a project for class that I am working on and I could use some help. The project guidelines are below as well as my code thus far.
    I have gotten this far with it but am having trouble specifically on accounting for the maximum hours in a month, and in Package B where it talks about charging $1 per 3-hour unit over 50 hours. Currently, my code is charging $1 per hour over 50 hours which is incorrect.
    Thanks in advance for any assistance.

    DROP LEAP YEAR REQUIREMENT
    ASSUME FEB 672 hrs
    An Internet service provider has three different subscription packages for its customers:

    Package A: For $12 per month with 10 hours of access provided.
    Additional hours are $2.00 per hour for the next
    20 hours of usage. Then the charges are $1.00 for
    each additional hour thereafter.
    Assume usage is recorded in one-hour increments,
    i.e., a 25-minute session is recorded as one hour.

    Package B: For $18 per month with 20 hours of access provided.
    Additional hours are $1.00 per hour for the next
    30 hours of usage. Then the charges are $1.00 for
    each additional 3-hour unit of usage thereafter,
    i.e., 1 or 2 hour(s) of aggregated usage would be
    charged $1.00.

    Package C: For $25 per month with 200 hours access is provided.
    Additonal $10 for the next 250 hours and an additional
    $15 for usage over 450 hours.

    Write a program that calculates a customer’s monthly charges.
    Must account for the maximum hours in a month.
    Validate all input.

    Code:
    //Program 2 ISP Packages
    
    
    #include <iostream>
    using namespace std;
    
    
    
    void main()
    {
        int pkg;
        cout<<"Enter pkg: ";
        cin>>pkg;
    
        if( pkg==1 || pkg==2 || pkg==3)
        {
            int hrs;
            cout<<"Enter hrs: ";
            cin>>hrs;
    
            if( hrs>= 0 && hrs<=720 )
            {
                int chg;
                switch(pkg)
                {
                
                    case 1:
                        chg = 12 + ( (hrs>10) ? (hrs-10)*2 : 0 );
                        break;
    
                    case 2:
    		{
                    	chg = 18 + ( (hrs>20 && hrs<=50) ? (hrs-20)*1 : 0 );		//Case 2 is working except for the $1
    			chg = 18 + ( (hrs>50) ? 30 + (hrs - 50)*1 : (hrs-20)*1);	//for each 3-hour unit. I'm charging 
                    	break;								//$1 per hour. Must fix!
    		}
    		case 3:
    		{
    			if (hrs<=200)
    			{
    				chg=25;
    			}
    			else if (hrs>200 && hrs<=450)
    			{
    				chg=35;
    			}
    			else if (hrs>450)
    			{
    				chg=50;
    			}
    			break;
    		}
    
                    default: 
                        break; 
                }
    
                cout<<"charges: "<<chg<<endl;
            }
            else
            {
                cout<<"Invalid hrs"<<endl;
            }
    
        }
        else
        {
            cout<<"Invalid pkg"<<endl;
        }
    
    
    
    
    
    }//main
    Last edited by ThePhenom; 09-28-2007 at 12:56 AM. Reason: Forgot to add code

  2. #2
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    First thing I can see, the first if statement:
    Code:
    if( pkg==1 || pkg==2 || pkg==3)
    It just makes your code harder to read. You're testing an error condition here. If the test fails, i.e. you have a pkg number other than 1, 2 or 3, you want to exit or ask again. In your case, where you just exit, you want to do somthing like:
    Code:
    if ((pkg < 1) || (pkg > 3)) {
         cout << "Invalid package" << endl;
         return 1;
    }
    // rest of prog, which you had inside your if statement previously
    This also removes the extra level of indentation you have on your main program. Rule of thumb: The code path you are likely to take in most cases, should be at the lowest indentation level.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    5
    Quote Originally Posted by QuantumPete View Post
    First thing I can see, the first if statement:
    Code:
    if( pkg==1 || pkg==2 || pkg==3)
    It just makes your code harder to read. You're testing an error condition here. If the test fails, i.e. you have a pkg number other than 1, 2 or 3, you want to exit or ask again. In your case, where you just exit, you want to do somthing like:
    Code:
    if ((pkg < 1) || (pkg > 3)) {
         cout << "Invalid package" << endl;
         return 1;
    }
    // rest of prog, which you had inside your if statement previously
    This also removes the extra level of indentation you have on your main program. Rule of thumb: The code path you are likely to take in most cases, should be at the lowest indentation level.

    QuantumPete
    I haven't gotten far enough in class yet to know, but why return 1? Basically it looks like you're just taking everything from the bottom of my code and moving it up to the top. Would this cause the code to run the same way?
    Also, do you have any input about my questions in my initial post?

  4. #4
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by ThePhenom View Post
    I haven't gotten far enough in class yet to know, but why return 1? Basically it looks like you're just taking everything from the bottom of my code and moving it up to the top. Would this cause the code to run the same way?
    Also, do you have any input about my questions in my initial post?
    It would run the same way. Consider this:
    Code:
    PSEUDOCODE:
    if (some_condition_is_true) {
         // Do all the things this prog is suppsed to do
    } else {
        // Print out an error message
        // Exit
    }
    That's what you have. It's much clearer if you test that the condition is false, and then exit if it is.
    Code:
    if (some_condition_is_false) {
        // Print out an error message
        // Exit
    }
    // Do all the things this prog is supposed to do
    As to the return 1. Have you come across the fact that in UNIX, every program will return a number to indicate whether it finished correctly or whether there was an error? 'return' will prematurely end your program and giving it a number can tell the user running your program that it finished incorrectly. By convention '0' means no errors, and all other numbers can be used to define exactly what went wrong.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    5
    I am still trying to get some help with this. I am having trouble specifically on accounting for the maximum hours in a month, and in Package B where it talks about charging $1 per 3-hour unit over 50 hours. Currently, my code is charging $1 per hour over 50 hours which is incorrect.

    Any help or direction would be appreciated.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    void main() is non-standard and as such should not be used.

    Code:
                    case 2:
    		{
                    	chg = 18 + ( (hrs>20 && hrs<=50) ? (hrs-20)*1 : 0 );		//Case 2 is working except for the $1
    			chg = 18 + ( (hrs>50) ? 30 + (hrs - 50)*1 : (hrs-20)*1);	//for each 3-hour unit. I'm charging 
                    	break;								//$1 per hour. Must fix!
    		}
    At first glance it seems like you could use hrs/3 instead of hrs to charge $1/3 hours instead of $1/hour. But that's not quite right, because if 3, 4, or 5 hours were used, you'd get charged for only 3 hours. What you want is to overcharge them, right?

    In that case you could use (hrs + 2) / 3. Think about it.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    Sep 2007
    Posts
    5
    Quote Originally Posted by dwks View Post
    void main() is non-standard and as such should not be used.

    Code:
                    case 2:
    		{
                    	chg = 18 + ( (hrs>20 && hrs<=50) ? (hrs-20)*1 : 0 );		//Case 2 is working except for the $1
    			chg = 18 + ( (hrs>50) ? 30 + (hrs - 50)*1 : (hrs-20)*1);	//for each 3-hour unit. I'm charging 
                    	break;								//$1 per hour. Must fix!
    		}
    At first glance it seems like you could use hrs/3 instead of hrs to charge $1/3 hours instead of $1/hour. But that's not quite right, because if 3, 4, or 5 hours were used, you'd get charged for only 3 hours. What you want is to overcharge them, right?

    In that case you could use (hrs + 2) / 3. Think about it.
    I appreciate your input! Thank you!
    What we're supposed to do is charge $1 for each 3-hour block of time over the set limit. So if you use 2 hrs, it'll round it up to 3 hours and charge you a dollar for it. Will you solution work in this case?

  8. #8
    Registered User
    Join Date
    Sep 2007
    Posts
    5
    Anyway, it looks like I've got it done. It's not 100&#37; as I'm not sure how to compensate for months with 28, 30 or 31 days, but I've got everything else working. Thanks for everyone's input.

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    What we're supposed to do is charge $1 for each 3-hour block of time over the set limit. So if you use 2 hrs, it'll round it up to 3 hours and charge you a dollar for it. Will you solution work in this case?
    Sure, just use the hours over the set limit instead of hrs. I guess you figured it out.

    I'm not sure how to compensate for months with 28, 30 or 31 days, but I've got everything else working.
    Something like this might help. I'm not sure if I have my leap-year algorithm right, you might want to check it.
    Code:
    int is_leap_year(int year) {
        return year &#37; 4 == 0 && year % 400;
    }
    
    int days_in_month(int month, int year) {
        switch(month) {
        case february:
            return is_leap_year(year) ? 29 : 28;
        case april:
        case june:
        /* ... */
            return 30;
        default:
            return 31;
        }
    }
    If months are represented as numbers, you can simplify that further with month%2 -- but you have to be careful with July and August, which are both 31 days.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    Registered User
    Join Date
    Sep 2007
    Posts
    7
    Thanks dwks. I've already submitted my work in class, but I'm going to add this when I get home for my own knowledge and see if it works. Thanks.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    int is_leap_year(int year) {
        return year % 4 == 0 && year % 400;
    }
    The leap year should also take into account that year % 100 is a NON-leap-year - besides, the code above is broken, because it will only be correct once we get to year 2400 - it requies that year is divisible by 4 AND by 400 at the same time, which in recent history is only year 2000.

    So, if it's divisible by 4, and NOT even divisible by 100, or it is evenly divisible by 400, it is a leap-year.
    Code:
    int days_in_month(int month, int year) {
        switch(month) {
        case february:
            return is_leap_year(year) ? 29 : 28;
        case april:
        case june:
        /* ... */
            return 30;
        default:
            return 31;
        }
    }
    I quite prefer to do this with one if and a table of 12 entries:
    Code:
    int days_in_month(int month, int year)
    {
       const static int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
       int retval;
    
       retval = days[month-1];  // This assume it's a numeric value where january is 1
       if (month == february && is_leap_year(year))
          retval++;
       return retval;
    }
    This should be, within reason, the most effiicent method.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I didn't think the leap year calculation was that simple . . .

    The lookup table for the days in months is a good idea.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. Replies: 6
    Last Post: 04-27-2006, 10:55 AM
  3. Replies: 8
    Last Post: 10-02-2005, 12:27 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM