C中的摩尔斯电码转换器

时间:2015-01-20 12:15:41

标签: c encoder decoder

是的功课 我们假设有char二维数组保持字符,大小限制为255 char char string[100][255];

程序neede:用户将输入的莫尔斯代码更改为字母/英文字母(大写字母)

示例输入

2

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

 .--- --- -.- .

Sample OutPut

  • 情况#1:

    HELLO WORLD
    
  • 情况#2:

    JOKE
    

我唯一的想法是让一个单词的第一个字符由用户输入..要检查它是否是'。'或' - '然后仔细并手动分配..嵌套的if(string[i][c]=='.')和每个嵌套的最后一个if将是if(string[i][c]==' ')然后打印出字母“E”示例

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

现在我的问题是..有没有更容易解决这个问题的方法?我不需要输入相同的' - '和'。'如果声明..和东西?我的思绪爆炸了吗?因为我用if或case语句丢失了对应下一个char的跟踪?

9 个答案:

答案 0 :(得分:11)

您已经发现可以对每个莫尔斯信号进行分支,并且将所有这些信号硬编码为if - else语句是很烦人的。当您这样做时,您将注意到具有更深嵌套条件的特定结构。您可以将此结构表示为树:

                       *
                   /       \
               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 * *

同一棵树可以在middle sections of the Wikipedia entry on Morse code中以(稍微)更漂亮的形式找到。 (最下面一行中的星号表示不是英文字母26个字母之一的编码。)

你从顶部开始。分支留在dit上,分支在dah上,并在完成后读取值。

实现树的方法有很多种。在这种情况下,树的分支都具有相同的深度,至少如果我们考虑星号也是如此。您可以通过逐行索引节点将树表示为线性数组。当toe top node为1时,你得到:

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

您可以看到从节点n左侧的分支将您带到节点2*n,并且右侧分支将您带到索引为2*n + 1的右邻居。从1开始构建索引,然后在数组中查找您的字母:

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

(前面的两个星号表示非法指数。)

答案 1 :(得分:2)

我的简短版本::

#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;
}

答案 2 :(得分:1)

#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);
}

答案 3 :(得分:0)

蛮力方法是最简单的 - 不像你提议的那样粗暴。

  1. 创建一个包含摩尔斯电码的输入字符串数组。
  2. 创建一个输出字符串数组,其中包含#1中的字符串所代表的字符串(大多数字符串将是单个字符)。确保它与#1中的数组完全相同。 (您可以使用二维数组或结构同时执行这两项操作,也可以使用更高级的方法执行这两种操作。使用您最了解的内容。)
  3. 外部循环开始:将目标字符串初始化为空。
  4. 从输入字符串一次读取一个字符,并且:
    一个。如果它是短划线或点,请将其添加到目标字符串;
    湾如果没有,请结束此循环。
  5. 重复#4,直到遇到没有破折号或点的东西。 一个。将新字符串与数组#1中的每个莫尔斯代码进行比较。找到后,从阵列#2中写入相应的输出代码 湾跳过输入字符串中的空格;
    C。如果你遇到斜线,写一个空格;和
    d。如果遇到输入字符串的结尾,那么就完成了。
  6. 在3处重复循环,直到遇到输入结束。

答案 4 :(得分:0)

这是一个评论代码,可以回答您的问题!

#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;
}

请记住,这不是最佳解决方案,因为例如搜索模式是线性的,而您可以在对数组进行排序后使用二进制搜索!

简单地说,上面的代码可以改进!!

希望它有所帮助!!

答案 5 :(得分: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?

答案 6 :(得分:0)

使用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;
}

答案 7 :(得分:0)

我找到了解决方案! :D学分为BLUEPIXY 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);} }

谢谢你们

#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;
}

答案 8 :(得分:0)

m-oehm的回答非常好,因为我发现涉及表的所有其他方法都有点多余。我遵循了二叉树编码器,并提供了一个可以使用的示例代码。

算法

您需要从预先解析的二叉树开始,找到要编码为morse的字母的索引,将其转换为二进制,忽略第一个数字,然后将零分配给点破碎的那些。这很简单。

C实施示例 enter image description here

还有一个完整的代码示例here