2016-02-13 68 views
0

我正在學習C++並有幾個問題。C++:循環嵌套if/else語句時的故障排除

此程序應該輸入項目的名稱和價格並將其輸出到文本文件。當爲項目名稱輸入標記值999時,while循環應該停止並將所有輸入組(項目名稱和價格)輸出到文本文件。

我有兩個問題與此程序:

  1. 只有最近的一組輸入(名稱,價格)被顯示。我如何將所有輸入保存在內存中?

  2. 爲項目名稱輸入999不會導致程序退出。相反,該程序停止顯示提示。如何正確停止程序?

我應該使用for循環,但我不知道如何實現。

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

using namespace std; 

int main() 
{ 
    string item_name; 
    double price; 
    int item_number; 

    const string SENTINEL = "999"; 

    ofstream myfile ("invoice1.txt"); 


    while(item_name != SENTINEL) 
    { 
     cout<<"Enter the name of the item."<<'\n'; 
     cin>>item_name; 

     if (item_name == SENTINEL) 
     { 
      cin>>item_name; 
      myfile<<"Thank you for your entries"<<'\n'; 
      myfile<<item_name<<"#"<<price<<endl; 
      myfile.close(); 

      break; 
     } 
     else 
     { 
      cout<<"Enter the price of the item."<<'\n'; 
      cin>>price; 
     } 
    } 

    myfile<<"Thank you for your entries"<<'\n'; 
    myfile<<item_name<<"#"<<price<<endl; 
    myfile.close(); 

    return 0; 
} 
+2

編譯器可能不關心空格式格式,但人類可以。請在將來正確縮進您的代碼。 –

回答

0

如何用std::vector

首先做到這一點,一些包括:

#include <vector> // obviously. Can't do vectors without the vector header. 
#include <limits> // for a trick I'll use later 

創建鏈接的項目名稱的結構價格

struct item 
{ 
    string name; 
    double price; 
}; 

和使該結構的載體

vector<item> items; 

然後你在一個名稱和價格讀取之後,東西它在結構與材料結構到載體。

item temp; 
temp.name = item_name; 
temp.price = price; 
items.push_back(temp); 

關於爲什麼while循環不起作用......這將通過散步。

while(item_name != SENTINEL) 

這是一個好的開始。如果item_name不是SENTINEL,繼續。非常正確。事情是,物品名稱在你第一次來到這裏時並沒有被設定好,在循環內強制一些松鼠邏輯。一般的經驗法則是讀取,然後測試。閱讀之前的測試並不是那麼有用。首先,沒有什麼可以測試的,但真正的問題是現在你使用的是未經測試的數據,或者必須包含另一個測試來捕捉它。

閱讀,然後測試。

{ 
    cout<<"Enter the name of the item."<<'\n'; 
    cin>>item_name; 

獲取項目名稱。 Groovy的雜交。

if (item_name == SENTINEL) 
    { 
     cin>>item_name; 

好的。不錯,但爲什麼要在這裏獲得另一個item_name?

 myfile<<"Thank you for your entries"<<'\n'; 
     myfile<<item_name<<"#"<<price<<endl; 
     myfile.close(); 

     break; 

break退出環或switch。所以我們走了。

} 
    else 
    { 
     cout<<"Enter the price of the item."<<'\n'; 
     cin>>price; 

閱讀數值有一些危險,你必須小心。最大的問題是,如果輸入的用戶無法變爲price,則cin將進入錯誤模式,直到錯誤被清除後纔會恢復。在您再次嘗試獲取價格之前,需要刪除垃圾數據。

關於cin >> x的整潔的事情是它返回cin。這可以讓你堆疊命令。 cin>>a>>b>>c>>dcin,以及它的所有流媒體同道,都有一個內置的布爾運算符,您可以在測試中使用它。如果cin仍處於良好狀態,則所有讀取都已成功完成,則可以進行測試並返回true

這可以讓你做一些像if (cin>>a>>b>>c>>d)之類的東西,並測試所有的閱讀都很好。

} 
} 

應用讀取,然後進行測試,我們得到

while(cin>>item_name && // read in an item name 
     item_name != SENTINEL) // and then test that it isn't the sentinel 

代碼這個傻瓜看的有點是要做到這一點,最安全的方式。它甚至會趕上並退出cin突然結束。 cin不會經常發生,但這是測試文件結尾的好方法。

{ 
    while (!(cin >> price)) // keep looping until the user gives a number 
    { // if we're here, the user didn't give a good number and we have to clean up 
     // after them. Bad user. Bad. Bad. 

另外,不要用文件來做這個技巧。該文件可能已經結束。在繼續清理之前,您必須測試文件的結尾並退出。

 // clear the error 
     cin.clear(); 
     // throw out everything the user's typed in up to the next line 
     cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
    } 
    // user got out of the while of doom. They must have entered a number. 

實際上,Welllll只是從一個數字開始。 cin >>是非常愚蠢的,將讓1234abcd通過,採取1234和離開abcd爲下一次閱讀。這會給你帶來一些令人討厭的驚喜。在這種情況下,abcd將作爲下一個item_name結束。本來應該是下一個item_name將成爲下一個price和壞ju ju從那裏滾。

現在回到代碼。

item temp; // make a temporary item 
    temp.name = item_name; // set the values correctly 
    temp.price = price; 
    items.push_back(temp); // put them in the list. 

您可以通過添加一個構造函數來item和使用vectoremplace_back方法在這裏保存一些工作。看看它。非常便利。

} 

而且又沒有解說詞:

while(cin>>item_name && // read in an item name 
     item_name != SENTINEL) // and then test that it isn't the sentinel 
{ 
    while (!(cin >> price)) // keep looping until the user gives a number 
    { // if we're here, the user didn't give a good number and we have to clean up 
     // after them. Bad user. Bad. Bad. 
     // clear the error 
     cin.clear(); 
     // throw out everything the user's typed in up to the next line 
     cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
    } 
    // user got out of the while of doom. They must have entered a number. 
    item temp; // make a temporary item 
    temp.name = item_name; // set the values correctly 
    temp.price = price; 
    items.push_back(temp); // put them in the list. 
} 

現在你有一個vector充滿item s到打印。堆棧溢出是如何做到這一點的例子,但最好先對它進行處理。

-2

爲什麼在if語句檢查條目時你有額外的cin調用? 我認爲這不是必要的。

對於輸入問題,您只存儲最近輸入的值,因爲每次循環再次運行時都會寫入變量。

要解決此問題,您將需要使用數組來存儲項目。如果你想讓它可以運行循環,根據需要輸入儘可能多的輸入,你將需要實現一個動態數組。

這裏是如何實現動態數組http://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/

+1

呃,爲什麼不建議使用['std :: vector'](http://en.cppreference.com/w/cpp/container/vector)而不是重新發明輪子? –

+0

他正在學習,所以我認爲最好從大多數人學習的方式入手。 –

+1

我不會建議初學者開始處理原始指針和內存管理的路徑;並非所有的教程都很好。 –