Addressing elements of 2-dimensional array using compact pointer in C

Viewed 58

I am implementing Morse code using C and ran into some fundamentals.

Basic idea is I have 2-dimensional character array for A through Z. The first element of each array is an alphabet followed by corresponding Morse code. Program will receive a character which will be parsed through entire array once the match is found I will spit out the Morse code. I am able to run this program using help of simple array manipulation but I an running into issue with compact array.

The array is defined as below,

char *morseKey[37] = { 
    {"A.-"},
    {"B-..."},
    {"C-.-."},
    {"D-.."},
    {"E."},
    {"F..-."},
    {"G--."},
    {"H...."},
    {"I.."},
    {"J.---"},
    {"L.-.."},
    {"K-.-"},
    {"L.-.."},
    {"M--"},
    {"N-."},
    {"O---"},
    {"P.--."},
    {"Q--.-"},
    {"R.-."},
    {"S..."},
    {"T-"},
    {"U..-"},
    {"V...-"},
    {"W.--"},
    {"X-..-"},
    {"Y-.--"},
    {"Z--.."}
};

Regular 2D array implementation ,

/*
    Find a match for each character from nameCode string that need to be 
    transformed to Morse Code. Once the match is found then based on the 
    Morse code flash the LED for dash and dot.
*/
for(char *cp_nameCode = &nameCode[0]; *cp_nameCode != '\0'; cp_nameCode++)
{
    charLoc = GetMorseCode(morseKey, first, last, *cp_nameCode);
    for(int col = 1; cp_morseKey[charLoc][col] != '\0'; col++)
    {
        cp_morseKey[charLoc][col] == '.' ? dot() : dash();            
    }
}

Now my approach is to declare a pointer to point to this array as below,

char **cp = morseCode;

and then with the help of *cp and **cp access the columns and rows sequentially. But it does not work.

Alternatively, I tried declaring,

char **cp = morseCode;
char *cp_row = *morseCode;

and then accessing as below,

while(*cp != '\0')
{
    while(*cp_row != '\0')
    {
        //printf("%c\n", **cp++);
        printf("%c\n", *cp_row++);
    }
    cp_row = *((++*cp));
    //cp++;
}

But the code does not go beyond the first row. I feel there is still gap in my pointer knowledge.

I will appreciate any pointers to resolve this bottleneck.

1 Answers

You can simplify your lookup table by using the LETTER you want to code as an INDEX into the array. For example (not tested, no "bullet proofing" or error checking, only works for capital letters A..Z):

#define NELMS(A) A/sizeof(A[0])

char *morseKeys[] = { 
    ".-",
    "-...",
    "-.-.",
    "-..",
    ".",
    "..-.",
    "--.",
    "....",
    "..",
    ".---",
    ".-..",
    "-.-",
    ".-..",
    "--",
    "-.",
    "---",
    ".--.",
    "--.-",
    ".-.",
    "...",
    "-",
    "..-",
    "...-",
    ".--",
    "-..-",
    "-.--",
    "--.."
};

char *encodeLetter(char letter) {
  return morseKeys[letter - 'A'];
}

char decodeLetter(char *code) {
  // Search array
  for (int i=0; i < NELMS(morseKeys); i++) {
    if (strcmp(morseKeys[i], code) == 0)
      return 'A' + i;
  }
  // Not found
  return 0;
}

Hopefully that helps ... at least a little bit.

Q: What additional processing do you need to do once you've got the correct morse string (e.g. "-...")? I'm unclear from your code what else (if anything) you need to do.


In the above example, I was trying to show:

  • You DON'T need to include the letter (e.g. "A") in your morseKey[] values
  • You DON'T need to specify the array length ("37"), and
  • You DON'T necessarily need a "loop" to SEARCH the array. "encodeLetter()", for example, does a "direct lookup" by using the letter as the index value. It's much, much faster.

To answer your other question: if you want to iterate the morseKey[] values with a char** pointer, you would do something like this:

char *strings[] = { "AAA", "BBB", "CCC", 0 };
char **pp = strings;
while (*pp)
  printf ("value: %s\n", *pp++);
Related