2017-03-16 39 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