Looking up Char in Arrays

Hi,

Could some one help me with correct syntax for this. I am sure there are better ways to do this but I am just looking to look up a single Char in a list of them.

I started by declaring all it as Char* and this works, but I wanted to try it via strings

but then i get this error message

" In function ‘void getmorse(String)’:
76:42: error: cannot convert ‘String’ to ‘const char*’ for argument ‘1’ to ‘int strcmp(const char*, const char*)’"

Code below.

Thank you.

void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);

}

//define the structure of the mapping between letters and morse
typedef struct
{
String letter;
int code;

}morse;

// Populate morse array that we can use as a look up.
morse Temp[40] = {
{“a”, 01},
{“b”, 1000},
{“c”, 1010},
{“d”, 100},
{“e”, 0},
{“f”, 0010},
{“g”, 110},
{“h”, 0000},
{“i”, 00},
{“j”, 0111},
{“k”, 101},
{“l”, 0100},
{“m”, 11},
{“n”, 10},
{“o”, 111},
{“p”, 0110},
{“q”, 1101},
{“r”, 010},
{“s”, 000},
{“t”, 1},
{“u”, 001},
{“v”, 0001},
{“w”, 011},
{“x”, 1001},
{“y”, 1011},
{“z”, 1100},
{“1”, 01111},
{“2”, 00111},
{“3”, 00011},
{“4”, 00001},
{“5”, 00000},
{“6”, 10000},
{“7”, 11000},
{“8”, 11100},
{“9”, 11110},
{“10”, 11111}
};

void loop()
{

getmorse (“b”);

}

void getmorse(String let)
{

//char* let;
int i;
let.toLowerCase();
//let = “c”;

while(let)
{
for(i=0; i<40; ++i)
{
if (!strcmp(let, Temp*.letter))*

  • {*
    _ Serial.println(Temp*.code);_
    _
    }_
    _
    }_
    _
    let = strtok(NULL, " ");_
    _
    }*_
    delay(1000);

}

You cannot use strcmp() with Strings, only with strings

If you insist on using Strings then use the normal comparison operator (==)

UKHeliBob:
You cannot use strcmp() with Strings, only with strings

If you insist on using Strings then use the normal comparison operator (==)

Am i correct in thinking a string is just an array of char's as per string - Arduino Reference

Cheers

Am i correct in thinking a string is just an array of char's

A C style string is an array of chars terminated with a NULL ('\0')

Without the termination it is not a string, merely an array of chars

Yes a string (lowercase 's') is what you said, but there also exist String (capital 'S'). More on their use here

Ahh OK thank you all, still getting my head around C syntax. been spoilt in my career with scripting languages and I am not a coder

Will continue to learn :slight_smile:

The best way is use as little resources as possible, since we know the relation here being a-z and 0-9, you can just convert them to ASCII decimal and remove the associate array, in place of a simple function, fyi you used a int to store the Morse codes but an int fails to store the leading zeros so i used c strings instead.

Note as UKHeliBob said that c strings need a terminating null ‘\0’, to which the largest Morse code is 5 chars but if you set the array to 5 your get some unexpected results because the array no longer has space for the null zero ; ).

Just a concept buts here’s your code working, use the Serial monitor and either enter a single character, word or sentence and it will show the codes and flash the LED “pin 13” accordingly, set the delays accordingly as i have no idea about the exact time intervals.

const char morseCode[36][6] = {
  "01",     // a -- 97 ascii
  "1000",   // b
  "1010",   // c
  "100",    // d
  "0",      // e
  "0010",   // f
  "110",    // g
  "0000",   // h
  "00",     // i
  "0111",   // j
  "101",    // k
  "0100",   // l
  "11",     // m
  "10",     // n
  "111",    // o
  "0110",   // p
  "1101",   // q
  "010",    // r
  "000",    // s
  "1",      // t
  "001",    // u
  "0001",   // v
  "011",    // w
  "1001",   // x
  "1011",   // y
  "1100",   // z -- 122 ascii - position 26 in array
  "11111",  // 0 -- 48 ascii
  "01111",  // 1
  "00111",  // 2
  "00011",  // 3
  "00001",  // 4
  "00000",  // 5
  "10000",  // 6
  "11000",  // 7
  "11100",  // 8
  "11110",  // 9
};

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);  // LED_BUILTIN = 13
}

void loop() {
  if (Serial.available()) {
    char input = Serial.read();
    if (input >= 'a' && input <= 'z') {
      getmorse(input, true);
    }
    else if (input >= '0' && input <= '9') {
      getmorse(input, false);
    }
  }
}

void getmorse(char find, bool letter) {
  Serial.print(find); Serial.print(" = ");
  byte arrayPosition = find - '\0'; // char to ascii decimal
  if (letter) {
    Serial.println(morseCode[arrayPosition - 97]);
    flashLED(arrayPosition - 97);
  }
  else {
    Serial.println(morseCode[arrayPosition - 22]);
    flashLED(arrayPosition - 22);
  }
}

void flashLED(byte address) { // you could add a beeper to pin 13 too
  for (byte i = 0; i < 6; i++) {
    if (morseCode[address][i] == '0') { // short pulse
      digitalWrite(LED_BUILTIN, HIGH);
      delay(200);
      digitalWrite(LED_BUILTIN, LOW);
      delay(200);
    }
    else if (morseCode[address][i] == '1') { // long pulse
      digitalWrite(LED_BUILTIN, HIGH);
      delay(500);
      digitalWrite(LED_BUILTIN, LOW);
      delay(500);
    }
  }
}

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

...R

KawasakiZx10r:
The best way is use as little resources as possible, … fyi you used a int to store the Morse codes but an int fails to store the leading zeros so i used c strings instead.

using cString such as “1001” for ‘x’ or “00001” for ‘4’ is not the best way to “use as little resources as possible

As a morse code has less than 7 symbols, you could represent all of them in just one byte having a leading 1 as a flag to denote where the code starts (which you ignore in playback) and then a series of 0 or 1 bits

‘x’ would be 0b[color=red]1[/color][color=blue]1001[/color] and ‘4’ would be 0b[color=red]1[/color][color=blue]00001[/color]

that will save tons of memory…

Well that did cross my mind but i knew it was some extra work and i just wanted to show him that hes does not need two arrays, any who yes that is more efficient, here’s my code with just binary as you suggested.

const byte morseCodes[36] = {
  0b10100000,  // a - A
  0b00011000,  // b - B
  0b01011000,  // c - C
  0b00110000,  // d - D
  0b01000000,  // e - E
  0b01001000,  // f - F
  0b01110000,  // g - G
  0b00001000,  // h - H
  0b00100000,  // i - I
  0b11101000,  // j - J
  0b10110000,  // k - K
  0b00101000,  // l - L
  0b11100000,  // m - M
  0b01100000,  // n - N
  0b11110000,  // o - O
  0b01101000,  // p - P
  0b10111000,  // q - Q
  0b01010000,  // r - R
  0b00010000,  // s - S
  0b11000000,  // t - T
  0b10010000,  // u - U
  0b10001000,  // v - V
  0b11010000,  // w - W
  0b10011000,  // x - X
  0b11011000,  // y - Y
  0b00111000,  // z - Z
  0b11111100,  // 0
  0b11110100,  // 1
  0b11100100,  // 2
  0b11000100,  // 3
  0b10000100,  // 4
  0b00000100,  // 5
  0b00001100,  // 6
  0b00011100,  // 7
  0b00111100,  // 8
  0b01111100,  // 9
};

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);  // LED_BUILTIN is pin 13
  Serial.println(F("Serial to Morse code example."));
}

void loop() {
  if (Serial.available()) {
    char input = Serial.read();
    if (input >= 'a' && input <= 'z') {
      getMorseCode(input, true, false);
    }
    else if (input >= 'A' && input <= 'Z') {
      getMorseCode(input, true, true);
    }
    else if (input >= '0' && input <= '9') {
      getMorseCode(input, false, false);
    }
  }
}

void getMorseCode(char find, bool letter, bool upper) {
  byte arrayPosition = find - '\0'; // char to ascii decimal
  Serial.print(find); Serial.print(F(" = "));
  if (letter && !upper) {
    arrayPosition = arrayPosition - 97;
  }
  else if (letter && upper) {
    arrayPosition = arrayPosition - 65;
  }
  else {
    arrayPosition = arrayPosition - 22;
  }
  readMorseCode(arrayPosition);
}

void readMorseCode(byte address) {
  bool flagBit = false;   
  for (byte i = 0; i < 8; i++) {
    if ((bitRead(morseCodes[address], i) == 0) && flagBit) { // short pulse - dot
      Serial.print(F("0")); // dot
      flashLED(200);
    }
    else if ((bitRead(morseCodes[address], i) == 1) && flagBit) { // long pulse - dash
      Serial.print(F("1")); // dash
      flashLED(400);
    }
    else if ((bitRead(morseCodes[address], i) == 1) && !flagBit) { // flag bit
      flagBit = true;
    }
  }
  Serial.println(F(""));
}

void flashLED(int time) {  // you could add a beeper to pin 13 too
  digitalWrite(LED_BUILTIN, HIGH);
  delay(time);
  digitalWrite(LED_BUILTIN, LOW);
  delay(time);
}

Well done !

Sorry I have not replied. Work got in the way.

Just thanks guys, really nice info and working code! your all stars!