. . . . . . - . . . - -

This is a discussion on . . . . . . - . . . - - within the C++ Programming forums, part of the General Programming Boards category; Making a couple attempts at translating morse code into alpha-numeric. I want to see if I can do this without ...

  1. #1
    VA National Guard The Brain's Avatar
    Join Date
    May 2004
    Location
    Manassas, VA USA
    Posts
    903

    . . . . . . - . . . - -

    Making a couple attempts at translating morse code into alpha-numeric. I want to see if I can do this without pointers or using the <string> library. (This is kinda a lesson about how using pointers can make things easier) I am attempting to parse in the user entry into a multi-demensional array. Both programs compile fine, but print jibberish to the screeen. Through debugging, it seems that alpha[ ] is being assigned every strcmp( ) case. Just wondering if someone could take a look through me' code and make any suggestions.

    version 1 and version 2


    edit history:

    * replaced morse_array[a][b] with &morse_array[a][b] as a strcmp() argument
    * changed alpha[a] to alpha[b]
    * changed if's to else if's
    * getline(user_input, 79) to getline(user_input, 80)
    * removed trailing white spaces
    Last edited by The Brain; 05-12-2005 at 04:55 PM.
    • "Problem Solving C++, The Object of Programming" -Walter Savitch
    • "Data Structures and Other Objects using C++" -Walter Savitch
    • "Assembly Language for Intel-Based Computers" -Kip Irvine
    • "Programming Windows, 5th edition" -Charles Petzold
    • "Visual C++ MFC Programming by Example" -John E. Swanke
    • "Network Programming Windows" -Jones/Ohlund
    • "Sams Teach Yourself Game Programming in 24 Hours" -Michael Morrison
    • "Mathmatics for 3D Game Programming & Computer Graphics" -Eric Lengyel

  2. #2
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Code:
     if (strcmp(morse_char, "-.-.  "))
                             alpha[a]='c';
             
                         if (strcmp(morse_char, "-..   "))
                             alpha[a]='d';
             
                         if (strcmp(morse_char, ".     "))
                             alpha[a]='e';
    Why the trailing spaces?
    -.. . would be valid

    Code:
    char user_input[80];
    // ... 
    cin.getline(user_input, 79);
    http://www.cppreference.com/cppio/getline.html

    Code:
     cout << alpha;
    Where has alpha been null terminated?

    Tips: Use strtok
    Use else if to avoid testing things you know will be false

  3. #3
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    After quick look I'd change the variable as the index of the alpha array from a to c and initialize c to 0 before running the nested a/b loops. I'd change all the if's in the nested array to else ifs except the first one. Then I'd increment c after each conversion from morse to alpha, after the last else if. As it is each successful conversion will overwrite alpha[a] until a is incremented.
    You're only born perfect.

  4. #4
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    A couple more points:

    There is no need for a nested loop in this. You don't have to use strtok if you use strchr and strncmp.

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    I want to see if I can do this without pointers
    int strcmp( const char *str1, const char *str2 );

    <cstring> functions like strcmp() only work on cstrings, which are pointers to char arrays that have a '\0' character at the end.
    Last edited by 7stud; 05-12-2005 at 03:54 PM.

  6. #6
    VA National Guard The Brain's Avatar
    Join Date
    May 2004
    Location
    Manassas, VA USA
    Posts
    903
    by "without pointers" i mean without strtok( )
    Last edited by The Brain; 05-13-2005 at 05:42 AM.
    • "Problem Solving C++, The Object of Programming" -Walter Savitch
    • "Data Structures and Other Objects using C++" -Walter Savitch
    • "Assembly Language for Intel-Based Computers" -Kip Irvine
    • "Programming Windows, 5th edition" -Charles Petzold
    • "Visual C++ MFC Programming by Example" -John E. Swanke
    • "Network Programming Windows" -Jones/Ohlund
    • "Sams Teach Yourself Game Programming in 24 Hours" -Michael Morrison
    • "Mathmatics for 3D Game Programming & Computer Graphics" -Eric Lengyel

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Wouldn't a FSM be most efficient here? Or simply a binary tree of characters (also a kind of FSM)? You walk along the tree until you hit a space, then look at the character associated with your current node. With every dot you go to the left child, every dash leads you to the right child.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    I was bored, so I put my suggestion into practice:
    Code:
    #include <iostream>
    #include <string>
    
    struct morse_node
    {
    	const char ch;
    	const morse_node *dot;
    	const morse_node *dash;
    };
    
    /*
                   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
    5 4   3      2                   1 6                   7         8     9  0
    */
    
    const morse_node
    mc_0 = { '0', NULL, NULL },
    mc_9 = { '9', NULL, NULL },
    mc_8 = { '8', NULL, NULL },
    mc_7 = { '7', NULL, NULL },
    mc_6 = { '6', NULL, NULL },
    mc_1 = { '1', NULL, NULL },
    mc_2 = { '2', NULL, NULL },
    mc_3 = { '3', NULL, NULL },
    mc_4 = { '4', NULL, NULL },
    mc_5 = { '5', NULL, NULL },
    mc_Odash = { '\0', &mc_9, &mc_0 },
    mc_Odot = { '\0', &mc_8, NULL },
    mc_Q = { 'q', NULL, NULL },
    mc_Z = { 'z', &mc_7, NULL },
    mc_Y = { 'y', NULL, NULL },
    mc_C = { 'c', NULL, NULL },
    mc_X = { 'x', NULL, NULL },
    mc_B = { 'b', &mc_6, NULL },
    mc_J = { 'j', NULL, &mc_1 },
    mc_P = { 'p', NULL, NULL },
    mc_L = { 'l', NULL, NULL },
    mc_Udash = { '\0', NULL, &mc_2 },
    mc_F = { 'f', NULL, NULL },
    mc_V = { 'v', NULL, &mc_3 },
    mc_H = { 'h', &mc_5, &mc_4 },
    mc_O = { 'o', &mc_Odot, &mc_Odash },
    mc_G = { 'g', &mc_Z, &mc_Q },
    mc_K = { 'k', &mc_C, &mc_Y },
    mc_D = { 'd', &mc_B, &mc_X },
    mc_W = { 'w', &mc_P, &mc_J },
    mc_R = { 'r', &mc_L, NULL },
    mc_U = { 'u', &mc_F, &mc_Udash },
    mc_S = { 's', &mc_H, &mc_V },
    mc_M = { 'm', &mc_G, &mc_O },
    mc_N = { 'n', &mc_D, &mc_K },
    mc_A = { 'a', &mc_R, &mc_W },
    mc_I = { 'i', &mc_S, &mc_U },
    mc_T = { 't', &mc_N, &mc_M },
    mc_E = { 'e', &mc_I, &mc_A },
    mc_root = { '\0', &mc_E, &mc_T };
    
    
    int main()
    {
        char ch;
        std::string seq;
        const morse_node *loc = &mc_root;
        int spcount = 0;
        bool run = true;
    
        while(run && std::cin.get(ch)) {
            switch(ch)
            {
            case '.':
            case '-':
                spcount = 0;
                seq += ch;
                loc = ch == '.' ? loc->dot : loc->dash;
                if(!loc) {
                    std::cerr << "Invalid sequence: " << seq << '\n';
                    seq.clear();
                    loc = &mc_root;
                }
                break;
    
            case '\n':
                ++spcount;
            case '\t':
                ++spcount;
            case ' ':
                ++spcount;
                if(loc != &mc_root) {
                    if(loc->ch == '\0') {
                        std::cerr << "Invalid sequence: " << seq << '\n';
                    } else {
                        std::cout << loc->ch;
                    }
                }
                if(spcount >= 3) {
                    std::cout << '\n';
                    spcount = 0;
                } else if(spcount >= 2) {
                    std::cout << ' ';
                    spcount = 0;
                }
                seq.clear();
                loc = &mc_root;
                break;
    
            case '!':
                run = false;
                break;
    
            default:
                std::cerr << "Invalid character: " << ch << '\n';
                seq.clear();
                loc = &mc_root;
                break;
            }
        }
        if(loc->ch != '\0') {
            std::cout << loc->ch;
        }
        std::cout << std::endl;
    }
    (Note: it uses pointers. But then, strictly speaking, so do all of your attempts.)

    The program decodes international morse, and here's the input sequence for "hello world":
    .... . .-.. .-.. --- .-- --- .-. .-.. -..
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,812
    Quote Originally Posted by 7stud
    int strcmp( const char *str1, const char *str2 );

    <cstring> functions like strcmp() only work on cstrings, which are pointers to char arrays that have a '\0' character at the end.
    You do know that arrays are treated like pointers right? So passing in an array will work the same as passing in a pointer.
    Woop?

  10. #10
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    I think what 7stud is trying to say is that no matter what you'll be using pointers as arrays degrade to pointers when passed to a function

  11. #11
    Registered User
    Join Date
    Mar 2002
    Posts
    1,595
    I've revamped the OPs protocol. I used the same user input mechanism, but i convert the original string of dots/dashes/spaces into morse "characters" and then convert morse "characters" into alphanumeric chars without using morse "words" and I use just a single null terminated char string as the final output, not individual words. I made each morse character a string of dots/dashes so I could compare them with the conversion strings OP provided (I did have to clean up the conversion strings for the p and w chars and I used syntax like if(strcmp(morse_array[b], ".--") == 0) alpha[c] = 'w'; rather than the syntax originally utilized). I also added a line to null terminate each string of dots/dashes at the first space char, and I added a morse_array element consisting of a single space as a string when I found double spacing between morse "words" so I could get spaces between words in the final output string. I only needed a single for loop to convert the char in morse_array into char that I stored in alpha. I used the actual number of morse chars to convert as the termination value of the loop rather than an arbitrary hard coded number of char to convert, I did increment c after each conversion from morse to alpha, and I null terminated alpha following completion of all conversions. I ended up with a warning that you shouldn't pass a local string variable as the return variable, but that didn't hurt the output, and could be cleared by passing the result string as a parameter rather than declaring locally, if desired. All in all it worked out fine once the details were ironed out and it doesn't use a pointer, in the strict sense of the concept, as indicated desirable by the OP. If the OP has questions about the details outlined above I'd be happy to try to walk him/her through them.
    You're only born perfect.

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    I changed my approach to not use pointers as well. Now it's a lot less readable.
    Code:
    #include <iostream>
    #include <string>
    
    struct morse_node
    {
    	const char ch;
    	const int dot;
    	const int dash;
    };
    
    /*
                   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
    5 4   3      2                   1 6                   7         8     9  0
    */
    
    const morse_node nodes[] = {
    /* mc_0 = */ { '0', -1, -1 }, /* 0 */
    /* mc_9 = */ { '9', -1, -1 }, /* 1 */
    /* mc_8 = */ { '8', -1, -1 }, /* 2 */
    /* mc_7 = */ { '7', -1, -1 }, /* 3 */
    /* mc_6 = */ { '6', -1, -1 }, /* 4 */
    /* mc_1 = */ { '1', -1, -1 }, /* 5 */
    /* mc_2 = */ { '2', -1, -1 }, /* 6 */
    /* mc_3 = */ { '3', -1, -1 }, /* 7 */
    /* mc_4 = */ { '4', -1, -1 }, /* 8 */
    /* mc_5 = */ { '5', -1, -1 }, /* 9 */
    /* mc_Odash = */ { '\0', /*&mc_9*/1, /*&mc_0*/0 }, /* 10 */
    /* mc_Odot = */ { '\0', /*&mc_8*/2, -1 }, /* 11 */
    /* mc_Q = */ { 'q', -1, -1 }, /* 12 */
    /* mc_Z = */ { 'z', /*&mc_7*/3, -1 }, /* 13 */
    /* mc_Y = */ { 'y', -1, -1 }, /* 14 */
    /* mc_C = */ { 'c', -1, -1 }, /* 15 */
    /* mc_X = */ { 'x', -1, -1 }, /* 16 */
    /* mc_B = */ { 'b', /*&mc_6*/4, -1 }, /* 17 */
    /* mc_J = */ { 'j', -1, /*&mc_1*/5 }, /* 18 */
    /* mc_P = */ { 'p', -1, -1 }, /* 19 */
    /* mc_L = */ { 'l', -1, -1 }, /* 20 */
    /* mc_Udash = */ { '\0', -1, /*&mc_2*/6 }, /* 21 */
    /* mc_F = */ { 'f', -1, -1 }, /* 22 */
    /* mc_V = */ { 'v', -1, /*&mc_3*/7 }, /* 23 */
    /* mc_H = */ { 'h', /*&mc_5*/9, /*&mc_4*/8 }, /* 24 */
    /* mc_O = */ { 'o', /*&mc_Odot*/11, /*&mc_Odash*/10 }, /* 25 */
    /* mc_G = */ { 'g', /*&mc_Z*/13, /*&mc_Q*/12 }, /* 26 */
    /* mc_K = */ { 'k', /*&mc_C*/15, /*&mc_Y*/14 }, /* 27 */
    /* mc_D = */ { 'd', /*&mc_B*/17, /*&mc_X*/16 }, /* 28 */
    /* mc_W = */ { 'w', /*&mc_P*/19, /*&mc_J*/18 }, /* 29 */
    /* mc_R = */ { 'r', /*&mc_L*/20, -1 }, /* 30 */
    /* mc_U = */ { 'u', /*&mc_F*/22, /*&mc_Udash*/21 }, /* 31 */
    /* mc_S = */ { 's', /*&mc_H*/24, /*&mc_V*/23 }, /* 32 */
    /* mc_M = */ { 'm', /*&mc_G*/26, /*&mc_O*/25 }, /* 33 */
    /* mc_N = */ { 'n', /*&mc_D*/28, /*&mc_K*/27 }, /* 34 */
    /* mc_A = */ { 'a', /*&mc_R*/30, /*&mc_W*/29 }, /* 35 */
    /* mc_I = */ { 'i', /*&mc_S*/32, /*&mc_U*/31 }, /* 36 */
    /* mc_T = */ { 't', /*&mc_N*/34, /*&mc_M*/33 }, /* 37 */
    /* mc_E = */ { 'e', /*&mc_I*/36, /*&mc_A*/35 }, /* 38 */
    /* mc_root = */ { '\0', /*&mc_E*/38, /*&mc_T*/37 } /* 39 */
    };
    
    #define start 39
    
    
    int main()
    {
        char ch;
        std::string seq;
        int loc = start;
        int spcount = 0;
        bool run = true;
    
        while(run && std::cin.get(ch)) {
            switch(ch)
            {
            case '.':
            case '-':
                spcount = 0;
                seq += ch;
                loc = ch == '.' ? nodes[loc].dot : nodes[loc].dash;
                if(loc == -1) {
                    std::cerr << "Invalid sequence: " << seq << '\n';
                    seq.clear();
                    loc = start;
                }
                break;
    
            case '\n':
                ++spcount;
            case '\t':
                ++spcount;
            case ' ':
                ++spcount;
                if(loc != start) {
                    if(nodes[loc].ch == '\0') {
                        std::cerr << "Invalid sequence: " << seq << '\n';
                    } else {
                        std::cout << nodes[loc].ch;
                    }
                }
                if(spcount >= 3) {
                    std::cout << '\n';
                    spcount = 0;
                } else if(spcount >= 2) {
                    std::cout << ' ';
                    spcount = 0;
                }
                seq.clear();
                loc = start;
                break;
    
            case '!':
                run = false;
                break;
    
            default:
                std::cerr << "Invalid character: " << ch << '\n';
                seq.clear();
                loc = start;
                break;
            }
        }
        if(nodes[loc].ch != '\0') {
            std::cout << nodes[loc].ch;
        }
        std::cout << std::endl;
    }
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    Registered User manofsteel972's Avatar
    Join Date
    Mar 2004
    Posts
    317
    Just thought of another way to tackle the problem using bitfields thought I would share.

    Code:
    #include<iostream>
    #include<bitset>
    using namespace std;
    /*
    00 00 00 11 10 A
    00 10 10 10 11 B
    00 10 11 10 11 C
    */
    int main(void)
    {
     
    	bitset<32> value;
    	size_t n=0;
     
     
    	char l='\0';
     
    	while(l!='\n')
    	{
    		do{
    			cin.get(l);
     
    			//remember binary is reverse so .- for "A" will be reversed in binary to 11 10
    			if(l=='-') //sets bit patter 11 for dash
    			{
    				value.set(n,true);
    				n+=1;
    				value.set(n,true);
    			}
    			if(l=='.') //sets bit pattern 10 for dot
    			{
    				value.set(n,false);
    				n+=1;
    				value.set(n,true);
    			}
    			n++;
     
     
    		} while((l!=' ')&&(l!='\n'));
     
     
    		//cout<<value.to_ulong()<<"\n"; //use this to get the decimal number for case statement for each letter
     
     
    		switch(value.to_ulong())
    		{
    		case 14:
    			cout<<"A";
    			break;
    		case 171:
    			cout<<"B";
    			break;
    		case 187:
    			cout<<"C";
    			break;
     
    		}
     
    		value.reset();
    		n=0;
     
    	}
    	return 0;
    }
     
    // sample input
    // .- -... -.-. 
    // sample output
    // ABC
    Last edited by manofsteel972; 05-14-2005 at 04:52 PM. Reason: bad formating
    "Knowledge is proud that she knows so much; Wisdom is humble that she knows no more."
    -- Cowper

    Operating Systems=Slackware Linux 9.1,Windows 98/Xp
    Compilers=gcc 3.2.3, Visual C++ 6.0, DevC++(Mingw)

    You may teach a person from now until doom's day, but that person will only know what he learns himself.

    Now I know what doesn't work.

    A problem is understood by solving it, not by pondering it.

    For a bit of humor check out xkcd web comic http://xkcd.com/235/

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Very easy to crash that one.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  15. #15
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    So when you input your morse code, do you have to put a space between every "letter", or how do you decide what I've just typed:
    Code:
    .....
    Is that si? Or is that is? Or is that just the number 5? I guess you'd have to. I've heard morse on a radio before. Crazy to listen to.

    Quzah.
    Hope is the first step on the road to disappointment.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21