【发布时间】:2020-04-16 05:31:12
【问题描述】:
这是我的代码:
int amount;
cout<<"How many books are you donating? ";
cin>>amount;
string donation[amount];
cout<<"Enter the titles:"<<endl;
for (int i=0; i<amount; i+=1)
{
getline(cin.ignore(numeric_limits<streamsize>::max(), '\n'), donation[i]);
}
cout<<endl<<"You donated these:";
for (int j=0; j<amount; j+=1)
{
cout<<donation[j]<<endl;
}
即使我只为amount 输入了 3,它也接受 5 个值。然后它只打印值 1、3 和 5。
如果我直接写成getline(cin.ignore(), donation[i]);或者getline(cin.ignore(1, '\n'), donation[i]);,那么输出就变成了这样:
How many books are you donating? 3
Enter the titles:
book1
book2
book3
You donated these:
book1
ook2
ook3
我应该在cin.ignore() 中写什么以使其仅忽略\n 值?
【问题讨论】:
-
string donation[amount];-- 这不是有效的 C++。 C++ 中的数组的大小必须由常量表达式表示,而不是运行时值。 C++ 中的动态数组是通过使用std::vector<std::string> donation(amount);来完成的,这种方式不仅使程序有效 C++,而且您还可以通过使用at()来检查数组边界,就像在getline(cin, donation.at(i));中一样。如果你这样做了,你会看到一个异常抛出。 -
问题已经指出。但至于为什么你的理论上不正确的版本似乎有效,它归结为一种叫做未定义行为的阴险。索引数组越界将导致它,写入和读取越界内存也是如此。只是需要注意和避免的事情,因为它可能会导致难以在大型程序中找到错误,尤其是当原因似乎与错误无关时。
-
@Mat 我用我尝试过的方法 (
cin.ignore()) 编辑了这个问题,但它仍然没有像我希望的那样工作。 -
不要将格式化 I/O(如
cin >> amount)与面向行的输入(getline(cin, ....))混合。不同的方法以不同的方式处理换行符(并且以不同的方式处理错误),因此可以像您描述的那样给出奇怪的交互(例如丢失的输入)。相反,使用getline()从cin读取所有内容。由于getline()读取一个字符串,您可以解析该字符串以从中提取(例如)amount的值。此外,string donation[amount]值amount不是编译时常量的 C++ 无效(尽管不幸的是,一些编译器支持它作为非标准扩展)