본문 바로가기
Algorithm/Algorithm

putnbr_base, 숫자를 진법으로 변환하기

by OdOp 관리자 2023. 12. 7.
SMALL

입력받은 숫자를 진법으로 변환하여 출력하는 방법에 대해 알아보도록 하겠습니다. 

 

우선 진법인 base가 적절한 형태로 되어 있는지 확인해 봅시다. 

 

 

OdOp_base

int    OdOp_base(char *base)
{
    int    n;
    int    i;

    n = 0;
    while (base[n] != '\0')
    {
        i = 0;
        if (base[n] == '+' || base[n] == '-')
            return (0);
        else if (base[n] == 32 || (base[n] >= 9 && base[n] <= 13))
            return (0);
        while (base[i] != '\0')
        {
            if (base[i] == base[n] && i != n)
                return (0);
            i++;
        }
        n++;
    }
    return (n);
}

진법 인자인 base 문자열에 부호가 있으면 부호를 표시할 수 없기 때문에 0을 리턴하게 했습니다. 

공백이 포함되어 있으면 tab과 구분을 할 수 없을 수 있기 때문에 역시 0을 리턴하게 했습니다. 

마지막으로 같은 것이 반복이 되면 0을 리턴하게 했습니다. 

 

모든 부분을 만족한다면 문자열의 길이를 리턴하여 몇 진법인지 파악하게 했습니다. 

 

다음으로 진법에 맞게 출력을 해야겠죠. 저희는 OdOp_putnbr_base함수에서 진행하도록 하겠습니다. 

 

 

OdOp_putnbr_base

void    OdOp_putnbr(int nbr, char *base, int n)
{
    if (nbr > n - 1)
    {
        OdOp_putnbr(nbr / n, base, n);
    }
    write(1, &base[nbr % n], 1);
}

nbr을 n으로 나누어서 나오는 나머지를 가지고 base에서 원하는 부분을 추출합니다. 

그전에 만약 nbr이 n-1보다 크다면 nbr을 n으로 나누어서 다시 OdOp_putnbr을 진행합니다. 

(재귀함수를 잘 모르시는 분들은 이링크를 참고해 주시길 바랍니다. https://hig0617.tistory.com/25)

 

이제 위의 함수를 합쳐봅시다. 

 

 

OdOp_putnbr_base

void    OdOp_putnbr_base(int nbr, char *base)
{
    int    n;

    n = OdOp_base(base);
    if (n < 2)
        return ;
    if (nbr < 0)
    {
        write(1, "-", 1);
        if (nbr == -2147483648)
        {
            OdOp_putnbr(-(nbr / n), base, n);
            write(1, &base[-(nbr % n)], 1);
            return ;
        }
        nbr = -nbr;
    }
    OdOp_putnbr(nbr, base, n);
}

여기서 특이한 부분은 n이 2 미만일 경우에는 0을 리턴하게 했습니다. 

진법이 1이거나 0이면 가능하지 않기 때문에 정수를 리턴할 수 없습니다. 

 

 

예시를 한번 살펴보겠습니다. 

#include <unistd.h>

int    OdOp_base(char *base)
{
    int    n;
    int    i;

    n = 0;
    while (base[n] != '\0')
    {
        i = 0;
        if (base[n] == '+' || base[n] == '-')
            return (0);
        else if (base[n] == 32 || (base[n] >= 9 && base[n] <= 13))
            return (0);
        while (base[i] != '\0')
        {
            if (base[i] == base[n] && i != n)
                return (0);
            i++;
        }
        n++;
    }
    return (n);
}

void    OdOp_putnbr(int nbr, char *base, int n)
{
    if (nbr > n - 1)
    {
        OdOp_putnbr(nbr / n, base, n);
    }
    write(1, &base[nbr % n], 1);
}

void    OdOp_putnbr_base(int nbr, char *base)
{
    int    n;

    n = OdOp_base(base);
    if (n < 2)
        return ;
    if (nbr < 0)
    {
        write(1, "-", 1);
        if (nbr == -2147483648)
        {
            OdOp_putnbr(-(nbr / n), base, n);
            write(1, &base[-(nbr % n)], 1);
            return ;
        }
        nbr = -nbr;
    }
    OdOp_putnbr(nbr, base, n);
}

int main(void)
{
    int nbr1 = 1530;
    char *base1 = "0123456789ABCDEF";
    write(1, "input nbr : 1530 | base : 0123456789ABCDEF\n", 43);
    write(1, "answer : 5FA\n", 13);
    OdOp_putnbr_base(nbr1, base1);
    return (0);
}

1530으로 어떻게 진법을 변환하는지 살펴보도록 하겠습니다. 

우선 1530은 15보다 크기 때문에 1530 / 16인 95로 다시 재귀함수를 돌게 됩니다. 

마찬가지로 95도 5로 다시 재귀함수를 돌립니다. 

이제 5는 더이상 15보다 크지 않습니다. 따라서 base의 index번호로 5번째 즉, 5를 출력합니다. 

95를 16로 나누면 15가 됩니다. 마찬가지로 base[15]는 F입니다. 

1530을 16로 나누면 10이 됩니다. 그러면 A를 출력하게 됩니다. 

그렇게 '5FA'를 출력하게 됩니다. 

LIST

'Algorithm > Algorithm' 카테고리의 다른 글

C언어, 거듭 제곱  (0) 2023.12.10
C언어, 피보나치 수열  (0) 2023.12.09
특정 진법 정수로 바꾸기  (1) 2023.12.05
문자열 소문자로 변환하기  (0) 2023.10.23
문자열 대문자로 변환하기  (0) 2023.10.22