-3

Yes its homework We were suppose to have char 2D array holding character with size limit of 255 char char string[100][255];

Program neede: change the input morse code by a user to alphabet/English letter (Capital Letters)

Sample Input

2

 .... . .-.. .-.. --- / .-- --- .-. .-.. -..

 .--- --- -.- .

Sample OutPut

  • Case#1:

    HELLO WORLD
    
  • Case#2:

    JOKE
    

My only idea is to have the first characters of a word that is inputed by the user.. to be.. checked if its '.' or '-' then scrupulously and manually assigning.. the nested if(string[i][c]=='.') and the last if on each nested would be if(string[i][c]==' ') then that prints out the letter "E" example

if(string[i][c]=='.') {
    isspace(string[i][c+1])
    printf("E");
}

Now my question is.. is there any easier way for this problem? where i don't have to type the same '-' and '.' if statement.. and stuff? and have my mind explode? because I lose track of corresponding the next char with if or case statements?

HerlDerp
  • 47
  • 1
  • 1
  • 11
  • 1
    This definitely smells like homework. Your question is also badly worded. It's worth re-writing it so that there's an actual question in here. At the moment, it's just a jumble of information that doesn't make your problem clear. – Matt Taylor Jan 20 '15 at 12:24
  • 2
    Okay i'll edit it with straight to the point – HerlDerp Jan 20 '15 at 12:26

9 Answers9

12

You have already discovered that you can branch on each morse signal and that it is tiresome to hard-code all that as if-else statements. When you have done so, you will have noted a certain structure with ever deeper nested conditions. You can represent this structure as a tree:

                       *
                   /       \
               E               T
             /   \           /   \
           I       A       N       M
          / \     / \     / \     / \ 
         S   U   R   W   D   K   G   O
        / \ / \ / \ / \ / \ / \ / \ / \ 
        H V F * L * P J B X C Y Z Q * *

That same tree can be found in a (slightly) prettier form in the middle sections of the Wikipedia entry on Morse code. (The asterisks in the lowest row indicate encodings that are not one of the 26 letters of the English alphabet.)

You start at the top. Branch left on a dit, branch right on a dah and read the value when you are done.

There are many ways to implement trees. In this case, the tree's branches are all of the same depth, at least if we consider the asterisks, too. You can represent the tree as a linear array by indexing the nodes row-wise. When toe top node is 1, you get:

                       1
                   /       \
               2               3
             /   \           /   \
           4       5       6       7
          / \     / \     / \     / \ 
         8   9  10  11  12  13  14  15
        / \ / \ / \ / \ / \ / \ / \ / \
       16 ...                     ... 31

You can see that branching left from node n brings you to node 2*n and branching right brings you to its right neighbour with index 2*n + 1. Build up the index as you go, starting from 1 and then look up your letter in the array:

const char *letter = "**ETIANMSURWDKGOHVF?L?PJBXCYZQ??";

(The two asterisks at the front indicate illegal indices.)

M Oehm
  • 28,726
  • 3
  • 31
  • 42
  • thanks for the idea.. but i never tried making a tree.. so :( yeah i know how it works but it was never discussed on us on how to create them – HerlDerp Jan 20 '15 at 23:41
  • 1
    Well, the point is, that this isn't really a tree but a linear array. A flat tree, if you like. Anyway, it seems you've got plenty of more straightforward solutions to chose from. – M Oehm Jan 21 '15 at 06:17
3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

static const char *alpha[] = {
    ".-",   //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
};
static const char *num[] = {
    "-----", //0
    ".----", //1
    "..---", //2
    "...--", //3
    "....-", //4
    ".....", //5
    "-....", //6
    "--...", //7
    "---..", //8
    "----.", //9
};
static const char **table[] = { alpha, num };

typedef enum kind {
    ALPHA, NUM
} Kind;

typedef struct mtree {
    char value;
    struct mtree *dot;
    struct mtree *bar;
} MTree;

MTree *root;

void make_tree(void);
void drop_tree(void);
void encode_out(const char *s);
void decode_out(const char *s);

int main(void){
    make_tree();
    encode_out("HELLO WORLD");
    encode_out("JOKE");
    decode_out(".... . .-.. .-.. --- / .-- --- .-. .-.. -..");
    decode_out(".--- --- -.- .");
    drop_tree();
    return 0;
}

void encode_out(const char *s){
    for(;;++s){
        char ch = *s;
        if(ch == '\0')
            break;
        if(isalpha(ch)){
            ch = toupper(ch);
            fputs(table[ALPHA][ch - 'A'], stdout);//`-'A'` depend on the sequence of character code
        } else if(isdigit(ch))
            fputs(table[NUM][ch - '0'], stdout);
        else if(ch == ' ')
            fputc('/', stdout);//need rest space skip ?
        else 
            ;//invalid character => ignore
        fputc(' ', stdout);
    }
    fputc('\n', stdout);
}
static void decode_out_aux(MTree *tree, const char *s){
    if(tree == NULL) return;
    if(*s == '\0')
        fputc(tree->value, stdout);
    else if(*s == '/')
        fputc(' ', stdout);
    else if(*s == '.')
        decode_out_aux(tree->dot, ++s);
    else if(*s == '-')
        decode_out_aux(tree->bar, ++s);
}
void decode_out(const char *s){
    char *p;
    while(*s){
        p = strchr(s, ' ');
        if(p){
            if(p-s != 0){
                char code[p-s+1];
                memcpy(code, s, p-s);
                code[p-s]='\0';
                decode_out_aux(root, code);
            }
            s = p + 1;
        } else {
            decode_out_aux(root, s);
            break;
        }
    }
    fputc('\n', stdout);
}
static void insert_aux(MTree **tree, char ch, const char *s){
    if(*tree == NULL)
        *tree = calloc(1, sizeof(**tree));
    if(*s == '\0')
        (*tree)->value = ch;
    else if(*s == '.')
        insert_aux(&(*tree)->dot, ch, ++s);
    else if(*s == '-')
        insert_aux(&(*tree)->bar, ch, ++s);
}

static inline void insert(char ch, const char *s){
    if(*s == '.')
        insert_aux(&root->dot, ch, ++s);
    else if(*s == '-')
        insert_aux(&root->bar, ch, ++s);
}

void make_tree(void){
    root = calloc(1, sizeof(*root));
    //root->value = '/';//anything
    int i;
    for(i = 0; i < 26; ++i)
        insert('A'+i, table[ALPHA][i]);
    for(i = 0; i < 10; ++i)
        insert('0'+i, table[NUM][i]);
}
static void drop_tree_aux(MTree *root){
    if(root){
        drop_tree_aux(root->dot);
        drop_tree_aux(root->bar);
        free(root);
    }
}
void drop_tree(void){
    drop_tree_aux(root);
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • well this would work but most of the code is never been taught to me.. anyway.. this is not also asking input from the user.. the input is already put in the code.. oh well i'll try to learn this code more.. thanks – HerlDerp Jan 21 '15 at 01:52
  • you are not asked about accepting input from the user in my understanding – BLUEPIXY Jan 21 '15 at 02:00
  • its okay it was my bad,, not pointing it out in the question.. i editted it and still some things where missing.. i guess i'll have to add that or it's too late for that now.. lol – HerlDerp Jan 21 '15 at 02:20
  • "Program neede: change the input morse code by a user to alphabet/English letter (Capital Letters)" wait.. actually i did clarify that i guess i dont need to edit it oh well haha – HerlDerp Jan 21 '15 at 02:22
2

My very short and simple version::

#include <stdio.h>
#include <string.h>

typedef struct
{
    char* morse;
    char* ascii;
} morse_table_t;

int main(void) {
    char input[] = ".- -... -.-.";

    morse_table_t table[] = { {".-", "A"},
                              {"-...", "B"},
                              {"-.-.", "C"}
/* TODO: Fill in the rest of the Morse Table Here */
    };

    char* segment;
    int i;
    segment = strtok(input, " ");

    while(segment)
    {
        for(i=0; i<ARRAY_SIZE(table); ++i)
        {
            if (!strcmp(segment, table[i].morse)) puts(table[i].ascii);
        }
        segment = strtok(NULL, " ");
    }

    return 0;
}
abelenky
  • 63,815
  • 23
  • 109
  • 159
0

A brute force approach is the easiest -- not as brute as you propose, though.

  1. Create an array of input strings containing the Morse codes.
  2. Create an array of output strings containing what the strings from #1 represent (most of them will be a single character). Make sure this is in the exact same order as the array from #1. (You can do both at once using a 2-dimensional array or a structure, or possibly in even more advanced ways. Use what you know best.)
  3. Start of outer loop: initialize a destination string to empty.
  4. Read one character at a time from the input string, and:
    a. if it's a dash or dot, add it to the destination string;
    b. if not, end this loop.
  5. Repeat #4 until you encounter something not dash or dot. a. Compare the new string to each of the Morse codes in the array #1. When found, write the corresponding output code from the array #2.
    b. skip spaces in the input string;
    c. if you encounter the slash, write a space; and
    d. if you encounter the end of the input string, you are done.
  6. Repeat the loop at 3 until you encounter end-of-input.
Jongware
  • 22,200
  • 8
  • 54
  • 100
  • `char input[36]={"-. ","-... ","-.-. ","-.. ",". "} char output[36]={'A','B','C','D','E'}` is this what you meant? – HerlDerp Jan 20 '15 at 13:25
  • `char input[36]` holds only char characters like this `char input[36]={'A' ,'B', ...` . If you want to store string in array you have two possibilites but I recommend this one `char input[number of strings][maximum letters in each string]` the other one is `char* input[number of strings]` – Meninx - メネンックス Jan 20 '15 at 13:32
  • in that case you need to allocate space with `malloc()` after that `free()` it or just initialize it like I did in my answer but you cannot modify the content of the array in this case !! – Meninx - メネンックス Jan 20 '15 at 13:40
0

Here is a commented code that answers your question !

#include <stdio.h>
#include <string.h>

int main()
{
    /* string array will contain the whole line morse  code */
    char string[256]="";
    /* T is the number of test c ases */
    int T;
    scanf("%d ",&T);
    /* morse array contains all the letters from A to Z in  */
    /* morse code  */
    const char morse[][10]={
        ".-", //morse code of letter A
        "-...", //morse code of letter B
        "-.-." , //morse code of letter C
        "-.." , //morse code of letter D
        "." , //morse code of letter E
        "..-." , //morse code of letter F
        "--." , //morse code of letter G
        "...." , //morse code of letter H
        ".." , //morse code of letter I
        ".---" , //morse code of letter J
        "-.-" , //morse code of letter K
        ".-.." , //morse code of letter L
        "--" , //morse code of letter M
        "-." , //morse code of letter N
        "---" , //morse code of letter O
        ".--." , //morse code of letter P
        "--.-" , //morse code of letter Q
        ".-." , //morse code of letter R
        "..." , //morse code of letter S
        "-" , //morse code of letter T
        "..-" , //morse code of letter U
        "...-" , //morse code of letter V
        ".--" ,  //morse code of letter W
        "-..-" ,  //morse code of letter X
        "-.--" , //morse code of letter Y
        "--.." //morse code of letter Z
    };

    /* i will be used to print the number of test case */
    int i=1;
    /* while loop to do every  case */
    while(T--)
    {
        printf("Case#%d:\n",i);
        /* read the line of more code via f gets */
        fgets(string,sizeof(string),stdin);
        /* strtok is for extracting every word from the  line */
        char *p=strtok(string," ");
        while(p!=NULL)
        {
            /* check if the word is / print space and go to the next  word */
            if(p[0]=='/')
            {
                printf(" ");
                goto next;
            }
            int j=0;
            for(j=0; j<26;j++)
            {
                //check the correspondant string in morse array 
                    if(!strcmp(p,morse[j])) 
                    {
                        /* print the equivalent letter after finding the subscript */
                        /* A=65+0 .... Z=90=65+25 */
                        printf("%c",(j+65));
                    }
            }
next:
            /* fetch the next  word by ignoring space tab newline*/
            p=strtok(NULL,"\t \n");
        }
        printf("\n");
        i++;

    }

    return 0;
}

Keep in mind that this is not an optimal solution because for instance the search for the pattern is linear instead you can use the binary search after sorting the array !

Brievely, the code above can be improved !!

Hope it helps anyway !!

0
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define MAX 100
#define SIZE 255

int main(){
char string[MAX][SIZE];
char destination[MAX][5];
char *input[37]={".-","-...","-.-.","-..",".","..-.","--.",
                "....","..",".---","-.-",".-..","--","-.",
                "---",".--.","--.-",".-.","...","-","..-",
                "...-",".--","-..-","-.--","--..","-----",
                ".----","..---","...--","....-",".....",
                "-....","--...","---..","----.","/"};
char *output[37]= {"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"," "};
int i, c, x, m, j;
printf("Enter the number of Cases:");
scanf("%d", &x);
for(i=0;i<x;i++){
    printf("Case#%d: ", i+1);
        if (i==0){
            gets(string[0]);    }
        gets(string[i]);
}

for(i=0;i<x;i++){
    printf("Case#%d: ",i+1);
    for(c=0,m=0;string[i][c]!='\0';c++,m++){
        if(isspace(string[i][c])){
            m++;} 
        else{
        destination[m][c]=string[i][c]; }
    }
    for(j=0,m=0;j<37;j++){
        if(destination[m]==input[j]){
            printf("%d %s \n", i+1, output[j]); m++;
        }
    }
 }  

 return 0;
 }
I might have done something stupid here... ._. i'm just trying though.. does this not work?
HerlDerp
  • 47
  • 1
  • 1
  • 11
  • use strcmp to comparison of string. `if (i==0){ gets(string[0]); }` seem redundant. – BLUEPIXY Jan 21 '15 at 02:10
  • i made it split by Spaces if the user inputs space it would skip and save it to another row in the destination of array, in this way it is going letter by letter and also considering spaces. – HerlDerp Jan 21 '15 at 02:17
  • the `if(i==0){gets(string[0]);}` is there for some reason when i input the number of cases.. it skips the `string[0]`... – HerlDerp Jan 21 '15 at 02:18
  • ah, yes. this need for newline.(`scanf("%d", &x)`) – BLUEPIXY Jan 21 '15 at 02:22
  • You can. BTW I think you already has been proposed is that use the strtok to split the string, but Is there a reason you do not use it,? – BLUEPIXY Jan 21 '15 at 02:33
  • also, string even if one of Morse code is assumed to be up to 5 characters are required size of +1 since it is necessary to terminate at the NUL character. – BLUEPIXY Jan 21 '15 at 02:40
  • oh yeah thanks thanks.. for pointing the null.. i always forgot that btw. what does the strok do? i don't know that function yet.. – HerlDerp Jan 21 '15 at 02:47
  • `strtok` cut out the string in the specified separator character. – BLUEPIXY Jan 21 '15 at 02:51
  • now i'm happy i have the strtok function.. but i don't know where to put it.. and which char to make constant.. – HerlDerp Jan 21 '15 at 02:54
  • does it need to be constant? – HerlDerp Jan 21 '15 at 02:54
  • `strtok` to update the string (replacing the delimiter to `\0`). So, there is a need for treatment, such as advance copy if you do not want to change the string. However, I seem to not immutable in your case.. – BLUEPIXY Jan 21 '15 at 03:09
  • I have added a simple example of `strtok` and `strcmp`. – BLUEPIXY Jan 21 '15 at 03:20
0

sample of split string by using strtok

#include <stdio.h>
#include <string.h>

#define MAX 100
#define SIZE 255

int main(){
    char string[MAX][SIZE] = {
        ".... . .-.. .-.. --- / .-- --- .-. .-.. -..",
        ".--- --- -.- ."
    };
    char destination[MAX][8];
    int x = 2;//number of input
    int i, j, m;
    char *code, *separator = " ";//" " --> " \t\n"
    for(i=0;i<x;++i){
        j = 0;
        for(code = strtok(string[i], separator);
            code != NULL;
            code = strtok(NULL, separator)){
            printf("'%s'\n", code);
            strcpy(destination[j++], code);
        }
        m = j;
        if(strcmp(destination[0], "....")==0)
            puts("yes, It's 'H'.");
    }
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • i wish i could vote but i cant haha i need 15 rep oh well thnx – HerlDerp Jan 21 '15 at 04:47
  • i got it to printing one letter.. but i can't print all the letters from the input.. – HerlDerp Jan 21 '15 at 21:35
  • more specifically.. i wanna know how this code work... ` for(code = strtok(string[i], separator); code != NULL; code = strtok(NULL, separator)){ printf("'%s'\n", code); strcpy(destination[j++], code);` – HerlDerp Jan 21 '15 at 21:36
  • _i can't print all the letters from the input._ You need to search from the table loops to each character(encoded code). `for(j=0,m=0;j<37;j++){` : `37` is not the number of characters entered, is a number of tables. – BLUEPIXY Jan 21 '15 at 21:42
0

i found the solution! :D credits to BLUEPIXY for the for(i=0,j=0;i<x;++i){ for(code = strtok(string[i], separator);code != NULL;code = strtok(NULL,separator)){ strcpy(destination[i][j++], code);} }

Thanks guys

#include<stdio.h>
#include<string.h>
#define MAX 100
#define SIZE 255

int main(){
char string[MAX][SIZE];
char destination[MAX] [MAX][8];
char *input[38]={".-","-...","-.-.","-..",".","..-.","--.",
                "....","..",".---","-.-",".-..","--","-.",
                "---",".--.","--.-",".-.","...","-","..-",
                "...-",".--","-..-","-.--","--..","-----",
                ".----","..---","...--","....-",".....",
                "-....","--...","---..","----.","/"};
char *output[38]={"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"," "};
char *code, *separator = " ";
int i, c, x, j;
int m[MAX];
printf("Enter the number of Cases:");
scanf("%d", &x);
getchar();
for(i=0;i<x;i++){
    printf("Case#%d: ", i+1);
        gets(string[i]);
}

for(i=0,j=0;i<x;++i){
    for(code = strtok(string[i], separator);code != NULL;code = strtok(NULL, separator)){
        strcpy(destination[i][j++], code);

    }
    m[i] = j;
}

for(i=0;i<x;i++){
    printf("Case#%d: ", i+1);
    for(j=0;j<m[i];j++){
        for(c=0;c<37;c++){
            if(strcmp(destination[i][j], input[c])==0){
                printf("%s",output[c]);}
        }
    }
    printf("\n");
}
return 0;
}
HerlDerp
  • 47
  • 1
  • 1
  • 11
0

m-oehm's answer is really good, as I find all the other approaches involving tables a bit redundant. I followed the binary tree encoder, and came out with an example code that is ready to use.

The algorithm

You'll need to start with the binary tree parsed in preorder, find the index of the letter you want to encode to morse, convert that to binary, ignore the first digit, and then just assign the zeros to dots, and the ones to dashes. It's really simple.

A C implementation example enter image description here

Also there is a full code example here.

Community
  • 1
  • 1
radhoo
  • 2,877
  • 26
  • 27