lookup table using struct

Hello, i can't print corresponding decoded character to serial, do you know where did i go wrong? Thank you in advance!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

// _____________________ Header Files _____________________

#include <ee108.h>
#include <ee108_switches.h>

// _________________________ Types ________________________

struct MorseCode {
  char decodedChar; // this represents the decoded character
  const char *encodedStr; // the represents the morse encoding
};

typedef  struct MorseCode    MorseCode;

// _______________________ Constants _______________________

// lookup table to allow conversion from characters to morse codes
// and from morse codes to characters
const MorseCode MORSE_TABLE[] = {
  { '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', "-----" }
};

const int SUPERLOOP_DELAY_MS = 25;

const int MORSE_TABLE_SIZE = sizeof(MORSE_TABLE) / sizeof(MORSE_TABLE[0]);
const int BUFFER_SIZE = 11;

// ___________________ Function Declarration __________________

// ____________________________________________________________

void setup() {

  // set up serial
  Serial.begin(9600);
  Serial.println("\n\n\t________A4_SerialMorseToChar________\n");

}

void loop() {

  char buf[BUFFER_SIZE] = "";

  Serial.println("\n\tType a pattern of . and - chars & hit send:");

  int bufIndex = 0;

  // read characters & break out of while loop if end of line,
  // space character or max buffer size is detected.
  while (bufIndex < BUFFER_SIZE) {
    char symbol;

    // wait until at least one character has been entered
    while (Serial.available() == 0)
      continue;

    // OK, we now have at least 1 character
    symbol = Serial.read(); // read 1 character

    // a newline or space indicates the end of the word
    // so we'll break out to process it
    if ((symbol == '\n') || (symbol == '\r') || (symbol == isspace(symbol))) {
      if (bufIndex > 0)

        break;
    }

    // ignore any characters that are not alphabetic
    if (symbol != '.' && symbol != '-')
      continue; // go directly to next iteration of while loop

    // at this point only valid characters should be left
    buf[bufIndex] = symbol; // add the character to the buffer
    bufIndex++; // increment index

  }

  // newline, space or max number of characters?
  buf[bufIndex] = '\0'; // add nul terminator to buf

  Serial.print("\tInput was: ");
  Serial.println(buf);

  for (bufIndex = 0; bufIndex < MORSE_TABLE_SIZE; bufIndex++) {

    if (buf == MORSE_TABLE[bufIndex].encodedStr) {
      Serial.print("Decoded character is: ");
      Serial.println(MORSE_TABLE[bufIndex].decodedChar);

    }
  }
}


Last edited on
This is nice code for a beginner. I hope you'll continue to pursue programming.

The problem is line 122 which compares the address of buf to the address of MORSE_TABLE[bufIndex].encodedStr. You want to compare the contents. For that, use strcmp(). Strcmp returns a negative number, 0, or a positive number if the first string is less than, equal to, or greater than the second, so you want:
if (strcmp(buf, MORSE_TABLE[bufIndex].encodedStr) == 0) {

Hint: because strcmp's return value is the opposite of the way we normally think, I always compare it to zero. To me, the above code is easier to understand than:
if (!strcmp(buf, MORSE_TABLE[bufIndex].encodedStr)) {

One other comment: You have a spin loop while waiting for data to be available. That will burn CPU time and power. If possible, add a short delay (maybe 0.01 seconds) before line 91.
Thank you a lot for your help!

However, what happens now is that whatever i pass in let's say ".....-.-.-.-.-" (which is also not found int lookup table) still gets executed..

1
2
3
4
5
6
7
8

  for (bufIndex = 0; bufIndex < MORSE_TABLE_SIZE; bufIndex++) {

    if (strcmp(buf, MORSE_TABLE[bufIndex].encodedStr) == 0) {
      Serial.print("\tDecoded character is: ");
      Serial.println(MORSE_TABLE[bufIndex].decodedChar);
    }
  }
Last edited on
I am not 100% sure but
".....-.-.-.-.-"

looks like
.... H
.-. R
-.-. C (or K??)

etc which brings up an issue... I don't see how it knows which letter to pick if the first 3 are one letter and the 4th makes a different letter...?


 
if ((symbol == '\n') || (symbol == '\r') || (symbol == isspace(symbol))) {


Well.. the output was:


Type a pattern of . and - chars & hit send:
Input was: .....-.-.-.
Input was: -.-
Decoded character is: K


This mightn't be the best example well lets assume the input is not found on the look up table, for example if i pass in : ''..--..--''

The outcome is:

Type a pattern of . and - chars & hit send:
Input was: ..--..--

My question is why did it get executed if this particular combination of "." "-" is not in the lookup table..
I do not want to be annoying here, but if anyone has some useful advice on this I would really appreciate. This is my college work and submission is due tomorrow. Thank you, once again!
Line 98 isn't checking for a space correctly. It should be:
if ((symbol == '\n') || (symbol == '\r') || isspace(symbol)) {

That may explain where here:
Input was: .....-.-.-.
Input was: -.-
Decoded character is: K

You're getting that very long line of dots and dashes (.....-,-.-.) that don't match anything.
@dhayden
Line 98 isn't checking for a space correctly. It should be:
if ((symbol == '\n') || (symbol == '\r') || isspace(symbol)) {


\r and \n are included in isspace so if (isspace(symbol)) should do.

http://www.cplusplus.com/reference/cctype/isspace/
But my question remains the same... if it doesn't match anything in the lookup table and
 
if (strcmp(buf, MORSE_TABLE[bufIndex].encodedStr) == 0) {
is not equal 0, shouldn't it just do nothing?? What i want to do is Serial.print("UNKNOWN"); if it doesn't match anything. But i can't get it working..
closed account (48T7M4Gy)
@OP This again appears to be an Arduino type exercise and if so the Arduino String type would be a better choice of Morse encoded data type than char[] which is especially cumbersome without a terminating character in the data stream.

https://www.arduino.cc/en/reference/string
https://www.arduino.cc/en/Reference/StringObject
I see two options.

1.) Check first if you the character is valid before starting to search the table. If not print an error
msg.

2.) Write a function int GetMorseCodeIndex(char ch) that returns the index of the entry or -1 if it is not there. In main you print an error msg if it is not there.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  for (bufIndex = 0; bufIndex < MORSE_TABLE_SIZE; bufIndex++) {

    if (strcmp(buf, MORSE_TABLE[bufIndex].encodedStr) == 0) {
      Serial.print("\tDecoded character is: ");

      int i;

      for (i = 0; i < buf; i++) {
        if (buf[i] == MORSE_TABLE[bufIndex].encodedStr[i]) {
          Serial.println(MORSE_TABLE[bufIndex].decodedChar);
        }
        else
          Serial.println("not found!");
        break;
      }
    }
  }


I did this, however it never gets to else statement...
I am really stuck here.
I was thinking about sth. like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int GetMorseCodeIndex(char ch)
{
   for (int i = 0; i < MORSE_TABLE_SIZE; i++)
   {
      if (MORSE_TABLE[i].decodedChar == ch)
        return i; // found it
   }
   return -1; // not found
}

INSIDE loop()

for (int i = 0; i < strlen(buf); i++) // check each char in buf
{
   int idx = GetMorseCodeIndex(buf[i]); // find index of buf[i] in table
   if (idx != -1) // found
      // use MORSE_TABLE[idx].encodedStr
   else
   {
       // handle error / invalid char
   }
}
Thank you!
Topic archived. No new replies allowed.