2016-02-13 103 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

我不会建议初学者开始处理原始指针和内存管理的路径;并非所有的教程都很好。 –