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 ]로서 해당하는 모스부호를 추가시 켜 줍니다.
------------
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문을 사용하셔도 무관합니다.
'명품 C++ programming' 카테고리의 다른 글
명품 C++ programming 실습문제 6장 1번 - (2) (0) | 2019.04.12 |
---|---|
명품 C++ programming 실습문제 6장 1번 - (1) (0) | 2019.04.12 |
명품 C++ programming 실습문제 5장 8번 (0) | 2019.04.07 |
명품 C++ programming 실습문제 5장 7번 (0) | 2019.04.07 |
명품 C++ programming 실습문제 5장 6번 (0) | 2019.04.07 |