首页 文章

如何使打印整数函数(没有printf)输出INT_MAX

提问于
浏览
-2

我正在编写一个不使用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);
    }
}

1 回答

  • 1

    问题在于 Pow 函数的结果:返回类型是 int (可能是32位),并且发生溢出 . 我将在此期间使用 int32_t (在 stdint.h 中定义),假设您的系统具有32位整数(大多数台式计算机都有,但如果这是针对可能不是这种情况的嵌入式系统),则要明确问题是 .

    你使用 Pown 之后获得10的下一个幂,但是对于接近INT32_MAX的值(特别是1,000,000,000之后的任何值,这是10的第一个幂小于 INT32_MAX ),10的下一个幂不能表示为a int32_t (因为 10,000,000,000 > INT32_MAX )导致溢出(我相信结果是未定义的,但实际上 Pow 返回的值很可能是 -(INT32_max-10,000,000,000) ) .

    所以,你可以通过增加 Pow 结果中使用的位数来解决这个问题,方法是让它返回 int64_t (或 long long int ,如果你不想使用 stdint.h

    另外,不要忘记按照我在上面的评论中提到的那样对缓冲区进行签名 . 您的编译器应该捕获并发出警告,如果没有,那么您可能没有编译启用所有警告 . 在一些(大多数?)编译器中,通过将标志-Wall传递给它来启用它 .

    编辑:

    请参阅chux关于为什么使 buffer 签名不是正确解决方案的评论(使用 unsigned 是完全定义的并且有效) . 考虑始终使用 int64_t 以避免溢出和类型转换 .

相关问题