Work Checker / String Manipulation

Hi, im currently working on this problem.

Task Description
The menu for the local Lone Star Diner is as follows:
COFFEE – $0.50
SODA - $1.00
MILKSHAKE - $2.13
PANCAKES - $3.25
WAFFLES - $3.92
HAMBURGER – $4.01
PASTA - $4.44
HOTDOG - $2.98
CHIPS - $0.65
FRIES - $0.99
Write a program that takes a given list of menu items that have been ordered and displays the total bill.
Program Input
The customer’s order is contained in an input file (c:\codewars\prob11.in). The input file will contain a list
of items ordered by the customer. Each item will be on a separate line. “END” will signify the end of the
order.
COFFEE
COFFEE
WAFFLES
PASTA
END
Oh, and by the way, when the diner gets really busy, the waiters get a little sloppy with the order entry so
there may be a typo (or not) in each line of the order. A typo will only consist of a single missing letter or
having a single wrong letter per each item name, but not both. For example:
CONFEE
OFFEE
WAIFLES
PASTE
END
You can assume END will always be spelled correctly.
Program Output
The total cost of the order, as follows:
Your total is $9.36



I have gotten past the part of the correct problem, where my program works fine and gets the total. The trouble i am having is with the incorrect word plus the missing letter. I know its going to involve string manipulation.

Here is the code i have so far, and yes i know else if statement wasnt efficient.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
double totalCost = 0.00;

int counter;

ifstream theItems;
theItems.open("in.txt");

string currentItem;

while(theItems >> currentItem)
{
if(currentItem == "COFFEE")
{
totalCost = totalCost + 0.50;
}else if(currentItem == "SODA")
{
totalCost = totalCost + 1.00;
}else if(currentItem == "MILKSHAKE")
{
totalCost = totalCost + 2.13;
}else if(currentItem == "PANCAKES")
{
totalCost = totalCost + 3.25;
}else if(currentItem == "WAFFLES")
{
totalCost = totalCost + 3.92;
}else if(currentItem == "HAMBURGER")
{
totalCost = totalCost + 4.01;
}else if(currentItem == "PASTA")
{
totalCost = totalCost + 4.44;
}else if(currentItem == "HOTDOG")
{
totalCost = totalCost + 2.98;
}else if(currentItem == "CHIPS")
{
totalCost = totalCost + 0.65;
}else if(currentItem == "FRIES")
{
totalCost = totalCost + 0.99;
}else
{
totalCost = totalCost;
}

}

cout<<"Your total is: "<<totalCost<<endl;
return 0;
}

and as the problem states

"Oh, and by the way, when the diner gets really busy, the waiters get a little sloppy with the order entry so
there may be a typo (or not) in each line of the order. A typo will only consist of a single missing letter or
having a single wrong letter per each item name, but not both"

so as you see in the program, it takes every line of my input file, and checks it.
I have no idea how to approach it, any ideas?

Thanks in advance
Soundex might be an option: https://en.wikipedia.org/wiki/Soundex
I did a quick test at https://www.functions-online.com/soundex.html with COFFEE and it gives the same value for COFEE, CFFEE, COFFE
> A typo will only consist of a single missing letter or having a single wrong letter per each item name, but not both.

In other words, Levenshtein distance == 1 https://en.wikipedia.org/wiki/Levenshtein_distance

The simple recursive algorithm should suffice (break out of the recursion if distance > 1) : https://en.wikipedia.org/wiki/Levenshtein_distance#Recursive
Don't forget to normalize your input. You'll want all of the letters you are testing against each other to be in the same case to cut the number of checks you have to do in half. "std::tolower()" should be adequate: http://en.cppreference.com/w/cpp/string/byte/tolower
Last edited on
First, let me congratulate you. Your code is well written for a beginner. You recognized that the "and by the way" part is an extension of the problem and you solved the easy part first. You also recognized that the lookup function is inefficient. You have a knack for programming.

You can make the code a little cleaner by moving the menu data into an array of structures and then write a function to find the appropriate entry in the menu:

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
struct MenuItem {
    const char *name;
    double cost;
};

MenuItem menu[] = {
    { "COFFEE", 0.50 },
    { "SODA", 1.00 },
    { "MILKSHAKE", 2.13 },
    { "PANCAKES", 3.25 },
    { "WAFFLES", 3.92 },
    { "HAMBURGER", 4.01 },
    { "PASTA", 4.44 },
    { "HOTDOG", 2.98 },
    { "CHIPS", 0.65 } ,
    { "FRIES", 0.99 }
};

// Find the menu item from the name. Returns a pointer to the item
// or NULL if not found.
MenuItem *findItem(const string &name)
{
    for (MenuItem &item : menu) {
        if ( name == item.name) {
            return &item;
        }
    }
    return nullptr;
}


Then the code to track the order in main() looks like this:
1
2
3
4
5
6
7
8
    while (theItems >> currentItem) {
        MenuItem *item = findItem(currentItem);
        if (item) {
            totalCost += item->cost;
        } else {
            cout << "Can't find " << currentItem << '\n';
        }
    }

Note the use of += to add to totalCost.

If you have findItem() then you can easily add the tolower() code that Computergeek01 suggested, along with the Levenshstein distance code that JLBorges suggested.
Topic archived. No new replies allowed.