2017-03-16 77 views
0
#include <iostream> 
#include <iomanip> 
#include <string> 
#include <fstream> 


using namespace std; 


const int N = 20; 

void instructions() 
{cout << "* To quit or print a bill, enter 0 when asked to Enter an item number." << endl; 
cout << endl; 
cout << "* To cancel orders, enter the item number of the item to cancel" << endl; 
cout << " and then enter the negative of the number of orders to cancel." << endl; 
cout << " (e.g., -3 to cancel 3 orders of the selected item)." << endl; 
cout << endl; 
cout << "--- MENU --------------------" << endl; 
} 
int main(int argc, char *argv[]) 
{ 

ifstream infile; // init input file 
string foods; // food name 
float costs; // food cost 
string food[N]; // food array 
float cost[N]; // cost array 
int cnt; // counter 
char tab = '\t'; 


cout << setprecision(2) << fixed; // shows decimal two places 
// below if file argument isn't found return error message 
if(argc != 2) 
{ 
    cerr << "File not found." << endl; 
    return 1; 
} 

infile.open(argv[1]); // opens the user inputed file 
    cnt = 0;// sets up counter for while loop 
     infile >> foods >> costs; // initalizes the while loop 


instructions(); 

// While loop reads in information from input file and uses a count. 
while(infile && cnt < N) 
{ 

    food[cnt]= foods; 
    cost[cnt] = costs; 
    cout << cnt << ": " << food[cnt] << tab << cost[cnt] << endl; 
    ++cnt; 

    infile >> foods >> costs; 
} 

cout << "Enter item number (0 to print bill): "; 
cout << endl << cnt; 

return 0; 
} 

对象:程序读入菜单文件。食物的名字进入阵列,成本进入阵列。我遇到的问题是,当文字中有空格时,它会抛出所有的东西。我知道我需要使用getline,但我不确定如何将getline分解为名称/成本。有人可以帮助或显示某种类型的示例。有没有办法打破getline?

Hamburger 1.89 
Cheeseburger 2.29 
French Fries 1.59 
Onion Rings 1.59 
Soda   1.29 
Iced Tea  1.29 
+0

什么是菜单文件是什么样子?物品和价格的名称分开了什么? – harmic

+0

汉堡\t 1.89 汉堡\t 2.29 炸薯条\t 1.59 洋葱圈\t 1.59 纯碱\t \t 1.29 冰茶\t 1.29 –

+0

那不是格式化的汉堡包1.89是它自己的行,以便每个项目的价格有自己的行 –

回答

1

可以使用std::getline()在循环读取每一行,然后使用std::find_if()找到该行的第一位。这是分割字符串的位置。我会把它留给你来修剪食物名称中的尾随空白。

#include <iostream> 
#include <sstream> 
#include <string> 
#include <algorithm> 
#include <cctype> 

int main() 
{ 
    using namespace std; 

    istringstream is(
R"(Hamburger 1.89 
Cheeseburger 2.29 
French Fries 1.59 
Onion Rings 1.59 
Soda   1.29 
Iced Tea  1.29 
)"); 

    string s; 
    while(getline(is, s)) 
    { 
     auto it = find_if(begin(s), end(s), [](char c){ return isdigit(c); }); 
     if(it != end(s)) 
     { 
      string name(begin(s), it); 
      string price(it, end(s)); 
      cout << "\nFood: " << name << "\nPrice: " << price << endl; 
     } 
    }  
} 

Live Demo.

更强大的解决方案

正如评论者指出,如果食品名称中包含数字的上述解决方案不起作用。为了解决这个问题,我们可以用reverse_iterator来解析每一行。 reverse_iterator将通过调用免费函数crbegin()(const reverse begin)和crend()(const reverse end)获得。

如果你的STL的版本不提供这些的是,你可以通过相关std::string方法line.crbegin()line.crend()(删除c如果连这些都没有用)取代它们。

找到的第一个令牌是我们的价格。从价格的“反转端”,我们进一步向后解析,跳过名称和价格之间的空白。

#include <iostream> 
#include <sstream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <cctype> 

int main() 
{ 
    using namespace std; 

    istringstream is(
R"(Hamburger 1.89 
Cheeseburger 2.29 
French Fries 1.59 
Onion Rings 1.59 
Soda 24  1.29 
Iced Tea  free 
)"); 

    string line; 
    while(getline(is, line)) 
    { 
     auto itLineRevEnd = crend(line); 

     // Find end (reverse begin) of price token. 
     auto itPriceRevBegin = find_if(crbegin(line), itLineRevEnd, [](char c){ return ! isspace(c); }); 
     if(itPriceRevBegin != itLineRevEnd) 
     { 
      // Find begin (reverse end) of price token. 
      auto itPriceRevEnd = find_if(itPriceRevBegin, itLineRevEnd, [](char c){ return isspace(c); }); 
      if(itPriceRevEnd != itLineRevEnd) 
      { 
       // Find end (reverse begin) of name. 
       auto itNameRevBegin = find_if(itPriceRevEnd, itLineRevEnd, [](char c){ return ! isspace(c); }); 
       if(itNameRevBegin != itLineRevEnd) 
       { 
        // Call reverse_iterator::base() to turn them into forward iterators (otherwise strings would be reversed). 
        string name(itLineRevEnd.base(), itNameRevBegin.base()); 
        string price(itPriceRevEnd.base(), itPriceRevBegin.base()); 

        cout << "\nFood: \"" << name << "\""; 
        cout << "\nPrice: "; 

        try 
        { 
         double priceNum = stod(price); 
         cout << priceNum << endl;  
        } 
        catch(std::exception& e) 
        { 
         // Conversion error or out-of-range. 
         cout << "ERROR" << endl; 
        }      
       }  
      }    
     } 
    }  
} 

Live Demo.

输出:

Food: "Hamburger" 
Price: 1.89 

Food: "Cheeseburger" 
Price: 2.29 

Food: "French Fries" 
Price: 1.59  

Food: "Onion Rings" 
Price: 1.59 

Food: "Soda 24" 
Price: 1.29 

Food: "Iced Tea" 
Price: ERROR 
+0

一个问题这个解决方案是如果名称本身包含任何数字。更好的方法可能是从每行末尾开始寻找第一个非空间 – harmic

+0

@harmic感谢您的建议,我已经添加了第二个示例。 – zett42