무슨 일로 C 하셨습니까?

[C] 진수 변환기__1.0 본문

C - 이걸 굳이?/유틸리티

[C] 진수 변환기__1.0

OJJJ 2020. 8. 18. 21:43

프로젝트를 진행하다가 진수변환기가 필요한 일이 생겼다.

 

진수변환하는 코드야 널리고 널렸겠지만, 직접 만들어 보기에 아주 적절한 난이도 인것 같아서 직접 만들어보기로 한다.

 


진수변환의 개념은 익숙하다. 그런데 코드로 구현하기가 막막하다.

개념부터 다시 생각해보도록 하자

 

10진수 255를 2진수로 바꿔보면

255 -> 11111111 로 나타낼 수 있는데

 

255는 1 + 2 + 4 + 8 + 16 + 32 + 64 +128 로 쪼갤 수 있고

2진수 11111111의 각 각 1은 제일 낮은 비트(제일 오른쪽) 부터 1, 2, 4, 8, 16, 32, 64, 128 을 의미한다.

 

즉, 128*1 + 64*1+ 32*1 + 16*1 + 8*1 + 4*1 + 2*1 + 1*1 = 255 이다.

 

 

10진수 250을 2진수로 바꿔 본다면

 

128*1 + 64*1 + 32*1 + 16*1 + 8*1 + 4*0 + 2*1 + 1*0 = 250 이므로

250 -> 11111010 일 것이다.

 

이것을 로직적으로 생각하면, 10진수를 2진수로 나누어 몫이 0이 나올때까지 반복하는데

 

250 / 2 = 125 ... 0

125 / 2 = 62 ... 1

62 / 2 = 31 ... 0

31 / 2 = 15 ... 1

15 / 2 = 7 ... 1

7 / 2 = 3 ... 1

3 / 2 = 1 ... 1

1 / 2 = 0 ... 1

 

여기서 각 나머지를 아래에서 부터 위로, 제일 높은 비트에서 제일 낮은 비트로 채워주면 된다.

 

이토록 2진수는 매우 간단하다. 8진수나 16진수야 2진수에서 비트끼리 묶으면 그만이지만

3진수나 7진수로 변환을 해야한다면 어떻게 할까

 

2진수와 같은 방법으로 10진수를 나누어 보도록하자

 

10진수 220을 3진수로 나누어보면

 

220 / 3 = 73 ... 1

73 / 3 = 24 ... 1

24 / 3 = 8 ... 0

8 / 3 = 2 ... 2

2 / 3 = 0 ... 2

 

22011이 나온다.

1*1 + 3*1 + 9*0 + 27*2 + 81*2 = 220으로 정확하다.

 

혹시 모르니 다른 숫자로 다른 진수로 변환해보도록하자

 

10진수 391을 7진수로 변환해보면

 

391 / 7 = 55 ... 6

55 / 7 = 7 ... 6

7 / 7 = 1 ... 0

1 / 7 = 0 ... 1

 

1066, 1*6 + 7*6 + 49*0 + 343*1 = 391 매우 정확하다.

 

로직을 정확히 찾은 것 같다. 이제 코드로 구현해보자


함수 이름은 일단 비워두도록 하자

 

각 인수는 입력 숫자와 변환할 비트로 한다.

( 입력 숫자는 기본 10진수로 ToBit가 8일 경우, 10진수를 8진수로 바꾸는 것으로 하겠다. )

 

void f(int Number, int ToBit) {}

 

앞서 직접 구해본 로직을 구현해보자.

입력 값을 변환하려는 비트로 나누어 몫이 0이 될때까지 반복할 것이다.

 

int Temp_Number = Number;

while (1) {
	if (Temp_Number == 0) break;
}

 

그런데 고민거리가 하나 발생했다.

반환 데이터의 자료형을 int형이나 float형으로 하기에는 진수가 헷갈리기도하고

11진수 그 이상의 진수에서는 문자가 사용될 것이니 정수 배열보다는 문자열로 하려 하는데

문자열의 길이를 모른다. 그렇다고 문자열의 길이를 무작정 크게 잡고싶지는 않다.

 

그렇다면 문자열의 길이가 얼만큼 발생할지 계산을 해서 동적으로 문자 배열을 할당하도록 하겠다.

우리는 변환된 숫자의 최대 비트가 몇자리인지만 체크하면 된다.

 

int MSB = 1;
int temp = ToBit;

while (1) {
	if (temp > Number) break;
	else {
		temp *= ToBit;
		MSB++;
	}
}
char* result = (char*)malloc(sizeof(char) * MSB+1);
result[MSB] = 0;

 

동적할당을 더 크게하는 이유는 문자열에 종료 문자를 추가하기 위해서이다.

 

나머지 코드는 간단하다. 그냥 원래 숫자를 반복해서 나누어서 몫과 나머지를 적절히 처리해주면 된다.

 

result[--MSB] = (Temp_Number % ToBit)+'0';
Temp_Number = Temp_Number / ToBit;

 

문자열에 숫자를 문자로 변환시켜서 넣는 것은 다음과 같이 하는 것이 제일 간단한 것같다.

그리고 문자열을 반환해주면 되겠다.

 

최종 코드는 다음과 같다.

 

#include<stdio.h>
#include<stdlib.h>

char* NumberConverter(int Number, int ToBit) {

	
	int MSB = 1;
	int temp = ToBit;
	
	while (1) {
		if (temp > Number) break;
		else {
			temp *= ToBit;
			MSB++;
		}
	}

	char* result = (char*)malloc(sizeof(char) * (MSB+1));
	result[MSB] = 0;

	int Temp_Number = Number;

	while (1) {
		if (Temp_Number == 0) break;
		
		result[--MSB] = (Temp_Number % ToBit)+'0';
		Temp_Number = Temp_Number / ToBit;
	}

	return result;
}

 

이 함수가 정상 작동하는지는 직접 테스트해보길 바란다. 

 

 * 동적할당을 했으니 free()를 통해 메모리를 release해주기 바란다. (release의 뜻이 생각안난다.)

 

 

 

 

 

Comments