我有一个print_number函数。
该功能检查是否存在数字前面的' - ',然后它反转该数字并取每个数字并打印出来。算法工作得很好但是如果我给-2.147.483.648(应该是整数的下限)它pritns -0并且我不知道为什么。
#include<stdio.h>
void print_char(char character)
{
printf("%c",character);
}
void print_number(int nr)
{
int reverse=0;
if (nr < 0)
{
print_char('-');
nr *= -1;
}
while(nr > 9)
{
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
print_char(nr + '0');
while(reverse)
{
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}
答案 0 :(得分:1)
当你做的时候
if (nr < 0)
{
print_char('-');
nr *= -1;
}
它将负数反转为正数。 如果你将它运行-2.147.483.648,你将收到
nr = 2.147.483.648 // == binary 1 0000000000000000000000000000000
由于INT在您的架构中是32 BIT变量(并且规格至少有16个BIT变量),因此'1'溢出它等等
nr = 0 // For gcc-like C realisation
接受ISO9899规范,signed int overflow的这种行为是实现指定的东西,可能无法预测共同。
如果您需要将程序用于较大的值,请使用long long值。 类似的东西:
#include<stdio.h>
void print_char(char character)
{
printf("%c",character);
}
void print_number(long long nr)
{
int reverse=0;
if (nr < 0)
{
print_char('-');
nr *= -1;
}
while(nr > 9)
{
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
print_char(nr + '0');
while(reverse)
{
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}
void main(void){
print_number(-2147483648LL);
}
并测试:
> gcc test.c
> ./a.out
-2147483648
答案 1 :(得分:1)
首先,INT的MAX和MIN范围分别为-2,147,483,648
和2,147,483,647
。
否定-2,147,483,648
表示正值2,147,483,648
会导致溢出1,因为它超出了MAX范围的范围。
此操作将产生相同的-2,147,483,648
。
其次,在整数反转过程中可能会遇到溢出
例如,在2147483647
的中间结果之后,反转746384741
会导致溢出
因此,您应该通过抛出异常或返回0来处理它。
第三,用于反转数字的循环不准确。它应该循环到while(nr != 0)
这是完整的代码。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main()
{
void reverseNumber(int);
reverseNumber(124249732);
return 0;
}
void reverseNumber(int nr)
{
printf("nr = %d\n", nr);
int reverse = 0;
bool neg = false;
if (nr < 0) {
neg = true;
nr *= -1;
}
while (nr != 0) {
int digit = nr % 10;
int result = reverse * 10 + digit;
if ((result - digit) / 10 != reverse) {
printf("ERROR\n");
exit(0);
}
reverse = result;
nr = nr / 10;
}
if(neg) {
printf("%c", '-');
}
printf("%d\n", reverse);
}
答案 2 :(得分:0)
nr *= -1;
是nr == INT_MIN
的问题,因为它是签名的整数溢出。结果是未定义的行为(UB)。最好避免。
更广泛的整数并不总是可用。
使用OP的一般方法,在nr
减少之前不要更改void print_number(int nr) {
int reverse = 0;
if (nr < 0) {
print_char('-');
//nr *= -1;
}
while (nr/10) { // new test
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
reverse = abs(reverse); // reverse = |reverse|
nr = abs(nr); // nr = |nr|
print_char(nr + '0');
while (reverse) {
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}
的符号。
class Detector : public QIODevice {
Q_OBJECT
Q_DISABLE_COPY(MasterDevice)
public:
enum CHANNEL_TYPE {
DataChannel,
ControlChannel
};
private:
QTcpSocket *controlDevice;
QTcpSocket *dataDevice;
QHostAddress hostAddress;
quint16 dataPort;
quint16 controlPort;
public:
explicit Detector(QObject *parent, QHostAddress hostAddress, quint16 dataPort, quint16 controlPort)
: QIODevice(parent)
, hostAddress(hostAddress)
, dataPort(dataPort)
, controlPort(controlPort)
{
controlDevice = new QTcpSocket(this);
connect(controlDevice, SIGNAL(readyRead()),this, SLOT(controlChannelReadReady()));
dataDevice = new QTcpSocket(this);
connect(dataDevice, SIGNAL(readyRead()),this, SLOT(dataChannelReadReady()));
}
virtual ~Detector() {}
bool open(OpenMode mode) override {
QIODevice::open(mode);
controlDevice->connectToHost(hostAddress, controlPort, QTcpSocket::ReadWrite);
dataDevice->connectToHost(hostAddress, dataPort, QTcpSocket::ReadOnly);
}
qint64 readData(char *data, qint64 maxSize) override {
QTcpSocket *socket;
switch ( currentReadChannel() ) {
case DataChannel:
socket = dataDevice;
break;
case ControlChannel:
socket = controlDevice;
break;
default:
return -1;
break;
}
return socket->read(data, maxSize);
}
qint64 writeData(const char * data, qint64 maxSize) override {
QTcpSocket *socket;
switch ( currentWriteChannel() ) {
case DataChannel:
socket = dataDevice;
break;
case ControlChannel:
socket = controlDevice;
break;
default:
return -1;
break;
}
return socket->write(data, maxSize);
}
private slots:
void controlChannelReadReady() {
emit channelReadyRead(ControlChannel);
}
void dataChannelReadReady() {
emit channelReadyRead(DataChannel);
}
};