patterncppModerate
Morse code emitter
Viewed 0 times
codeemittermorse
Problem
As the first step for writing a Morse code practice program, I thought I'd start with the very simplest step of a text-based Morse code translator. This simple program reads lines from
I'm interested particularly in a few things.
The private
Morse.cpp:
stdin and emits them as a text-based representation of the Morse code equivalent. Any character that doesn't have a Morse code equivalent is simply skipped.I'm interested particularly in a few things.
- Is there a better representation than
mapthat I should use?
- Is there a way to declare it as
constexpr?
- Would this be better implemented as a
facet?
The private
emit member function is intended to be replaced by a mechanism that will queue up audio output.Morse.cpp:
#include
#include
#include
#include
/* Morse code ITU-4 M.1677 */
class Morse
{
public:
Morse &operator coding;
};
std::map Morse::coding = {
{' ', " "},
{'\n', "\n"},
{'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', "--.."},
{'1', ".----"},
{'2', "..---"},
{'3', "...--"},
{'4', "....-"},
{'5', "....."},
{'6', "-...."},
{'7', "--..."},
{'8', "---.."},
{'9', "----."},
{'0', "-----"},
{'.', ".-.-.-"},
{',', "--..--"},
{'?', "..--.."},
{'-', "-...-"},
{'/', "-..-."},
{'@', ".--.-."},
{'+', ".-.-."},
{'=', "-..."},
{'\'', ".----"},
{'(', "-.--"},
{')', "-.--."},
{'\"', ".-..-"},
{'\x04', "...-.-"}, //EOT = SK
};
int main()
{
using namespace std;
Morse morse;
string line;
while (getline(cin, line))
morse << line << '\n';
}Solution
The others have provided enough comments on the current code.
I find using facets relatively straight forward.
Then the facet you want to specialize is
Output:
Some examples of fun things to do with Facets and locale's:
Facet: numpunct
Facet: ctype
Facet: codecvt
I find using facets relatively straight forward.
int main()
{
std::locale MorseLocal(std::locale::classic(), new ASCIItoMorse());
/* Imbue std::cout before it is used */
std::cout.imbue(MorseLocal);
std::cout << "Line 1\nLine 2\nLine 3\n";
/* You must imbue a file stream before it is opened. */
std::ofstream data;
data.imbue(MorseLocal);
data.open("PLOP");
data << "Loki\n translated into morse rather than norse.";
}Then the facet you want to specialize is
codecvt#include
#include
#include
#include
class ASCIItoMorse: public std::codecvt
{
public:
explicit ASCIItoMorse(size_t ref = 0): std::codecvt(ref) {}
typedef std::codecvt_base::result result;
typedef std::codecvt parent;
typedef parent::intern_type intern_type;
typedef parent::extern_type extern_type;
typedef parent::state_type state_type;
protected:
virtual result do_out(state_type& tabNeeded,
const intern_type* rStart, const intern_type* rEnd, const intern_type*& rNewStart,
extern_type* wStart, extern_type* wEnd, extern_type*& wNewStart) const
{
result res = std::codecvt_base::ok;
for(;rStart wEnd)
{
res = std::codecvt_base::partial;
break;
}
wStart = std::copy(std::begin(output), std::end(output), wStart);
}
rNewStart = rStart;
wNewStart = wStart;
return res;
}
// Override so the do_out() virtual function is called.
virtual bool do_always_noconv() const throw() {return false;}
};Output:
> ./a.out
.-.. .. -. . .----
.-.. .. -. . ..---
.-.. .. -. . ...--
> cat PLOP
.-.. --- -.- ..
- .-. .- -. ... .-.. .- - . -.. .. -. - --- -- --- .-. ... . .-. .- - .... . .-. - .... .- -. -. --- .-. ... . .-.-.-Some examples of fun things to do with Facets and locale's:
Facet: numpunct
- Is there a built-in function that comma-separates a number
- How to insert spaces in a big number to make it more readable?
Facet: ctype
- Is there a flag to make istream treat only tabs as delimiters?
- How to tokenzie (words) classifying punctuation as space
Facet: codecvt
- How to write only regularly spaced items from a char buffer to disk in C++
- How can I count the number of characters that are printed as output?
- ignore punctuation using manipulator
- How to easily indent output to ofstream?
- Writing utf16 to file in binary mode
- Remove punctuation when reading a file
Code Snippets
int main()
{
std::locale MorseLocal(std::locale::classic(), new ASCIItoMorse());
/* Imbue std::cout before it is used */
std::cout.imbue(MorseLocal);
std::cout << "Line 1\nLine 2\nLine 3\n";
/* You must imbue a file stream before it is opened. */
std::ofstream data;
data.imbue(MorseLocal);
data.open("PLOP");
data << "Loki\n translated into morse rather than norse.";
}#include <locale>
#include <algorithm>
#include <iostream>
#include <fstream>
class ASCIItoMorse: public std::codecvt<char,char,std::mbstate_t>
{
public:
explicit ASCIItoMorse(size_t ref = 0): std::codecvt<char,char,std::mbstate_t>(ref) {}
typedef std::codecvt_base::result result;
typedef std::codecvt<char,char,std::mbstate_t> parent;
typedef parent::intern_type intern_type;
typedef parent::extern_type extern_type;
typedef parent::state_type state_type;
protected:
virtual result do_out(state_type& tabNeeded,
const intern_type* rStart, const intern_type* rEnd, const intern_type*& rNewStart,
extern_type* wStart, extern_type* wEnd, extern_type*& wNewStart) const
{
result res = std::codecvt_base::ok;
for(;rStart < rEnd;++rStart)
{
// Get the output string
// Note: I would add the trailing space into each `coding` value.
std::string const& output = coding[std::toupper(*rStart)];
// Check we have room
if (wStart+output.size() > wEnd)
{
res = std::codecvt_base::partial;
break;
}
wStart = std::copy(std::begin(output), std::end(output), wStart);
}
rNewStart = rStart;
wNewStart = wStart;
return res;
}
// Override so the do_out() virtual function is called.
virtual bool do_always_noconv() const throw() {return false;}
};> ./a.out
.-.. .. -. . .----
.-.. .. -. . ..---
.-.. .. -. . ...--
> cat PLOP
.-.. --- -.- ..
- .-. .- -. ... .-.. .- - . -.. .. -. - --- -- --- .-. ... . .-. .- - .... . .-. - .... .- -. -. --- .-. ... . .-.-.-Context
StackExchange Code Review Q#71228, answer score: 12
Revisions (0)
No revisions yet.