본문 바로가기

별걸다하는 IT/프로그래밍언어

[C언어]바이너리(binary)에서 BCD코드로 또는그 반대로 변환하기, 아스키코드<->BCD코드 변경 구현하기

안녕하세요 주인장입니다.

저번시간에 BCD코드 개념에 대해서 살펴봤다면 오늘은 실질적인 코드를 작성해볼게요!

 

저번시간 포스팅이 궁금하다면!

https://jhnyang.tistory.com/232

 

[BCD,8421코드 총정리]BCD코드는 언제 사용할까, BCD 장점, BCD가산법, 계산하는 법, 왜 6을 더하는가? 이진화 십진법 특징

안녕하세요~ 오늘은 BCD코드에 대해서 포스팅을 해보려고 합니다. [목차] 1. BCD 코드란 무엇인가? 2. 왜 8421코드란 이름이 붙었는가? 3. BCD코드 가산법 4. BCD코드 특징 5. BCD코드 장단점 정리 BCD Code란? BC..

jhnyang.tistory.com

바이너리에서 BCD코드로 전환! 

먼저 바이너리를 BCD코드로 변환하는 코드를 작성해봅시다.

저번시간에 BCD코드는 10진수의 기수마다 똑똑 떼서 4bit 이진수로 변경해 나열된다는 것을 배웠어요. 즉 12라는 수를 BCD코드로 표현하려면, 1에 해당하는 이진수 4bit '0001', 2에 해당하는 2진수 4bit를 '0010'을 나란히 두면 되는거죠!

매번 한 자리씩 값을 빼려면 %10 연산이 필요할 거예요.

한 예로 3124값이 있으면 (3124/1)%10 = 4 (1의 자리), (3124/10)%10 = 2(10의 자리), (3124/100)%10 =1 (100의 자리) 이런 방식으로 각각의 자리수 값을 떼어낼 수 있겠죠? 

 

[C언어 자리수 뽑기]

#include <stdio.h>
int main()
{
	unsigned int input;
	int bcd = 0;
	scanf("%d", &input);
	for(int i=0; input > 0 ;i++, input /= 10) 
		printf("뒤에서 %d번째 자리수 :%.1d\n", i+1, bcd = input % 10);
	return 0;
}

결과

그 다음 해야할 일은, 처음은 shift 0 (일의 자리니까) 

뒤에서 두 번째 자리수는 shift 4, 뒤에서 세 번째 자리수는 shift 8, 뒤에서 4번째.. 이렇게 되겠죠?

그래야 위의 예시일 경우

   0000 0000 0000 1000   (8을 shfit 0)

   0000 0000 0010 0000   (2를 shift 4)

   0000 0100 0000 0000   (4를 shift 8)

+ 0001 0000 0000 0000   (1을 shift 12)

이렇게 4개를 더해줘야 (정확히는 논리적으로 OR연산!) BCD결과인 0001 0100 0010 1000이 완성될테니까요! 

 

[C언어 바이너리 -> BCD코드 변환 전체 코드]

#include <stdio.h>
int main()
{
	unsigned int input;
	int bcd = 0;
	scanf("%d", &input);
	printf("input : 0x%x\n", input); //16진수로 입력값 보여주기
	for (int shift = 0; input > 0; shift++, input /= 10)
	{
		bcd |= input % 10 << (shift << 2) ; 
        //(input%10)은 차례대로 일의자리, 십의자리, 백의자리... etc가 된다.
        // shift 는 0, 1, 2, 3... 이렇게 하나씩 증가하므로
        // shift << 2 값은 0, 4, 8,,, etc가 된다.
	}
	printf("BCD : 0x%x\n", bcd);
	return 0;
}

결과창

BCD코드-> 바이너리(BINARY)코드 

바이너리에서 BCD로 변환하는법을 알았으면 반대로 BCD코드에서 binary값으로 변경하는 법도 알아야겠죠!

위의 1428 값을 그대로 들어볼게요.

0001 0100 0010 1000이 있어요. 이 값을 바이너리 코드로 만들려면 마찬가지로 4bits씩 떼야겠죠 

떼고 싶은 4bits를 남겨놓기 위해 오른쪽 비트수만큼 >> shift연산을 한 후 1111과 AND연산을 해줍시다. (내가 알고 싶은 4비트 제외한 그 외에 다른 bit들은 0으로 만들기 위해서임!)

shift후 AND연산

내가 앞에서 두 번째 숫자(4)에 해당하는 0100을 갖고 싶어! 그러면 8bit를 shift해주면 0000 0000 0001 0100이 남을거고  (0100이 맨 하위비트로 위치할 수 있게 조작한거) 여기에 0000 0000 0000 1111을 AND해주면 0000 0000 0000 0100이 되어 결국 원하는 값을 얻을 수 있어요.

 

이와 같은 원리로 각 자리수 값을 떼어 봅시다.

#include <stdio.h>
int main()
{
	unsigned int bcdinput;
	scanf("%x", &bcdinput);
	printf("bcd input : 0x%x\n", bcdinput);
	printf("0x%x\n", (bcdinput >> 0) & 0x0F);
	printf("0x%x\n", (bcdinput >> 4) & 0x0F);
	printf("0x%x\n", (bcdinput >> 8) & 0x0F);
	printf("0x%x\n", (bcdinput >> 12) & 0x0F);
	return 0;
}

몇자리까지 있을 지 모르니까 반복문으로 깔쌈히 구현해줍시다. 

 

[BCD코드 -> 바이너리 전체 코드]

#include <stdio.h>
int main()
{
	unsigned int bcdinput;
	int binary = 0;
	scanf("%x", &bcdinput);
	printf("bcd input : 0x%x\n", bcdinput);
	for (int i = 1; bcdinput != 0x00; bcdinput= bcdinput>>4, i*=10) 
    		binary += i * (bcdinput & 0x0F);
	printf("binary : 0x%x\n", binary);
	return 0;
}

이제 바이너리와 bcd코드 간의 변환은 다 살펴보았어요.

그 다음으로 아스키코드와 bcd코드간의 변환을 살펴봅시다.

아스키코드에서 BCD코드로 변환하기!

현재 통신에서 가장 많이 쓰는 아스키코드에서 BCD코드로 변경하는 소스를 짜봅시다.

일단 가장 먼저 알아야 할 법칙은 아스키코드의 경우 문자 '0', '1', '2', '3' ,'4'... 가 헥사 값으로 30,31,32,33,34..를 갖죠?!

즉 '아스키코드값 - 0x30'하면 문자가 아닌 숫자 값이 나온다는거!

#include <stdio.h>
#include <string.h>
int main()
{
    char str[100] = { 0x00 };
    scanf("%s", &str);
    printf("정수타입:");
    for (int i = 0; i<strlen(str) ;i++) printf("%d", str[i] - 0x30);
    return 0;
}

아스키코드 값으로 만약 12가 들어왔으면 여기 각 자리수에 0x30을 빼주면 정수 12가 나오고 이 12값을 '0001 0010'로 변경해서 저장해주면 되는겁니다.  아스키코드 한 글자가 8bits고 BCD코드 한 글자가 4bits로 표현되니, 아스키코드 두 글자가 BCD에서는 한 글자에 표현되는 것과 마찬가지네요! 이 부분만 주의하면 위의 로직과 원리는 동일합니다. (shift 후 OR연산으로 더해주는거) 

[ASCII -> BCD 전체 코드]

#include <stdio.h>
#include <string.h>
int main()
{ 
    char str[100] = { 0x00 };
    char bcd[100] = { 0x00 };
    
    scanf("%s", &str);
    int shift = 0;
    for (int i = 0; i<strlen(str) ;i++)
    {
        shift = (i % 2)? 0:4;
        bcd[i/2] |= (str[i] - 0x30) << shift; // bcd 한 글자에 아스키코드 두 글자
    }
    printf("%s", bcd);
    return 0;
}

결과창

BCD코드에서 아스키코드로 변환하기!

BCD코드에서 아스키코드로 변환해주려면 반대로 BCD코드 한 index에 들어있던 값이 아스키코드 2공간에 걸쳐 저장되겠죠!? 만약 BCD 첫 번째 데이터에 0001 0010이 있으면 아스키는 "12"이렇게 저장되어야 해요. 일단 0001을 문자로 변경한 값("1")을 0번지, 0010을 문자로 변경한 값("2")을 2번지에 저장되어야 하니까 

  ascii[0] = (bcd[0] >> 4) + 0x30;
  ascii[1] = (bcd[0] & 0x0F) + 0x30;

대략 위와 같은 형태가 나옴을 예상할 수 잇겠죠.

#include <stdio.h>
#include <string.h>
int main()
{
    char bcd[100] = "4";
    char ascii[100] = { 0x00 };
    printf("[bcd]%s\n", bcd);
    for (int i = 0; i < strlen(bcd)*2; i+=2)
    {
        ascii[i] = (bcd[i/2] >> 4) + 0x30;
        ascii[i + 1] = (bcd[i/2] & 0x0F) + 0x30;
    }
    printf("[ascii]%s\n", ascii);    
    return 0;
}

오늘은 여기까지입니다! 

해당 포스팅이 도움이 되셨다면 공감, 댓글 또는 광고보답은 어떤가요?! 

정성들여 정보공유 포스팅을 작성하는데 큰 힘이 됩니다 :)