如何捕获一个unsigned
值而无需强制转换?
我正在编写一个简单的程序来计算数字数组的LCF和GCD。为了正确地计算它们,数字应该始终是正整数,因为我选择了类型“ unsigned long long int
”。但是,我仍然没有找到一种方法来防止用户不强制转换而输入负值。
每当我使用std::cin >> variable
时,程序都会允许用户输入一个负数。如果是无符号值,则数字将是类型大小的范围减值。对于unsigned short
整数,如果用户输入-5
,则变量中存储的值为65.531
。
这是我要改进的部分代码:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef unsigned long long int ulli;
/* many lines of code, variables already declared */
// array_list_of_numbers is of type UNsigned long long int
// var_verify_if_negative is of type signed long long int
cout << "Please inform the numbers." << endl;
for ( iterador1 = 0 ; iterador1 < size_of_the_list ; ++iterador1){
cout << "Please, inform number "<< iterador1+1 << ": ";
cin >> var_verify_if_negative;
while (var_verify_if_negative <= 0){
cout << "Number must be equal or greater than 1!" << endl;
cout << "Try again: ";
cin >> var_verify_if_negative;
/*end while*/}
array_list_of_numbers[iterador1] = (ulli)var_verify_if_negative; // << here is the casting
/*end for*/}
但是,如果我使用带符号变量的强制转换,则根本没有必要使用无符号数据类型。最好将变量声明为已签名并执行检查。
原始代码为:
cout << "Please inform the numbers." << endl;
for ( iterador1 = 0 ; iterador1 < size_of_the_list ; ++iterador1){
cout << "Please, inform number "<< iterador1+1 << ": ";
cin >> array_list_of_numbers[iterador1];
/*end for*/}
哪个允许输入错误。
如何测试用户是否使用std::cin
输入了签名值?
答案 0 :(得分:1)
不幸的是,没有特定的提取器拒绝标准流的带符号整数,而是将带符号整数转换为无符号值(对于负数,这实际上是未定义的行为)。
但是,您的整个方法还是有缺陷的。如果您要禁止小于0的数字,最好的办法是实际接受带符号的整数,然后检查该数字是否大于零并在不大于0的情况下报告错误(并拒绝输入)。>
答案 1 :(得分:1)
为什么不简单地读一个(带符号的)long并在它为负数时拒绝它,否则使用它呢?
如果您确实需要完整的无符号长整数,则需要首先读取一个字符串,检查它是否以'-'开头(并拒绝),否则转换为无符号长整数。
答案 2 :(得分:1)
最好的情况是,当预期类型为无符号类型时,如果输入负数,则流提取器将报告失败。
unsigned int num;
while ( !(in >> num) )
{
std::cerr << "Wrong input. Try again...";
}
但是,标准指定即使期望的类型是无符号类型,也可以输入负数。
当类型是无符号类型时,标准库在核心转换逻辑中使用%u
格式说明符。来自https://en.cppreference.com/w/cpp/locale/num_get/get:
如果
v
的类型是无符号的,将使用转换说明符%u
现在,如果您查看标准库如何处理%u
(https://en.cppreference.com/w/cpp/io/c/fscanf#Parameters),将由strtoul
执行转换。
如果减号是输入序列的一部分,则从数字序列计算出的数值将被否定,就好像结果类型中的一元减号一样,这将应用无符号整数环绕规则。
您最好的选择是读入带符号的类型,并确保它是一个非负数,然后再使用它。