ctypea program

Pages: 123
I just wanted to ask what is used in this program? is it loop with an if/else?

https://imgur.com/a/GuOM0Fd

I tried doing it but every time I look down "- OFFICIAL RECEIPT - " I am getting confused. How can it read what I'm gonna input next on a loop? because it only read the last inputs I will enter. It closes/end with an 'x' or 'X'

Here is my attempt source code that is not even close to half.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
string productname;
do{
    double quantity = 0, price = 0, sum = 0, qprice, flist;
    cout<< "\nProduct name: ";
    cin>> productname;
    sum += quantity;
        if (productname == "x" || productname == "X"){
        cout<<" - OFFICIAL RECEIPT -\n";
        cout<<"Qty Product name   Price\n";
        cout<<flist;
        break;
        }
    cout << "Quantity: ";
    cin >> quantity;
    cout << "Price: ";
    cin >> price;
    } while(1);
}
Last edited on
Hello seghrein2300,

There is not enough code to duplicate the problem or see what is going on.

Line 5 is the only variable that is left after the do/while loop.

Line 7 is created each time you enter the loop and destroyed each time the loop ends, meaning the closing }.

Line 10 the variable is "sum", but sum of what? And at the moment "quantity" just feels like the wrong variable to add.

The code you are missing is what prints each line of the receipt.

The do/while loop looks like it is useful, but I do not see where you are storing the the value of the variables "productname", "quantity" and "price" outside of the loop.

Andy
Hello seghrein2300,

Working with and changing you code I came up with this. This does not fix the problem, but it might help to understand what it is doing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <cctype>  // <--- For "std::tolower() and std::toupper()" + others.
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

int main()
{
    string productname;

    double quantity = 0, price = 0, qprice{}, flist{};  // <--- "qprice" is never used here and "flist"'s value never changes.
    double subTotal{};  // <--- Maybe this would be a better name.
   
    do
    {
        cout << "\nProduct name: ";
        cin >> productname;

        subTotal += quantity;  // <--- Maybe you meant subTotal += quantity * price;

        if (std::tolower(productname[0]) == 'x' /*|| productname == "X"*/)
        {
            cout << "\n - OFFICIAL RECEIPT -\n";
            cout << "Qty Product name   Price\n";
            cout << flist;
            break;
        }

        cout << "Quantity: ";
        cin >> quantity;

        cout << "Price: ";
        cin >> price;
    } while (1);

    std::cout
        << quantity << "  "
        << productname << "  "
        << price << '\n';

    return 0;  // <--- Not required, but makes a good break point.
}


And this is the output I get:

Product name: 1
Quantity: 2
Price: 1

Product name: 2
Quantity: 4
Price: 2

Product name: x

 - OFFICIAL RECEIPT -
Qty Product name   Price
04  x  2
^ This number is from inside the loop from the if statement. It is "flist" who's value has never changed.
The 4 x and 2 are the last values of the variables "quantity", "productname" and "price". Not what you want.



Line 20 seams better suited to come after line 34.

Andy
@seghrein2300

Your program is a little bit more than halfway there but you need to rethink what it is you are trying to do.

pseudo-code organizes your thinking and planning before you start typing code. ( where have you heard that before )

The way I read it is:

1. LOOP:
2. If product name is not x/X continue, otherwise get out of loop
3. get details of name price and quantity of a product
4. process the current receipt total
5. go back to LOOP

6. Print header
7. Print itemised details
8. Print total cost


Now, you can see from this you need somewhere to store the data because you can't write out the receipt until you have everything including the total. The way it is you are left to print the header and mixing it up with the input data.

You need arrays, at least. And to keep it simple maybe allow for 5 items maximum.
... and this is what it translates to with code ... you can do the rest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<iostream>

using namespace std;

int main()
{
    const int MAX_NO_ITEMS{5};
    
    string productname[MAX_NO_ITEMS];
    double quantity[MAX_NO_ITEMS]{0};
    double price[MAX_NO_ITEMS]{0};
    
    int item_count{0};
    
    while( productname[item_count] != "x" && productname[item_count] != "X" )
    {
        cout<< "Product name: ";
        cin>> productname[item_count];
        
        cout << "Quantity: ";
        cin >> quantity[item_count];
        
        cout << "Price: ";
        cin >> price[item_count];
        
        item_count++;
    }
    
    cout << " - OFFICIAL RECEIPT -\n";
    cout << "Qty Product name   Price\n";
    
    /*
     for( ... blah blah 0 to item_count )
     {
     item by item - calculate qty * price* and display it
     plus add to grand total
     }
     
     print grand total blah blah ...
     */
    return 0;
}
PS for debugging purposes instead of 5 just have 2 to avoid too much typing as you test/fix and retest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(
          cout<< "Product name: " &&
          cin>> productname[item_count] &&
          productname[item_count] != "x"
          )
    {
        cout << "Quantity: ";
        cin >> quantity[item_count];
        
        cout << "Price: ";
        cin >> price[item_count];
        
        item_count++;
    }
Last edited on
thanks ya'll for helping me understand the logic. but I am limited not to use arrays sadly. I tried tweaking my code based on what you guys sent. here it is.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    string productname;
    double quantity, price, sum, qprice, sum1;
    do {
        cout << "Product name: ";
        cin >> productname;
        if (productname == "x" || productname == "X"){
        cout<<" - OFFICIAL RECEIPT -\n";
        cout<<"Qty Product name   Price\n";
        cout<< "" << quantity << "   " << productname << "              " << price;
        cout<<"\nTotal\n";
        cout<< sum1 << " item(s)" << "      " << sum;
        break;
        }
        if (productname != "x" || productname != "X"){
        cout << "Quantity   : ";
        cin >> quantity;
        cout << "Price      : ";
        cin >> price;
        }
        qprice = quantity * price;
        sum += qprice;
        sum1 += quantity;
    } while (10);
}

The problem is if I enter

Product name: Apple
Quantity: 3
Price: 15
Product name: Grapes
Quantity: 3
Price: 5
Qty Product name Price
3 x 5
TOTAL: 16

It reads what I input in the last, I want it to look more like.

Product name: Apple
Quantity: 3
Price: 15
Product name: Grapes
Quantity: 3
Price: 5
Qty Product name Price
3 Apple 15
3 Grapes 5
TOTAL: 16

Sorry I'm pretty new to this.
Last edited on
also, how can I read what I input in the loop? even if entered many times.
like

'x' 'X' to stop
input: Black
input: Blue
input: Red
input: Yellow
input: x

output:
Black
Blue
Red
Yellow
Sorry I'm pretty new to this.

As we go up (not down) in complexity perhaps use <vectors>'s.

I'm now just as interested as you are to see how this will run out if arrays are excluded.

Aside from stringstreams, displaying the (formatted) data on another terminal instance, using a GUI platform with textbox storage of some sort, or saving the data to a file and retrieving it for displaying the receipt, I can't think of a simpler way than C-style arrays. But I am open to whatever ...

BTW while(10), like while(1) just keeps the loop going around because 1, 10 or whatever number you put in their is always true.

Also, having the while at the start has the small advantage you can bail out before any data beyond a bail out 'x' is input.

Good luck with it. I look forward to the array alternatives :)
BTW If you include the heading all of that above applies. If you don't include the heading then use <iomanip> functionality to format/present the processed data. Even then mixing input with formatted output to the console/terminal becomes interesting unless you use something like nCurses software.
is it possible that cin.ignore() and cin.getline() can fix my output at -OFFICIAL RECEIPT-?
is it possible that cin.ignore() and cin.getline() can fix my output at -OFFICIAL RECEIPT-?


This tutorial example shows how the two fit together.

I'm not sure what 'fix my output' means. They won't fix the storage problem that arrays sor other containers solve. If I were you I would have a talk to your teacher or tutor on this and also the array ban.

If you have a productname that is made up of two or more words then you would use getline, instead of cin. cin.ignore(...) is explained in the tutorial.

As far as the operation of the while loop I suggest you read up on while loops and practice and test your ideas. They can be tricky so a simple test inside the while condition is the best way to go. Putting the if x stuff inside the while only makes it more complicated than it needs to be.




If you need to process/display which has previously been entered, then some sort of storage is required to hold the data. This would often be an array (if the number of items is known) or a vector.

but I am limited not to use arrays sadly


Does this also apply to using a vector - which would be the usual container used? If you aren't allowed to use a vector, can you use a file? what about dynamic memory? Assuming this is an exercise, what is your teacher expecting you to use?
Those questions plus others have already been raised and we are waiting answers from the teacher/tutor.

Of course, along the lines of a creative use of stringstream there might be a solution using getline(). The problem is, however, that tokenization, parsing or whatever would be a challenge way beyond the beginner level at an introductory course.
Thank ya'll I'm back at working at my program again, I will let you know if I will be getting it done or changing my logic.

Does this also apply to using a vector

Sadly, yes. It's kind of a challenge for us with limitations.
Last edited on
Hello seghrein2300,

It sounds like this is a school assignment. The first thing you should have done is pass along the instructions that you were given. This way everyone will know what you have to do without asking questions about what you can use.

I have come up with this code using a string stream, but you may not be able to use it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <cctype>  // <--- For "std::tolower() and std::toupper()" + others.
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    std::stringstream outStream;

    string productname;

    double quantity = 0, price = 0, qprice{}, flist{};  // <--- "qprice" is never used here and "flist"'s value never changes.
    double subTotal{}, lineTotal{};  // <--- Maybe this would be a better name.

    std::cout << std::fixed << std::showpoint;

    do
    {
        cout << "\nProduct name (x) to end: ";
        cin >> productname;

        if (std::tolower(productname[0]) == 'x' /*|| productname == "X"*/)
        {
            break;
        }

        cout << "Quantity: ";
        cin >> quantity;

        cout << "Price: ";
        cin >> price;
     
        lineTotal = quantity * price;

        subTotal += lineTotal;  // <--- Maybe you mean subTotal += quantity * price;

        outStream
            << std::setprecision(0) << std::setw(2) << quantity << "  "
            << std::left << std::setw(13) << productname
            << std::right << std::setprecision(2) << std::setw(6) << lineTotal << '\n';
    } while (1);

    cout << "\n - OFFICIAL RECEIPT -\n";
    cout << "Qty Product name   Price\n";
    //cout << flist;

    std::cout << outStream.str();

    std::cout
        << std::string(25, '-') 
        << '\n' << std::string(18, ' ') << std::setprecision(2) << std::setw(6) << subTotal << '\n';

    return 0;  // <--- Not required, but makes a good break point.
}

The only problem I am having is with line 43. It does not print ".00" and I am not sure why. I am not that familiar with creating a string stream this way so any input is appreciated.

If you can not use a string stream the only other option I can think of is to use a file.

I hope this is at least something that will help you grt to the right direction.

Andy
Hello seghrein2300,

Sorry, I did not have this ready yet.

The output produced looks like:

Product name (x) to end: Apples
Quantity: 1
Price: 1.56

Product name (x) to end: Oranges
Quantity: 2
Price: 1

Product name (x) to end: x

 - OFFICIAL RECEIPT -
Qty Product name   Price
 1  Apples          1.6
 2  Oranges           2
-------------------------
 Sub Total          3.56


Added the "Sub Total" as an after thought.

Andy
Handy Andy,

OMG Thank you so much but knowing just know cctype, sstream, outstream ain't allowed too. Ahhgh. Im tryna tweak the code you gave.
This is really, really, yucky code - but it'll do what you want without explicitly using an array or having to know how many items there are:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <cstdlib>
#include <string>
#include <iostream>

int main()
{
	struct Item {
		double quant {};
		double price {};
	};

	size_t used {};
	char* data {nullptr};

	for (std::string name; (std::cout << "\nProduct name [CR to end]: ") && std::getline(std::cin, name) && !name.empty(); ) {
		Item item;

		std::cout << "Quantity: ";
		std::cin >> item.quant;

		std::cout << "Price: ";
		std::cin >> item.price;

		std::cin.ignore(1000, '\n');

		const size_t old {used};

		used += sizeof(Item) + name.size() + 1;
		data = (char*)std::realloc(data, used);
		memcpy(data + old, &item, sizeof(Item));
		memcpy(data + old + sizeof(Item), name.c_str(), name.size() + 1);
	}

	std::cout << '\n';

	for (char* ptr = data, *endptr = data + used; ptr < endptr; ) {
		const std::string name(ptr + sizeof(Item));
		Item item;

		memcpy(&item, ptr, sizeof(Item));
		std::cout << item.quant << "  " << name << "  " << item.price << '\n';
		ptr += sizeof(Item) + name.size() + 1;
	}

	std::free(data);
}




Product name [CR to end]: apple
Quantity: 2
Price: 4

Product name [CR to end]: pear
Quantity: 3
Price: 10

Product name [CR to end]:

2  apple  4
3  pear  10

Handy Andy,

I tried tweaking your code and I don't know if this makes any sense but it somehow works, here it is.

I made or tweak it within our limitations, but the problem is there is still an 'outStream' which ain't allowed for us.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main(){
    stringstream outStream;
    string productname;
    int subTotal{};
    double quantity = 0, price = 0, qprice{}, flist{};  // <--- "qprice" is never used here and "flist"'s value never changes.
    double lineTotal{}, priceTotal{};  // <--- Maybe this would be a better name.
    cout << fixed << showpoint;
    do{
        cout << "Product name: ";
        cin >> productname;
        if ( productname == "x" || productname == "X"){
            break;
        }
        cout << "Quantity: ";
        cin >> quantity;
        cout << "Price   : ";
        cin >> price;
        lineTotal = quantity * price;
        subTotal += quantity;
        priceTotal += lineTotal;
        outStream
            << setprecision(0) << setw(2) << quantity << "  "
            << left << setw(13) << productname
            << right << setprecision(4) << setw(6) << price << '\n';
    } while (1);
    cout << "- OFFICIAL RECEIPT -\n";
    cout << "Qty Product name   Price\n";
    cout << outStream.str();
    cout << "Total\n";
    cout <<  subTotal << " item(s)" << "      " << setprecision(2) << "    " << priceTotal;
    return 0;
}



Product name: Bread
Quantity: 3
Price : 65.75
Product name: Banana
Quantity: 4
Price : 9.20
Product name: Noodles
Quantity: 5
Price : 6.40
Product name: x
- OFFICIAL RECEIPT -
Qty Product name Price
3 Bread 65.75
4 Banana 9.2
5 Noodles 6.4
Total
12 item(s) 266.05
Last edited on
Pages: 123