정보 과학융합탐구

C언어로 모스부호를 익힐 수 있는 프로그램을 만들어 보자!

Halfand 2024. 12. 4. 12:26

0. 들어가며

여러분 모두 모스부호가 뭔지 알고 계신가요? 아마도 다들 모스부호를 한 번쯤 들어보셨을 것이라 생각해요. 모스부호는 어렵지도 않고 외우는데 그렇게 큰 시간이 걸리지 않습니다. 그러나 모스부호를 외워 보려고 마음먹는 사람은 흔치 않죠. 어려울 것 같아서, 시간이 오래 걸리니까 등등 여러 이유가 있겠지요.

그래서 많은 사람들이 쉽게 모스부호를 익힐 수 있는 프로그램을 만들게 되었습니다. 

 

*제가 모스부호를 외우는데 사용한 Morse Mania라는 앱의 구성을 바탕으로 만들었습니다. 

 

1. 모스 부호란 무엇인가?

일단 이 글의 주제인 모스부호가 무엇인지 먼저 알아야겠죠?

모스 부호(Morse code)는 한 종류의 신호발생장치로 짧은 신호( · , 점 또는 단점)와 긴 신호( - , 선 또는 장점)를 적절히 조합하여 문자 기호를 표기하는 방식이다.   - 위키백과

 

 

 //1836년을 기점으로, 미국의 아티스트 새뮤얼 모스, 미국의 물리학자 조지프 헨리, 앨프리드 베일이 전신 시스템을 개발하였다.
 //모스 코드가 개발되어 조작자들이 종이 테이프에 적힌 자국을 텍스트 메시지로 해석할 수 있었다. 초기 코드에서 모스는 숫자만을 전송할 계획이었다. 그러나 이 코드는 앨프리드 베일이 일반 문자와 특수 문자를 포함, 확장시켰고 일반화되었다.
 //로마자에 대한 부호 지정은 가장 많이 사용되는 글자일수록 가장 짧고 간단한 부호가 되도록 정했다. 즉 많이 사용되는 글자일수록 타전하기 편하도록 할당 부호가 짧아진다는 것이다. 모스 부호의 길이가 짧은 것부터 순서대로 늘어놓으면, e i t a n s d h m r u b f g k l v w c j o p x z q y 가 된다.
 //한글 전신 부호는 김학우가 개발했으며, 사용 빈도와 한글 순서나 획순을 함께 고려하여 정했다. 가장 많이 쓰는 글자인 'ㅏ'에 점을 지정했고, 이에 대칭인 'ㅓ'에 선을 지정했다. 'ㅑ, ㅕ, ㅜ'에 각각, 두 점 '··', 세 점 '···', 네 점 '····'을 지정했다. 자음은 ㄷ, ㄱ, ㄴ, ㄹ 순으로 규칙을 정해 각각 '-···, '.-··', '··-·', '···-'로 정했다.
- 위키백과 -

 

위키백과에 있는 설명을 조금 빌려왔는데요. 이 외에 추가적으로

  • 선(dash) 길이는 점(dot)의 3배일 것,
  • 한 자(로마자 또는 한글자모 문자)를 형성하는 선과 점 사이 간격은 1점과 같을 것,
  • 문자와 문자, 문자와 기호 사이 간격은 3점과 같을 것,
  • 단어와 단어 사이는 7점과 같을 것.

과 같은 규칙이 있습니다. 

 

 

* 외우기 쉽도록 각 알파벳의 모양을 따서 이런 식으로도 표현하기도 하더라고요.

 

제가 좋아하는 방식은 아니지만... 모 친구의 말에 의하면 확실히 잘 외워진다고 하네요.

 

 

2. 코드 소개

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

int n;
int w1, w2;
char M;
char RD(){
	srand((unsigned int)time(NULL));
	return ('A'+ (rand()%26)); //랜덤으로 알파벳을 뽑음
}
void write(){ //모스부호를 쓰며 외우는 함수
	system("cls");
    while(1){
		puts("");
		w1=RD();
	    printf("%c\n", w1);
	    scanf("%s", &w2);
	    if (w1=='A'){
	    		if (w2==11566) printf("정답입니다!"); //각 숫자는 그 모스부호를 정수로 출력한 값
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='B'){
	    		if (w2==774778413) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='C'){
	    		if (w2==774712877) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='D'){
	    		if (w2==3026477) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='E'){
	    		if (w2==46) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='F'){
	    		if (w2==774712878) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='G'){
	    		if (w2==3026221) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='H'){
	    		if (w2==774778414) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='I'){
	    		if (w2==11822) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='J'){
	    		if (w2==757935406) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='K'){
	    		if (w2==2960941) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='L'){
	    		if (w2==774778158) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='M'){
	    		if (w2==11565) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='N'){
	    		if (w2==11821) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='O'){
	    		if (w2==2960685) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='P'){
	    		if (w2==774712622) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='Q'){
	    		if (w2==758000941) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='R'){
	    		if (w2==3026222) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='S'){
	    		if (w2==3026478) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='T'){
	    		if (w2==45) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='U'){
	    		if (w2==2960942) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='V'){
	    		if (w2==758001198) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='W'){
	    		if (w2==2960686) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='X'){
	    		if (w2==758001197) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='Y'){
	    		if (w2==757935661) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		if (w1=='Z'){
	    		if (w2==774778157) printf("정답입니다!");
	    		else printf("틀렸습니다!"); 
		}
		w2=0;
		puts("");
	}
}
void all(){ //모스부호 전체를 보여주는 함수
	system("cls");
    puts("");
    puts("-------------");
    puts("");
    puts("A .-");
    puts("B -...");
    puts("C -.-.");
    puts("D -..");
    puts("E .");
    puts("F ..-.");
    puts("G --.");
    puts("H ....");
    puts("I ..");
    puts("J .---");
    puts("K -.-");
    puts("L .-..");
    puts("M --");
    puts("N -.");
    puts("O ---");
    puts("P .--.");
    puts("Q --.-");
    puts("R .-.");
    puts("S ...");
    puts("T -");
    puts("U ..-");
    puts("V ...-");
    puts("W .--");
    puts("X -..-");
    puts("Y -.--");
    puts("Z --..");
    puts("");
    puts("-------------");
    puts("");
}
void remember(){ //모스부호에 따른 알파벳을 맞히는 함수
	system("cls");
	while(1){
		puts("");
		w1=RD();
		switch (w1){
			case 65:
				puts(".-");
				getchar();
				scanf("%c", &w2);
				if (w2=='A') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 66:
				puts("-...");
				getchar();
				scanf("%c", &w2);
				if (w2=='B') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 67:
				puts("-.-.");
				getchar();
				scanf("%c", &w2);
				if (w2=='C') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 68:
				puts("-..");
				getchar();
				scanf("%c", &w2);
				if (w2=='D') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 69:
				puts(".");
				getchar();
				scanf("%c", &w2);
				if (w2=='E') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 70:
				puts("..-.");
				getchar();
				scanf("%c", &w2);
				if (w2=='F') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 71:
				puts("--.");
				getchar();
				scanf("%c", &w2);
				if (w2=='G') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 72:
				puts("....");
				getchar();
				scanf("%c", &w2);
				if (w2=='H') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 73:
				puts("..");
				getchar();
				scanf("%c", &w2);
				if (w2=='I') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 74:
				puts(".---");
				getchar();
				scanf("%c", &w2);
				if (w2=='J') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 75:
				puts("-.-");
				getchar();
				scanf("%c", &w2);
				if (w2=='K') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 76:
				puts(".-..");
				getchar();
				scanf("%c", &w2);
				if (w2=='L') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 77:
				puts("--");
				getchar();
				scanf("%c", &w2);
				if (w2=='M') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 78:
				puts("-.");
				getchar();
				scanf("%c", &w2);
				if (w2=='N') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 79:
				puts("---");
				getchar();
				scanf("%c", &w2);
				if (w2=='O') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 80:
				puts(".--.");
				getchar();
				scanf("%c", &w2);
				if (w2=='P') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 81:
				puts("--.-");
				getchar();
				scanf("%c", &w2);
				if (w2=='Q') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 82:
				puts(".-.");
				getchar();
				scanf("%c", &w2);
				if (w2=='R') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 83:
				puts("...");
				getchar();
				scanf("%c", &w2);
				if (w2=='S') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 84:
				puts("-");
				getchar();
				scanf("%c", &w2);
				if (w2=='T') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 85:
				puts("..-");
				getchar();
				scanf("%c", &w2);
				if (w2=='U') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 86:
				puts("...-");
				getchar();
				scanf("%c", &w2);
				if (w2=='V') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 87:
				puts(".--");
				getchar();
				scanf("%c", &w2);
				if (w2=='W') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 88:
				puts("-..-");
				getchar();
				scanf("%c", &w2);
				if (w2=='X') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 89:
				puts("-.--");
				getchar();
				scanf("%c", &w2);
				if (w2=='Y') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
			case 90:
				puts("--..");
				getchar();
				scanf("%c", &w2);
				if (w2=='Z') puts("정답입니다!");
				else puts("틀렸습니다!");
				break; 
		}
	}
}
void mm(){ //메인함수
    while(1){
    	puts("최근에 모스부호에 흥미를 붙여 한동안 외웠었는데요.");
	    puts("제가 모스부호를 외우는데 사용한 Morse Mania라는 앱을 한번 c언어로 구현해 보려고 합니다.");
	    puts("dash(선)은 -, dot(점)은 .로 표현합니다.");
	    puts("");
	    puts("0. 모스부호 외우기");
	    puts("1. 모스부호 쓰기");
	    puts("10. 전체 모스부호 보기"); //2를 이진법, 즉 10으로 표현
	    puts("11. 종료"); //3도 마찬가지
	    puts("선택: ");
	    scanf("%d", &n);
	    if(n!=0&&n!=1&&n!=10&&n!=11){ //0, 1, 10, 11이 아닌 다른 수를 입력할 시 
	    	puts("다시 입력하세요!");
	    	Sleep(700);
			system("cls");
		}
		else break;
    }
    if(n==1) write();
	if(n==10) all();
	if(n==0){
	   	remember();
	}
	if(n==11){
		system("cls"); 
    	puts("");
    	puts("모스부호 외우기를 종료합니다.");
	}
}
int main(){
    mm(); //메인함수 호출
    //이렇게 따로 mm이라는 함수를 만든 이유는... 제가 다른 것을 시도하다가 실패했기 때문...
}

 

 

3. 실행 화면

 

 

4. 코드를 짜는데 어려웠던 점, 아쉬운 점

1. 일단 저 모스부호들을 하나하나 입력하는게 생각보다 귀찮았습니다. 더욱이 모스부호를 입력 받을 때는 문자열로 받고 이를 어떻게 정답처리해야 할 지 조금 고민했습니다.

 그 문자열을 %d로 출력한 값을 붙여넣기 할 수 있지 않을까라는 생각이 들었고, '-.-.'을 출력해 본 결과 774712877라는 값을 얻게 되었습니다. 하나하나 입력하고 출력해 봐서 그 값을 얻어야 했지만 그래도 코드가 돌아간다는 마음에 즐겁게 작업했습니다. (대신 중간에 오류가 생겨 전체를 한 번 더 입력하고 출력받았다는...)

 

2. 그냥 X표 눌러서 끄면 될 걸 굳이 11. 종료 라는 선택지가 있는 이유는, 원래 외우기 / 쓰기 / 전체 보기 등을 마치면 main을 입력하여 다시 메인화면으로 돌아오게 하려고 했기 때문입니다. 그러나 그렇게 코드를 짜면 중간에 코드가 꼬여 그냥 이 상태로 두기로 결정했습니다. 

 

3. 이건 코드를 짜면서 어려웠던 점은 아닌데, 확실히 한동안 c를 안 하다보니 기본적인 것도 가물가물해서 인터넷을 찾아봤다는 것에 충격을 받았습니다. 물론 검색해보면 바로바로 기억나기는 하지만... 그래도 감이 죽지 않도록 종종 해봐야 할 듯 합니다.

 

 

5. 마치며

 전에 과제로 제출한 '갓생 만들기 프로젝트' 부터 시작해 이것까지 코드로 만들어 보면서 점점 이걸 그저 코드로 내버려 두는 것이 아니라 앱을 만들어 구현해보고 싶다는 생각이 들었다. 그래서 다음 달 부터는 'flutter'를 배우는 과정도 적어보려고 한다. 

 나한테 딱 맞는 공부 관리 앱이 없어 항상 아쉬웠는데, 그걸 만들어 보는 것이 내 목표이다.