Files
dotdash/main.cpp

205 lines
5.3 KiB
C++

#include <cctype>
#include <iostream>
#include <map>
#include <optional>
#include <sstream>
#include <string>
using namespace std;
const map<char, string> morse_map = {
{'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', "--.."}, {'0', "-----"}, {'1', ".----"},
{'2', "..---"}, {'3', "...--"}, {'4', "....-"}, {'5', "....."},
{'6', "-...."}, {'7', "--..."}, {'8', "---.."}, {'9', "----."},
{'.', ".-.-.-"}, {',', "--..--"}, {'?', "..--.."}, {'!', "-.-.--"},
{'\'', ".----."}, {'/', "-..-."}, {'(', "-.--."}, {')', "-.--.-"},
{'&', ".-..."}, {':', "---..."}, {';', "-.-.-."}, {'=', "-...-"},
{'+', ".-.-."}, {'-', "-....-"}, {'_', "..--.-"}, {'"', ".-..-."},
{'$', "...-..-"}, {'@', ".--.-."}};
bool should_exit = false;
bool is_exit(const string &s) {
return s.length() == 4 && tolower(s[0]) == 'e' && tolower(s[1]) == 'x' &&
tolower(s[2]) == 'i' && tolower(s[3]) == 't';
}
string read_input(const string &prompt) {
cout << prompt;
string line;
if (!getline(cin, line) || line.empty())
return "";
if (is_exit(line)) {
should_exit = true;
return "";
}
return line;
}
class MorseDecoder {
private:
static const map<string, char> &get_morse_to_char() {
static map<string, char> morse_to_char;
static bool initialized = false;
if (!initialized) {
for (const auto &[ch, code] : morse_map) {
morse_to_char[code] = ch;
}
initialized = true;
}
return morse_to_char;
}
public:
optional<char> decode(const string &morse) const {
const auto &morse_to_char = get_morse_to_char();
auto it = morse_to_char.find(morse);
if (it == morse_to_char.end())
return nullopt;
return it->second;
}
};
class MorseEncoder {
private:
const map<char, string> &char_to_morse;
public:
MorseEncoder() : char_to_morse(morse_map) {}
string encode(char c) {
auto it = char_to_morse.find(toupper(c));
return it != char_to_morse.end() ? it->second : "";
}
string get_full_sequence(const string &text) {
string sequence;
sequence.reserve(text.length() * 5);
bool need_space = false;
for (char c : text) {
if (c == ' ') {
sequence += " / ";
need_space = false;
} else {
string morse = encode(c);
if (!morse.empty()) {
if (need_space)
sequence += " ";
sequence += morse;
need_space = true;
}
}
}
return sequence;
}
void print_morse_pattern(const string &text) {
for (char c : text) {
if (c == ' ') {
cout << "\n[Space]\n";
} else {
string morse = encode(c);
if (!morse.empty()) {
cout << c << " -> " << morse << "\n";
}
}
}
}
};
void decode_mode() {
MorseDecoder decoder;
cout << "Decode mode: Enter morse sequence to decode. Press 'e' to switch to "
"encode mode, 'exit' to exit.\n\n";
while (!should_exit) {
string input = read_input("Enter morse sequence: ");
if (input.empty())
continue;
if (tolower(input[0]) == 'e')
return;
string decoded_message;
bool has_invalid_tokens = false;
bool has_unknown_codes = false;
istringstream stream(input);
string token;
while (stream >> token) {
if (token == "/") {
if (!decoded_message.empty() && decoded_message.back() != ' ')
decoded_message += ' ';
continue;
}
if (token.find_first_not_of(".-") != string::npos) {
has_invalid_tokens = true;
cout << token << " -> [ignored: invalid characters]\n";
continue;
}
optional<char> decoded = decoder.decode(token);
if (!decoded) {
has_unknown_codes = true;
cout << token << " -> [unknown]\n";
continue;
}
cout << token << " -> " << *decoded << "\n";
decoded_message += *decoded;
}
if (has_invalid_tokens)
cout << "\nWarning: Tokens with invalid characters were ignored.\n";
if (has_unknown_codes)
cout << "Warning: Unknown Morse codes were skipped.\n";
cout << "\nFinal message: " << decoded_message << "\n\n";
}
}
void encode_mode() {
MorseEncoder encoder;
cout << "Encode mode: Enter text to see Morse code patterns. Press 'd' to "
"switch to decode mode, 'exit' to exit.\n\n";
while (!should_exit) {
string input = read_input("Enter text to encode: ");
if (input.empty())
continue;
if (tolower(input[0]) == 'd')
return;
cout << "\n";
encoder.print_morse_pattern(input);
cout << "\nFinal sequence: " << encoder.get_full_sequence(input) << "\n\n";
}
}
int main() {
cout << "dotdash - Morse code playground\n";
cout << "Starting in decode mode...\n\n";
bool decode = true;
while (!should_exit) {
decode ? decode_mode() : encode_mode();
if (!should_exit) {
decode = !decode;
cout << "\nSwitched to " << (decode ? "decode" : "encode")
<< " mode.\n\n";
}
}
cout << "\nExiting...\n";
return 0;
}