1. 문제

 

영문 텍스트와 모스(Morse) 부호 변환기

 

아래 <표 5-1>을 참고하여 영문 텍스트, 숫자, 몇 개의 특수 문자로 구성되는 텍스트를 모스 부호로 변환하는 프로그램을 작성하라. 모스 부호는 전보를 쳐서 통신하는 시절에 사용된 유명한 코딩 시스템이다. 각 모스 코드들을 하나의 빈칸으로 분리되고, 영문 한 워드가 모스 워드로 변환되면 워드들은 3개의 빈칸으로 분리된다. 실행 예는 다음과 같다. 영문 텍스트를 입력받아 모스 부호로 변환하여 출력하고, 변환이 잘 되었는지 확인하기 위해 다시 모스 부호를 영문 텍스르로 변환하여 원문을 출력한 사례이다.

 

 

2. 결과

 

 

 

 

3. 코드

 

#include <iostream>
#include <string>
using namespace std;

class Morse {
	string alphabet[26];
	string digit[10];
	string slash, question, comma, period, plus, equal;
public :
	Morse();
	void text2Morse(string text, string& morse);
	bool morse2Text(string morse, string& text);
};

Morse::Morse() {
	string alphamorse[26] = { ".-", "-...", "-.-.", "-..", ".",
							 "..-.", "--.", "....", "..", ".---",
							 "-.-", ".-..", "--", "-.", "---",
							 ".--.", "--.-", ".-.", "...", "-",
							 "..-", "...-", ".--", "-..-", "-.--", "--.."};
	string digitmorse[10] = { "-----", ".----", "..---", "...--", "....-",
							".....", "-....", "--...", "---..", "----." };
	int i;

	for(i=0; i<26; i++)
		alphabet[i] = alphamorse[i];
	for(i=0; i<10; i++)
		digit[i] = digitmorse[i];
	slash = "-..-.";	question = "..--..";	comma = "--..--";
	period = ".-.-.-";	plus = ".-.-.";		equal = "-...-";
}
void Morse::text2Morse(string text, string& morse) {

	morse = "";

	for(int i=0; i<text.length(); i++) 
	{
		char temp = text.at(i);
		if( isalpha( temp ) ) {
			if( temp >= 65 && temp <= 90 ) tolower( temp );
			morse = morse + alphabet[ temp-97 ] + " ";
		}
		else if( temp == ' ')
			morse += "  ";
		else if( isdigit( temp ) )
			morse = morse + digit[ temp -48 ] + " ";
		else {
			if( temp == '/' ) morse = morse + slash + " ";
			else if( temp == '?' ) morse = morse + question + " ";
			else if( temp == ',' ) morse = morse + comma + " ";
			else if( temp == '.' ) morse = morse + period + " ";
			else if( temp == '+' ) morse = morse + plus + " ";
			else if( temp == '=' ) morse = morse + equal + " ";
		}
	}
}
bool Morse::morse2Text( string morse, string& text) {
	int before;
	int pos = -1;
	string retext;
	bool exit = true;

	string al[26] = {"a", "b", "c", "d", "e", "f", "g", "h", "i",
					"j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
					"t", "u", "v", "w", "x", "y", "z"};
	string di[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};

	while(1) {

			before = pos +1;
			pos = morse.find(" ", before);

			string temp = morse.substr( before, pos-before);
			for(int i=0; i<26; i++) {
				if( temp == alphabet[i] ) {
					retext.append(al[i]);
					exit = false;
					break;
				}
			}
			if( exit) {
				for(int i=0; i<10; i++) {
					if( temp == digit[i] ) {
						retext.append(di[i]);
						break;
					}
				}

		if( temp == slash ) retext.append("/");
			else if( temp == question ) retext.append("?");
			else if( temp == comma ) retext.append(",");
			else if( temp == period ) retext.append(".");
			else if( temp == plus ) retext.append("+");
			else if( temp == equal ) retext.append("=");
		}

		exit = true;

		if( pos == morse.size()-1 ) break;   //while문 종료

		while( morse.at(pos) == ' ' && morse.at(pos+1) == ' ' && morse.at(pos+2) == ' ' ) {
			retext.append(" ");
			pos += 2;
		}

	}

	if( retext == text ) return true;
	else return false;
}

int main() {

	string text, morse;
	Morse m;

	cout << "아래에 영문 텍스트를 입력하세요. 모스 부호로 바꿉니다." << endl;
	getline(cin, text);
	m.text2Morse( text, morse );
	cout << morse << endl << endl;

	cout << "모스 부호를 다시 영문 텍스트로 바꿉니다." << endl;
	
	if( m.morse2Text( morse, text) )
		cout << text << endl;
	else
		cout << "모스 부호가 아닙니다." << endl;

}

 

 

4. 설명

 

Morse 클래스 생성자에서 <표 5-1>의 문자들을 초기화 하여 줍니다.

 

저는 새로운 배열을 하나 선언한 후 for문을 이용하여서 Morse 클래스 멤버 변수들을 초기화 하였습니다. 이 방법이 아니면 alphabet[0] = ; alphabet[1] = ; alphabet[2] =; 이렇게 일일이 다 초기화 해주어야 합니다.

 

----------

text2Morse() 멤버 함수는 우선 text.at(i)로 문자열 text에서 인덱스 값이 i인 문자를 가져와서 temp에 저장합니다.

 

이 temp가 isalpha()를 사용하여서 알파벳인지 검사를 합니다. 알파벳이라면 temp >= 65 && temp <= 90 일 경우 즉, 대문

 

자일 경우 tolower(  )함수를 사용하여서 temp를 소문자로 고쳐줍니다.

 

그 후 morse = morse + alphabet[ temp-97] + " "; 여기서 "temp - 97"인 이유는 temp가 소문자이므로 temp의 값 범위는 temp >= 97 && temp <= 123 입니다. 여기서 temp가 'a'라면 97로서 alphabet[0] 즉 a의 해당하는 모스부호를 morse 변수에 추가합니다. 그 후 + " "로 한칸을 띄어 줍니다.

 

숫자인 경우도 isdigit()을 사용하여서 숫자이면 digit[ temp - 48 ]로서 해당하는 모스부호를 추가시 켜 줍니다.

 

 

※ 주의하실 점은 temp == ' '일 경우 입니다. 이 경우는 띄어쓰기일 경우인데 이 경우 모스부호로 바꾸었을 때는 3개의 공간을 비워주어야 합니다. 하지만 조건문이 temp == ' '인 if문에서 morse += "  "; 로서 2칸만 띄어쓰기를 해주셔야 합니다.
그 이유는 다른 문자를 추가하고서 + " "로 이미 한칸을 띄어쓰기 하였기 때문입니다.

 

------------

morse2Text() 멤버 함수가 가장 어려웠던 것 같습니다.

 

우선 변수들을 선언 합니다. before은 한 모스 부호의 시작 부분의 인덱스를, pos는 그 모스 부호 끝의 다음 " "부분의 인덱스 값을 저장합니다.

 

그리고 알파벳들을 저장하고 있는 배열과 숫자 0~9를 저장하고 있는 배열을 선언, 초기화 해줍니다.

 

string temp = morse.substr( before, pos-before ) : substr() 함수는 문자열 morse의 인덱스 before부터 pos-before(개)를 return 합니다. pos는 " "의 인덱스 값이므로 pos-before(개)만큼 return하여야 합니다.

 

모스 부호 하나를 temp 변수에 저장 하였으면 Morse클래스의 멤버 변수들을 이용하여서 어떤 문자인지를 구하여 retext변수의 추가하여 줍니다.

 

->여기서 exit는 알파벳인 것을 구하였다면 다음 숫자 또는 기호인지 검사할 필요가 없으므로 시간 절약을 위하여 선언하였습니다.

 

if( pos == morse.size()-1 ) break; 일 경우 while문을 종료합니다.

여기서 중요한 것은 morse의 인덱스 morse.size()-1인 부분은 맨 끝으로 " "이라는 것 입니다.

-> 모든 문자들 끝에 띄어쓰기가 추가되었기 때문에

그러므로 모스 부호 단어 끝 " "의 인덱스 번호를 저장하는 pos를 이용하여서 종료시점을 정할 수 있습니다.

 

 

while( morse.at(pos) == ' ' && morse.at(pos+1) == ' ' && morse.at(pos+2) == ' ' )는 띄어쓰기가 있을 경우 " "을 retext의 추가 해준다음 pos값을 +2하여서 다음 단어의 pos값을 구할 수 있도록 합니다.

 

여기서 while문을 사용한 이유는 띄어쓰기를 연속적으로 2번 하였을 시 알맞게 출력하기 위해서 입니다. 하지만 정작 text2Morse()함수에서는 띄어쓰기가 연속적으로 2번 하였을 시를 알맞게 코딩하지 않았습니다.

 

그러니 연속적인 띄어쓰기를 입력하지 않는다면, 이 부분에서는 while문 말고 if문을 사용하셔도 무관합니다.

+ Recent posts