Thread: Question for an assignment

  1. #1
    Registered User
    Join Date
    Oct 2016
    Posts
    23

    Question for an assignment

    Hey I am fairly new to programming and have to do an assignment for class. I did the assignment, but it closes after you input the Month portion of the date any ideas why?

    PROBLEM SPECIFICATION

    The MOREPRINTS Photo Store needs a program to calculate a customer bill based on the number
    of photos submitted and the number of reprints ordered. Reprints cost fifty cents a piece. The number
    of reprints ordered will be the same for each photo submitted: example - 5 photos, 3 reprints would be
    15 total reprints. Sales tax is 7%. The customer bill should include the customer's name ( first and last).
    The number of photos submitted, the number of reprints ordered, total number of reprints made, the cost
    per reprint, the total cost of reprints, tax, and total bill.

    Input: Customer Name
    Order Date (MM//DD/YY)
    Number of Photos submitted
    Number of reprints ordered

    CONSTANT: Any Information that is given and that will not be changed by the entry of data or by
    calculation.

    Variables: Data that will be changed by data entry, data calculation, or data manipulation.

    Calculations: Number of photos * number of reprints
    Total reprints * cost per reprint,
    Cost of reprints * tax percentage
    Cost of reprints + tax amount


    CODE
    Code:
    #include <iostream> // Required #include for running program
    #include <fstream>
    #include <string>
    #include <iomanip>
    
    
    using namespace std;
    const double SALES_TAX = 0.07; //constant values of sales tax
    const double REPRINTS = .50; // constant value of reprints
    
    
    int main()
    {
        char cust_name[40];
        char dummy;
        double total_reprints;
        double tax_amount;
        double reprint_cost;
        double total_cost;
        int photos_submitted;
        int reprints_ordered;
        int year;
        int month;
        int day;
    
    
    //Inputs of the date / customer name/ photos and reprints sumbmitted
    cout << "Please Enter the month: ";
    cin >> month; 
    
    
    cout << "Please Enter the day: ";
    cin >> day;
    
    
    cout << "Please Enter the year: ";
    cin >> year;
    
    
    cout << "Please enter your full name: ";
    cin >> cust_name;
    
    
    cout << "Please enter the number of photos submitted: ";
    cin >> photos_submitted;
    
    
    cout << "Please enter the number of reprints you would like: ";
    cin >> reprints_ordered;
    
    
    // cost of reprints
    reprint_cost = total_reprints * REPRINTS;
    
    
    // cost of total reprints
    total_reprints = photos_submitted * reprints_ordered;
    
    
    // cost of tax
    tax_amount = reprint_cost * SALES_TAX;
    
    
    //total cost of everything
    total_cost = reprint_cost + tax_amount;
    
    
    
    
    // Outputs of the date / customer name/ photos reprints and total cost sumbmitted
    cout << "MOREPRINTS Photo Store" << endl;
    
    
    cout << "Date: " << month << "/" << day << "/" << year << endl;
    
    
    cout << "Customer Name: " << cust_name << endl;
    
    
    cout << "Photos In: " << photos_submitted << endl;
    
    
    cout << "Reprints Ordered: " << reprints_ordered << endl;
    
    
    cout << "Total Reprints: " << total_reprints << endl;
    
    
    cout << "Price per Reprint: " << REPRINTS << endl;
    
    
    cout << "Tax: " << tax_amount << endl;
    
    
    cout << "Total Cost: " << total_cost << endl;
    
    
    cout << "Have a nice day" << endl;
    
    
    return 0;
    }


  2. #2
    Guest
    Guest
    I did the assignment, but it closes after you input the Month portion of the date any ideas why?
    Works fine here. Are you sure this is the exact code you're running? Check again and report back if the problem persists. You can also try with an online compiler like ideone, which lets you specify dummy input.

    As a question of style, I would recommend less blank lines in your code; there's a point where more whitespace makes things harder to read, not easier. It's also customary to declare variables near their use, instead of at the beginning. Some in your test program are unused, though this might have been deliberate if it's a work in progress.

  3. #3
    Registered User
    Join Date
    Oct 2016
    Posts
    23
    Quote Originally Posted by Guest View Post
    Works fine here. Are you sure this is the exact code you're running? Check again and report back if the problem persists. You can also try with an online compiler like ideone, which lets you specify dummy input.

    As a question of style, I would recommend less blank lines in your code; there's a point where more whitespace makes things harder to read, not easier. It's also customary to declare variables near their use, instead of at the beginning. Some in your test program are unused, though this might have been deliberate if it's a work in progress.

    It compiles just fine, but the output i get is this when I type in a random month to test it.

    Code:
    Please Enter the month: MayPlease Enter the day: Please Enter the year: Please enter your full name: Please enter the number of photos submitted: Please enter the number of reprints you would like: MOREPRINTS Photo Store
    Date: 0/0/0
    Customer Name:
    Photos In: 0
    Reprints Ordered: 1
    Total Reprints: 0
    Price per Reprint: 0.5
    Tax: 7.35827e-319
    Total Cost: 1.12477e-317
    Have a nice day

  4. #4
    Guest
    Guest
    You declared your date variables as integers:
    Code:
    int year;
    int month;
    int day;
    Thus an appropriate value for the month would be 5, not May. If you want that field to contain letters, you should declare it as a std::string.

  5. #5
    Registered User
    Join Date
    Oct 2016
    Posts
    23
    Quote Originally Posted by Guest View Post
    You declared your date variables as integers:
    Code:
    int year;
    int month;
    int day;
    Thus an appropriate value for the month would be 5, not May. If you want that field to contain letters, you should declare it as a std::string.
    Thank you for that. That was a dumb mistake on my part. Thank you for the help you have given me so far I am still really new to programming. Now I've run into another issue with the output:

    Code:
    Please Enter the month: 5Please Enter the day: 5
    Please Enter the year: 5
    Please enter your full name: Joe Smith
    Please enter the number of photos submitted: Please enter the number of reprints you would like: MOREPRINTS Photo Store
    Date: 5/5/5
    Customer Name: Joe
    Photos In: 0
    Reprints Ordered: 1
    Total Reprints: 0
    Price per Reprint: 0.5
    Tax: 7.35827e-319
    Total Cost: 1.12477e-317
    Have a nice day

  6. #6
    Guest
    Guest
    Yes, this another pitfall in C++ streams. Basically, when you type in the year and press enter, you send the year's number and a newline \n character. The latter doesn't get discarded and gets read the next time you use cin >> ...
    To alleviate this, you can clear the \n from the cin input stream. Do a websearch on the topic and you should find a more complete answer.

    For the customer name, you should use a std::string instead of a char array, and std::getline to read into it.

    So to combine above suggestions, make the following changes:
    Code:
    string cust_name; // instead of char cust_name[40];
    
    ...
    
    cin >> year;
    cin.ignore(8, '\n'); // discard the next \n you find; 8 is arbitrary but sufficient
    
    getline(cin, cust_name); // instead of cin >> cust_name;
    That should fix your problems, unless I missed something. Starting out with C++ can be a bit hairy at times, but the sailing gets smoother as you learn.
    Last edited by Guest; 10-04-2016 at 02:39 PM.

  7. #7
    Nasal Demon Xupicor's Avatar
    Join Date
    Sep 2010
    Location
    Poland
    Posts
    179
    @up - in this case it's not actually "dangling \n" problem, not just yet - anyway.

    Input streams' operator>> overloaded for char* or std::string will return on any whitespace, so since "Joe Smith\n" has a space in it - operator>> will return "Joe" and " Smith\n" is left in the input buffer. That's why the latter attempts at extracting integer data from the stream would fail.

    If you instead of operator>> use std::getline to get the full name - it will get everything till it finds \n, so a whole line, however, we know that at the point of calling it the input stream buffer is not actually empty because we called operator>> on it, to extract integers. When we extracted these integers - we left the dangling \n in there, and thus std::getline would return an empty string, that's why we need to extract/ignore the dangling newline.
    So, while attempting to solve one problem we find ourselves knee deep in another.

    Code:
    // let input buffer be called "buf"
    // buf == "";  -- it's empty, since we haven't done anything yet.
    int a = 0;
    std::cin >> a; 
    // what happens here? A couple of things:
    // since buf is empty, we get prompted for data; 
    // we type in "42" and press Enter, since the prompt will wait for either EOF or newline
    // now, buf == "42\n"; 
    // since the operator>> overloaded on int was called, it will try and export a value out of buf that will look like an int and store it into a, while ignoring any whitespace before that data, and stopping on first character that doesn't fit as part of an integer
    // "42" sure looks like int, but the next character - \n - sure doesn't look like a part of int representation, so "42" is extracted from buf, and the rest is left alone
    // now, buf == "\n"; and value of 42 is stored into a
    std::string s;
    std::getline(std::cin, s);
    // if buf is empty, we get prompted - but it isn't, as we now know
    // so getline extracts everything till \n (or EOF) from buf (if there's no \n in buf, it will prompt for more data)
    // then it stores everything it extracted into s; \n it merely "consumes" (extracts from buf, but doesn't store into the string). ;)
    // so that leaves s as an empty string here, no prompt called.
    We might want to put std::cin.ignore(std::numeric_limits<std::streamsiz e>::max(), '\n'); before we use getline() there.

  8. #8
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    @Xupicor, your explanation is much better than anything I've read in several books and online about this, thanks. I have one question though, if I'd input another int after int a, say int b, from the console before moving on to string s, how come b is read fine though buf after cin>>a still == '\n'. It seems that cin>>b first clears the existing buf before sending the prompt to console but getline() doesn't do something similar. Is this what actually happens? And if so, shouldn't we always, in theory, have a cin.ignore(numeric_limits<streamsize>::max(),'\n') after any cin>> statement in case a getline() appears in the code after that? This getline() can appear immediately at the time of writing the original program or at some point in the future when the code is modified and so a cin.ignore() would make the code safer.

    Thanks again

  9. #9
    Nasal Demon Xupicor's Avatar
    Join Date
    Sep 2010
    Location
    Poland
    Posts
    179
    Thank you for your kind words. ; )

    It seems that cin>>b first clears the existing buf before sending the prompt to console
    No, not exactly. The std::cin >> b; would work fine there because, let me quote myself: "it will try and export a value out of buf that will look like an int and store it into a, while ignoring any whitespace before that data". So even though there's dangling \n there - it gets ignored by the second call to operator>>.

    Try out some things - for example, have this code:
    Code:
    int a, b, c, d;
    std::cin >> a >> b >> c >> d;
    You can type every value in separate line, and press Enter key after each one. Let's consider that situation step by step. On first >> the input buffer is empty and thus we get prompt for data. We type "12" and press Enter. buf == "12\n", "12" gets extracted, converted into int(12) and stored into a, "\n" is left alone. Second >> is called, the input buffer isn't empty - so the buffer gets examined char by char, and "\n" - as it is considered a whitespace - is extracted and ignored. Now the buf is empty and still no proper data was extracted, so the prompt is shown again! You already know what happens next.

    You can also just type "12 23 34 45" and press Enter. It will work too. On first >> the input buffer is empty and thus we get prompt for data, same old story. "12" is extracted and converted to int(12) and stored in a. Then, the second >> is called, sees that the buffer isn't empty and goes over it, ignoring whitespace, until it finds proper data - so, " " is discarded, "23" is extracted and converted to int(23) and stored into b. The same thing happens again and again.

    As you can see above - operator>> here does NOT clear the input buffer.

    shouldn't we always, in theory, have a cin.ignore(numeric_limits<streamsize>::max(),'\n') after any cin>> statement in case a getline() appears in the code after that?
    Should you make all the necessary arrangements for your funeral every time you get into a car just in case you die this time around? I sure don't.
    You should put it before getline if you used operator>> on an input stream, if that's appropriate and what you want. It's usually what you want, but that isn't necessarily universal rule. To me, it sounds like a lot of unnecessary typing/copy-pasting.
    Again, instead of doing it everywhere just in case it's necessary - do it just (as in: only), nomen omen, in case where it actually is necessary. ; )

    If operator>> would do that automatically - our case with "12 23 34 45" wouldn't work.
    Last edited by Xupicor; 10-06-2016 at 04:38 AM.

  10. #10
    Registered User
    Join Date
    Mar 2016
    Posts
    203
    Another good explanation with a dash of humor, many thanks.

  11. #11
    Registered User
    Join Date
    Oct 2016
    Posts
    23
    Thank you for your help with this. Everyone has been so nice to me on here I do appreciate this more than words. I am running into a math problem now with the assignment. it outputs:
    Code:
    Please Enter the month: 5Please Enter the day: 5
    Please Enter the year: 5
    Please enter your full name: Joe Smith
    Please enter the number of photos submitted: 5
    Please enter the number of reprints you would like: 5
    MOREPRINTS Photo Store
    Date: 5/5/5
    Customer Name: Joe Smith
    Photos In: 5
    Reprints Ordered: 5
    Total Reprints: 25
    Price per Reprint: 0.5
    Tax: 7.35842e-319
    Total Cost: 1.12479e-317
    Have a nice day

    Not sure why am I also making a mistake I am missing?
    Last edited by Pastryking; 10-06-2016 at 09:12 AM.

  12. #12
    Guest
    Guest
    You need to make sure that the variables you use actually have the values you expect them to. In your original example, total_reprints remains an unknown quantity.

    What program are you using to write your code? You should set it a higher warning level if possible.

  13. #13
    Registered User
    Join Date
    Oct 2016
    Posts
    23
    I am using Dev Bloodshed 5.11. So the ones that have exact values are good. I thought it was as simple as declaring the input and than multiplying the constants I have by the input amounts the person gives in the actual code. Am I doing something wrong?

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    There is a case to be made for consistently using std::getline to read into a std::string, then parsing that string. This way, you can detect invalid input rather than just take the acceptable portion of the input and discard the rest. For example:
    Code:
    #include <iostream>
    #include <string>
    
    int main()
    {
        std::cout << "Enter your age in years: ";
        int age = 0;
        std::cin >> age;
    
        std::cout << "Enter your favourite drink: ";
        std::string drink;
        std::getline(std::cin, drink);
    
        std::cout << "You are " << age << " years old and your favourite drink is " << drink << std::endl;
    }
    The above program would demonstrate the problem that you encountered earlier, e.g., the user enters "99", and then getline reads the unread whitespace up to the newline from the enter, leaving the reader with no chance to enter the drink and with a weird output. As previously suggested, you could use cin.ignore:
    Code:
    #include <iostream>
    #include <string>
    #include <limits>
    
    int main()
    {
        std::cout << "Enter your age in years: ";
        int age = 0;
        std::cin >> age;
    
        std::cout << "Enter your favourite drink: ";
        std::string drink;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::getline(std::cin, drink);
    
        std::cout << "You are " << age << " years old and your favourite drink is " << drink << std::endl;
    }
    Now, the user can enter "99", then enter "beer", and it works perfectly fine. But if the user were to enter "99 bottles of beer", the input will still be treated as valid, i.e., age == 99 and then then user would be prompted for the drink. If you read the line into a string and use stoi or stringstreams instead, you could check for this. It would also automatically eliminate the need for the cin.ignore call later because the entire line is read, including the newline.

    As a bit of trivia: while researching how to write a manipulator that could match constants so as to enforce an input format more easily, I came across the std::ws input manipulator. You could actually use it in place of std::cin.ignore here:
    Code:
    #include <iostream>
    #include <iomanip>
    #include <string>
    
    int main()
    {
        std::cout << "Enter your age in years: ";
        int age = 0;
        std::cin >> age;
    
        std::cout << "Enter your favourite drink: ";
        std::string drink;
        std::cin >> std::ws;
        std::getline(std::cin, drink);
    
        std::cout << "You are " << age << " years old and your favourite drink is " << drink << std::endl;
    }
    Though it remains an inferior solution to both cin.ignore and the read the entire line as a string then parse solutions because it performs poorly when faced with invalid input.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Guest
    Guest
    Quote Originally Posted by Pastryking View Post
    I am using Dev Bloodshed 5.11.
    I'm only familiar with that IDE by name. It appears to use GCC as its compiler. Judging by the screenshots, there are tabs called "Compiler" and "Compile Log" at the bottom. Have you looked at their contents? If they don't contain any warnings, then do a websearch on how to set warning levels in your IDE (pass the -Wall and -Wextra flags).

    I thought it was as simple as declaring the input and than multiplying the constants I have by the input amounts the person gives in the actual code.
    It is. I mentioned total_reprints in my earlier post. Looking back at the code in your first post, what value do you think that variable holds when you use it on line 53? (The order of execution matters)
    Last edited by Guest; 10-06-2016 at 10:59 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. assignment question
    By alien1 in forum C Programming
    Replies: 1
    Last Post: 10-27-2014, 05:47 PM
  2. C assignment question
    By Martyn27 in forum C Programming
    Replies: 15
    Last Post: 02-23-2010, 03:17 PM
  3. assignment question...
    By jerrykelleyjr in forum C Programming
    Replies: 2
    Last Post: 10-31-2006, 08:21 AM
  4. DevCPP assignment question
    By SinAmerica in forum C++ Programming
    Replies: 3
    Last Post: 03-07-2004, 05:22 AM
  5. array assignment question
    By threahdead in forum C Programming
    Replies: 2
    Last Post: 08-17-2003, 05:36 PM

Tags for this Thread