我正在编写一个不使用printf的打印整数函数。该函数应该能够接受需要打印的整数,输出的基数以及要在整数值之前插入的字符。我已经能够制作大部分代码;然而,一旦输入超过15亿,输出保持不变,大约为10亿。在平台上我使用INT_MAX是21.7亿,所以我知道这绝对是在int的范围内。另外,我想知道如何在没有静态数组的情况下创建这个函数:在我的情况下是baseDigs。
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "hw02.h"
int Pow(int a, int b);
void print_integer(int n, int radix, char* prefix){
if(radix == 0){
return -1;
}
char baseDigs[36]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','n','p','q','r','s','t','u','v','w','x','y','z'};
unsigned int buffer = n;
int dollar = 0;
int counter = 0;
int counter2 = 0;
int counter3 = 0;
int j = 0;
if (prefix[0] == '$'){
dollar++;
}
if(n < 0){
fputc('-', stdout);
buffer = -buffer;
}
while(prefix[j] != '\0'){
fputc(prefix[j], stdout);
j++;
}
while (buffer >= radix){
counter = 0;
counter2 = 0;
while((Pow(radix, counter)) <= buffer){
counter++;
}
counter--;
while(counter3 - counter > 1){
fputc('0', stdout);
counter3--;
}
counter3 = counter;
while((Pow(radix, counter)* counter2)<= buffer){
counter2++;
}
counter2--;
if (dollar > 0){
if(counter == 1){
fputc('.', stdout);
}
}
putchar(baseDigs[counter2]);
buffer-= Pow(radix,counter) * counter2;
}
while(counter3 > 1){
fputc('0', stdout);
counter3--;
}
fputc(baseDigs[buffer], stdout);
return;
}
int Pow(int a, int b){
if(b<0){
return (1/a) * Pow(a ,b-1);
}
else if (b==0) {
return 1;
}
else if (b==1){
return a;
}
else{
return a * Pow(a,b-1);
}
}
答案 0 :(得分:1)
问题出在你的Pow
函数的结果中:返回类型是int
(可能是32位),并且发生了溢出。我将在此期间使用int32_t
(在stdint.h
中定义),假设您的系统具有32位整数(大多数台式计算机都有,但如果这是针对嵌入式系统可能不是这样的话) ),以明确问题所在。
您使用Pow
在n
之后获得10的下一个幂,但是对于接近INT32_MAX的值(特别是1,000,000,000之后的任何值,这是10的第一个幂小于{ {1}})10的下一个幂无法表示为INT32_MAX
(因为int32_t
)导致溢出(我相信结果是未定义的,但实际上10,000,000,000 > INT32_MAX
返回的值1}}很可能是Pow
)。
因此,您可以通过增加-(INT32_max-10,000,000,000)
结果中使用的位数来解决此问题,方法是让它返回Pow
(或int64_t
,如果您不想使用long long int
)
另外,请不要忘记按我在上面的评论中提到的那样签署 stdint.h
。您的编译器应该已经捕获并发出警告,如果没有,那么您可能没有编译启用所有警告。在一些(大多数?)编译器中,通过将标志buffer
传递给它来启用它。
请参阅chux关于为何-Wall
签名不正确的解决方案的评论(使用buffer
是完全定义的并且有效)。考虑始终使用unsigned
以避免溢出和类型转换。