Hi, So I am working on a drink machine simulation. I have a text file that holds the prices, names and inventory. My problem is It won't let me set my prices at 1.00 or higher. Ex: I set the price to 1.50 in the text file then when the program reads the info from the text it will only read the cents so instead of 1.50 it will read .50

textfile looks like this:
Apple Juice 1.50 20
Mango Juice 1.50 20
Sprite Mix 1.90 20
Coca Cola 1.90 20

my code:

#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <cctype>
using namespace std;

struct Machine
{
    string name;
    double cost;
    int num;
};

void init(Machine []);
int menu(Machine[]); 
void payment(double);

int main()
{
    Machine drink[5];
    int choice;
    double made=0;
    init(drink);
    choice=menu(drink);
    while(choice!=5)
    {
        payment(drink[choice].cost);
        made+=drink[choice].cost;
        drink[choice].num--;
        choice=menu(drink);  
    }
    cout<<"Today the machine has made $"<<setprecision(2)<<fixed<<made<<endl;
    system("pause");
    return 0;
}

void payment(double p)
{
    double pay;
    cout<<"Your drink costs $"<<setprecision(2)<<fixed<<p<<endl;
    cout<<"Enter payment: ";
    cin>>pay;
    while(pay<0||pay>1.||pay<p)
    {
        cout<<"please insert the correct amount for your drink!\n";
        cout<<"maximum payment is $1.00\n";
        cout<<"Enter payment: ";
        cin>>pay;
    }
    cout<<"Your change is: $"<<setprecision(2)<<fixed<<pay-p<<endl;
    return;
}

void init(Machine d[])
{
    ifstream infile("DrinkMachineInventory.txt");

    if(infile.fail())
    {
        cout << "Could not find the file DrinkMachineInventory.txt \n";
        cout << "Exiting the program\n";
        exit(0);
    }

    int i=0;
    char ch;
    string word= "";

    while(!infile.eof())
    {
        word= "";
        ch = infile.get();
        while(true)
        {
            if(isdigit(ch) || ch == '\n')
                break;
            else
                word += ch;
            ch = infile.get();
        }

        if(word != "")
        {
            d[i].name = word;
            infile >> d[i].cost >> d[i].num ;
            i++;
        }
    }

    infile.close();   
}

int menu(Machine d[])
{
    int choice=8,i;
    bool soldout=true;
    while((choice<1||choice>6)||soldout)
    {
        soldout=false;
        cout<<"Menu\n";
        cout<<"      Drink      Cost\tleft\n";
        for(i=0;i<5;i++)
        {
            cout<<i+1<<". "<<setw(15)<<left<<d[i].name<<setw(5);
            cout<<setprecision(2)<<fixed<<d[i].cost<<"\t"<<d[i].num<<endl;
        }
        cout<<"6. Exit\n";
        cout<<"Enter Choice ";
        cin>>choice;
        if(choice<1||choice>6)
            cout<<"invalid entry\n";
        else
            if(d[choice-1].num==0)
            {cout<<"sold out\n";
        soldout=true;
        }
    }
    return choice-1;
}

Dani AI

Generated

The bug (prices like 1.50 becoming .50) comes from the name-reading loop consuming the leading digit before the stream extraction for cost. As pointed out, the loop breaks on the first digit and that digit has already been taken out of the input buffer, so >> d[i].cost only sees .50. Putback fixes this, and the two-word >> approach also works, but a more robust method is to read each line and parse tokens from the end (that way the name can have any number of words).

A safe, compact parser: read each line with getline, split tokens into a vector, pop the last two tokens as cost and qty, and join the rest as the name. Example:

string line;
int i = 0;
while (getline(infile, line) && i < 5) {
    if (line.empty()) continue;
    istringstream iss(line);
    vector<string> parts;
    string tok;
    while (iss >> tok) parts.push_back(tok);
    if (parts.size() < 3) continue;
    int qty = stoi(parts.back()); parts.pop_back();
    double cost = stod(parts.back()); parts.pop_back();
    string name = parts[0];
    for (size_t k = 1; k < parts.size(); ++k) name += " " + parts[k];
    d[i].name = name; d[i].cost = cost; d[i].num = qty; ++i;
}

Also address the payment logic: the current payment loop blocks amounts > $1.00. Replace the pay > 1.0 check with a simple while (pay < price) or use a do/while that validates input. For correctness and to avoid floating-point cents issues, consider storing money as integer cents (e.g., int cents = round(amount*100)), do all arithmetic in cents, then format output as dollars.

Final notes: stop using while (!infile.eof()); guard the array bounds when filling d[]; validate stoi/stod (or catch exceptions) so malformed lines are skipped gracefully. This ties back to 's suggestions and gives a reliable parsing + payment fix that handles prices >= $1.00.

Recommended Answers

All 4 Replies

Bump

The code where you read name:

ch = infile.get();
while(true)
{
    if(isdigit(ch) || ch == '\n')
    break;
    else
    word += ch;
    ch = infile.get();
}

textfile looks like this:
Apple Juice 1.50 20

In your code, you read the name as a series of single characters and break when the character is a digit. At that point Apple Juice will be held by the word string, but the 1 in 1.50 will have also been consumed.
If you want to read the file this way, then you'll need to putback the 1 held in ch before you call infile >> d[i].cost >> d[i].num;

Thanks! Okay so after the while loop add the instream infile >> d[i].cost;

If all the drink names are comprised of two words, then it would be far easier to read the file as follows.

    int i = 0;
    string word1, word2;

    while (infile >> word1 >> word2 >> d[i].cost >> d[i].num)
    {
        d[i].name = word1 + " " + word2;
        i++;
    }

You'll also need to fix your payment function. The problem should be obvious once you've correctly read the file and tested.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.