C++:使用嵌套 if/else 语句对 while 循环进行故障排除
C++: Troubleshooting while loop with nested if/else statement
我正在学习 C++,有几个问题。
此程序应输入商品的名称和价格并将其输出到文本文件。当为项目名称输入标记值 999 时,while 循环应停止并将所有输入集(项目名称和价格)输出到文本文件。
这个程序有两个问题:
仅显示最新的一组输入(名称、价格)。如何将所有输入保存在内存中?
为项目名称输入 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;
}
为什么在检查条目的 if 语句中有一个额外的 cin 调用?
我觉得没必要。
对于您输入的问题,您只存储了最近输入的值,因为每次循环 运行s 再次它会覆盖变量。
要解决这个问题,您需要使用数组来存储项目。如果你想做到这样你就可以 运行 循环并根据需要输入尽可能多的输入,你将需要实现一个动态数组。
下面是动态数组的实现方法http://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/
如何使用 std::vector
首先,有几个包括:
#include <vector> // obviously. Can't do vectors without the vector header.
#include <limits> // for a trick I'll use later
创建结构 link 商品名称和价格
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
,请继续。非常正确。问题是,您第一次到达此处时尚未设置 item-name,从而在循环中强制执行了一些松鼠逻辑。阅读一般经验法则,然后进行测试。阅读前测试不是很有用。一方面,没有什么可测试的,但真正的问题是现在您正在使用未经测试的数据,或者必须包括另一个测试来捕获它。
阅读,然后测试。
{
cout<<"Enter the name of the item."<<'\n';
cin>>item_name;
获取项目名称。 Groovy-ish.
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
的巧妙之处在于 returns cin
。这使您可以堆叠命令。 cin>>a>>b>>c>>d
。 cin
及其所有流媒体兄弟都有一个内置的布尔运算符,您可以在测试中使用。如果cin
状态还不错,所有读取都成功完成,可以测试,会returntrue
.
这让您可以执行 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.
实际上,它只需要以数字开头。 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
添加构造函数并使用 vector
的 emplace_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
份要打印。 Stack Overflow 上有很多关于如何执行此操作的示例,但最好先尝试一下。
我正在学习 C++,有几个问题。
此程序应输入商品的名称和价格并将其输出到文本文件。当为项目名称输入标记值 999 时,while 循环应停止并将所有输入集(项目名称和价格)输出到文本文件。
这个程序有两个问题:
仅显示最新的一组输入(名称、价格)。如何将所有输入保存在内存中?
为项目名称输入 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;
}
为什么在检查条目的 if 语句中有一个额外的 cin 调用? 我觉得没必要。
对于您输入的问题,您只存储了最近输入的值,因为每次循环 运行s 再次它会覆盖变量。
要解决这个问题,您需要使用数组来存储项目。如果你想做到这样你就可以 运行 循环并根据需要输入尽可能多的输入,你将需要实现一个动态数组。
下面是动态数组的实现方法http://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/
如何使用 std::vector
首先,有几个包括:
#include <vector> // obviously. Can't do vectors without the vector header.
#include <limits> // for a trick I'll use later
创建结构 link 商品名称和价格
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
,请继续。非常正确。问题是,您第一次到达此处时尚未设置 item-name,从而在循环中强制执行了一些松鼠逻辑。阅读一般经验法则,然后进行测试。阅读前测试不是很有用。一方面,没有什么可测试的,但真正的问题是现在您正在使用未经测试的数据,或者必须包括另一个测试来捕获它。
阅读,然后测试。
{
cout<<"Enter the name of the item."<<'\n';
cin>>item_name;
获取项目名称。 Groovy-ish.
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
的巧妙之处在于 returns cin
。这使您可以堆叠命令。 cin>>a>>b>>c>>d
。 cin
及其所有流媒体兄弟都有一个内置的布尔运算符,您可以在测试中使用。如果cin
状态还不错,所有读取都成功完成,可以测试,会returntrue
.
这让您可以执行 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.
实际上,它只需要以数字开头。 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
添加构造函数并使用 vector
的 emplace_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
份要打印。 Stack Overflow 上有很多关于如何执行此操作的示例,但最好先尝试一下。