当 c++ 需要一种数据类型并获取另一种数据类型时会发生什么?

What happens when c++ expects one data type and gets another?

本文关键字:数据类型 另一种 获取 什么 一种 c++      更新时间:2023-10-16

我是 c++ 的新手,正在用 c++11 制作一个程序,使用气泡排序算法对整数列表进行排序。当我这样做时,我注意到了一些奇怪的事情。这是我的代码:

#include <iostream>
void bubbleSort(int x) {
bool done;
int list[x] {0};
std::cout << "List:n";
for (int i=0;i<x;i++) {
std::cout<<i<<':';
std::cin>>list[i];
}
do {
done = true;
for (int i=0;i<x-1;i++) {
if (list[i]>list[i+1]) {
list[i] = list[i]+list[i+1];
list[i+1] = list[i]-list[i+1];
list[i] = list[i]-list[i+1];
done = false;
}
}
} while (not done);
for (int i:list) {
std::cout<<i<<' ';
}
std::cout<<std::endl;
}
int main() {
int n;
std::cout<<"Length of list: ";
std::cin>>n;
bubbleSort(n);
} 

如果我输入一个char而不是一个int程序会输出导致列表长度的数字,然后是一个等于列表长度的零字符串。

例如:如果我输入 5,则在输入处键入"k":

1:2:3:4:0 0 0 0 0 

我的问题是,为什么它会产生这种特定的输出?如果它获得错误的数据类型,我希望会出现错误。对不起,如果我的问题令人困惑。提前谢谢。

如果在输入需要数字时输入k。然后流将进入错误状态。

问题是您没有检查状态:

std::cin>>n;
// There could be an error in the line above.
// But you did not check for the error.

也在这里:

std::cin>>list[i];
// There could be an error in the line above.
// But you did not check for the error.

试试这个:

if (std::cin >> n) {
std::cout << "It worked I got the number: " << n << "n";
}
else
{
std::cout << "Failed to read a number.n";
}

以上是如何工作的。

那么operator>>的结果是对流的引用。因此,它将流中的值读入n但返回对流的引用。这允许您执行以下操作:

std::cin >> n >> x >> y;

每次operator>>后,您都会获得对流的引用以应用于下一个operator>>以便可以将读取链接在一起。

当您在布尔上下文中使用流时(像 if 或 while 这样的测试(,它会根据其内部状态将自身转换为布尔值。如果内部状态良好std::cin.good()则返回 true,否则返回 false。

因此,在它完成operator>>后,然后将自身转换为if statement的布尔值。如果它处于良好状态,您就知道读取有效。如果读取失败,它将设置内部失败状态,good()返回 false。

那么在你的代码中发生了什么。

读取失败,流的状态设置为失败。当读取失败时,首选行为是被读取的对象保持不变(这是 POD(标准(类型发生的情况,用户定义的类型可能会更加随意(。

因此,n的价值保持不变。

当您声明n

int n;

您没有定义初始值,因此它具有不确定的值。这意味着尝试读取该值是 UB。UB 不好。这意味着代码可以做任何事情(它已经做到了(。实际上(对于大多数系统(,这意味着变量具有不可知的值,并且是使用该变量的最后一个变量在该内存位置留下的任何值。

对于您的具体情况:

所以你先输入了 5,然后输入了k.

所以你的第一次阅读std::cin >> n;奏效了。 下一次读取std::cin>>list[i];失败。

这会将流的状态设置为坏。任何后续读取都不执行任何操作(直到将流状态重置为良好(。因此,您应该检测并修复流状态。

每次后续循环时,std::cin >> list[i]都不会执行任何操作,因为流处于错误状态。这意味着它将保持其原始值(在这种情况下定义为零0(。

同样,此处的正确操作是读取并检查流的状态。如果失败,请采取纠正措施:

if (std::cin >> list[i]) {
// Worked
}
else {
std::cerr << "Bad input. Try againn";
// reset the state of the stream
// before trying to read again.
std::cin.clear();
if (std::cin >> list[i]) {
std::cerr << "You got it correct this timen";
}
else {
std::cerr << "User not bright enough to use the app abortingn";
throw std::runtime_error("Failed Bad User");
}
}

附加说明

流的这种行为有利于读取用户输入。因为它允许自然流来检测和编写代码,以便用户解决问题。对于具有相同模式的所有现代语言,此设计实际上是相同的。

但是,当您有机器输入时,这不是一个好的流程(即,输入中预计不会有任何错误,如果有错误,则无法纠正它(。

对于读取机器输入,您可以设置流以引发错误。这允许您编写干净易读的代码,当出现问题时(当它们不应该出错时(,会抛出异常,导致应用程序正确终止(或者可能会捕获异常(。

std::cin.exceptions(std::ios::badbit); // Fail and Bad 
相关文章: