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

时间:2017-12-09 20:27:45

标签: c

我正在编写一个不使用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 个答案:

答案 0 :(得分:1)

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

您使用Pown之后获得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以避免溢出和类型转换。