2017-03-16 10 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; 
} 

オブジェクト:プログラムはメニューファイルを読み込みます。食べ物の名前は配列に行き、コストは配列になります。私が抱えている問題は、単語にスペースがあると、それはすべてのものを捨てるということです。私はgetl​​ineを使う必要があることを知っていますが、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 フォーマットされていないハンバーガー1.89 thatsのソーダ\t \t 1.29 アイスティー\t 1.29 –

+0

ので、各項目と価格は、独自のライン –

答えて

1

あなたは、その行の最初の数字を見つけるためにstd::find_if()を使用し、その後、それぞれの行を読み取るためにループ内でstd::getline()を使用することができます。これは文字列を分割する位置です。私はそれをあなたに残して、食べ物の名前から末尾の空白を取り除く。

#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ありがとうございました.2番目の例を追加しました。 – zett42

関連する問題