GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 01-May-2006, 14:56
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Convert sentence to morse code


This code is to convert a sentence into Morse code. The run log always terminates with error:

Quote:
Enter a sentence to be translated to Morse Code:
Hi
....
..
terminate called after throwing an instance of 'std:ut_of_range'
what(): basic_string::at

C9PP9 has exited due to signal 6 (SIGABRT).

TIA for your help!!!

CPP / C++ / C Code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#define inFile "/Users/me/Documents/COMSCI101/C9PP9/MorseCode.txt"    //define location for MorseCode.txt

//function prototypes
void readCode (ifstream&, string[]);
void writeCode (const string[], const char);

int main () 
{
    string codeArray[26];   //Storage for Morse code characters read from codeFile
    string sentence;        //Input - next word
    char nextChar;          //Storage for next character read from string sentence
    int i;                  //counter variable
    ifstream codeFile (inFile); //Declare ifstream codeFile, associate with and open inFile
    if (codeFile.fail()) {
        cerr << "Error opening Code file" << endl;
        return EXIT_FAILURE;
    }
    
    readCode (codeFile, codeArray); //call function readCode to read each code into codeArray
    
    cout << "Enter a sentence to be translated to Morse Code: " << endl;
    cin >> sentence;
    while (sentence != ".") {   //while a period is not entered
        i = 0;                  //initialize counter i
        
        //cout << "< At beginning of outer while loop, i is " << i ;  //uncomment for error checking
        
        nextChar = sentence.at(i);  //get each character in turn from string sentence
        
        //cout << ", and nextChar is " << nextChar << " >" << endl;     //uncomment for error checking
        
        nextChar = toupper(nextChar);   //convert all lowercase characters to uppercase
        
        while (nextChar != ' ') {               //while blank space is not encountered
            writeCode (codeArray, nextChar);    //call function writeCode to display Morse code for nextChar
            i++;                                //increment counter i
            nextChar = sentence.at(i);          //get next character from string sentence
            
            //cout << "<< In inner while loop, nextChar is " << nextChar << ">>" << endl; //Uncomment for error checking
            
            if (nextChar == ' ') {              //if blank space is read, 
                break;                          //break out of loop
            }   
            nextChar = toupper(nextChar);       //convert lowercase to uppercase
        }
        cout << endl;
    }
    codeFile.close();
    
    return 0;
}

//Stores Morse codes read from codeFile in array code
void readCode (ifstream& codeFile, string codeArray[])
{
    int i;                      //counter variable
    string nextCode;            //storage for next code in file
    for (i = 0; i < 26; i++) {  //store strings from codeFile into codeArray
        codeFile >> nextCode;
        codeArray[i] = nextCode;
        
        //cout << nextCode << endl ;//uncomment to see contents of codeFile displayed
    }
}

//Writes Morse equivalent for a letter
void writeCode (const string codeArray[], const char letter)
{
    //cout << "<<< function writeCode called with character " << letter << ">>>" << endl; //uncomment for error checking
    //cout << "<<< integer value passed to codeArray is " << (int) letter - (int) 'A' << " >>>" << endl; //uncomment for error checking
    cout << codeArray[letter - (int) 'A'];  //display value of codeArray at location 0 - 25
    cout << " ";    //Display space between code
    //cout << endl;
}
Last edited by LuciWiz : 02-May-2006 at 07:51. Reason: Edited title; Previous title was "somebody please tell me what I'm doing wrong..."
  #2  
Old 01-May-2006, 15:01
QED's Avatar
QED QED is offline
Member
 
Join Date: Feb 2005
Location: Hudson Valley, NY
Posts: 231
QED is a jewel in the roughQED is a jewel in the roughQED is a jewel in the rough

Re: somebody please tell me what I'm doing wrong...


The only terminal conditions I see in your loops are a check for '.' and a check for ' '. If your string ends in anything else (which I expect is the case, since newline is likely the last thing read in), then you will keep read characters past the end of the string, hence the index counter i will cause string::at() to throw an exception.

Matthew
__________________
I was born not knowing and have only had a little time to change that here and there. -- Richard P. Feynman

Boris Podolsky: James! How's the rat business?
James Moreland: Well, actually it's mostly students I'm experimenting on now.
Kurt Gödel: My God, the mazes must be enormous.
  #3  
Old 01-May-2006, 21:17
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Re: somebody please tell me what I'm doing wrong...


(Edit) I've worked it out while writing this post - but am still interested in feedback on my solution)

OK, I'm still having a brain freeze on this. Help me break it down.

If I get a word from an input stream:

CPP / C++ / C Code:
cout << "Enter a sentence to be translated to Morse Code: " << endl;
 while (cin >> sentence) {   //while newline is not encountered, extract next word

And enter:

Quote:
Hi
followed by the newline character, the extraction operation grabs "Hi" , assigns it to variable sentence, ignores the newline character, and positions the input buffer pointer at the next character, right?
Now, if I was assigning "Hi" to a C-style string (character array), there would actually be three characters assigned, 'H', 'i', '\0'. But since I'm using a C++ string, there are only the two characters in the string, as evidenced by using

CPP / C++ / C Code:
cout << "sentence string length is: " << sentence.length() << endl;
and run log shows :

Quote:
Enter a sentence to be translated to Morse Code:
Hi
sentence string length is: 2

So having gotten that out of the way, and using input "Hi" as an example, using loop repetition condition

CPP / C++ / C Code:
while (nextChar = sentence.at(i))
should cause the loop to execute only twice. Both times it should call function writeCode with the current character (causing the corresponding Morse code to be displayed), increment the counter, and test the loop repetition condition. After the second repetition, the condition should fail, the loop should not execute, and control should return to the outer while loop, awaiting input from the keyboard.

The problem in my code is that
CPP / C++ / C Code:
while (nextChar = sentence.at(i))
doesn't actually cause the loop to terminate because the C++ string has no terminating null character, so it's not a valid loop termination condition, and the program tries to read from the string array at an out-of-bounds position. So my immediate thought would be to get the string length each time and use that as the termination condition. And indeed that works.

The complete (revised) code of that section is:
CPP / C++ / C Code:
cout << "Enter a sentence to be translated to Morse Code: " << endl;

    while (cin >> sentence) {   //while newline is not encountered, extract next word
        i = 0;                  //initialize counter i
        int length;            //Variable to store word length
        length = sentence.length(); //get length of sentence, store in variable length
        while (i < length) {   //while counter is less then the length of the word
            nextChar = sentence.at(i);//get each character in the word
            nextChar = toupper(nextChar);  //convert lower to upper case
            if (nextChar == '.') {   //If sentence ends in period, break out of loop
                break;
            }
            writeCode (codeArray, nextChar);    //call function writeCode to display Morse code for nextChar
            i++;                                //increment counter i
            }
        cout << endl;
    }

I still have a little work to do, but that's basically working.
Is that the "best" solution given the low level of programming that I'm on?
  #4  
Old 02-May-2006, 00:14
WaltP's Avatar
WaltP WaltP is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Midwest US
Posts: 3,373
WaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to all

Re: somebody please tell me what I'm doing wrong...


Instead of reading one word at a time, read the entire sentence with getline(). This will allow you to process whitespace (TABs and SPACEs) more accurately.

Also, why stop when you get a '.'? A period is a valid Morse Code character. IMO, you should process all valid characters and either ignore or flag all invalid characters.
__________________

The 3 Laws of the Procrastination Society:
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
  #5  
Old 02-May-2006, 07:29
QED's Avatar
QED QED is offline
Member
 
Join Date: Feb 2005
Location: Hudson Valley, NY
Posts: 231
QED is a jewel in the roughQED is a jewel in the roughQED is a jewel in the rough

Re: somebody please tell me what I'm doing wrong...


It might help to consider that std::string is an STL container (of chars). This means that you can use iterators to traverse the string. It is similar to what you've got already, except that each time you call string::at() bounds-checking is performed (some might say unnecessarily, since you know the length of the string).
CPP / C++ / C Code:
cout << "Enter a sentence to be translated to Morse Code: " << endl;

    while (cin >> sentence) {   //while newline is not encountered, extract next word
        std::string::const_iterator pos;
        for (pos = sentence.begin(); pos != sentence.end(); ++pos)
        {   // while current position is within the string
            nextChar = toupper(*pos);  // get current char and convert to upper case
            if (nextChar == '.') {   //If sentence ends in period, break out of loop
                break;
            }
            writeCode (codeArray, nextChar);    //call function writeCode to display Morse code for nextChar
        }
        cout << endl;
    }

Matthew
__________________
I was born not knowing and have only had a little time to change that here and there. -- Richard P. Feynman

Boris Podolsky: James! How's the rat business?
James Moreland: Well, actually it's mostly students I'm experimenting on now.
Kurt Gödel: My God, the mazes must be enormous.
  #6  
Old 02-May-2006, 09:53
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Re: somebody please tell me what I'm doing wrong...


Quote:
Originally Posted by WaltP
Instead of reading one word at a time, read the entire sentence with getline(). This will allow you to process whitespace (TABs and SPACEs) more accurately.

Also, why stop when you get a '.'? A period is a valid Morse Code character. IMO, you should process all valid characters and either ignore or flag all invalid characters.

Walt, that was the assignment! I guess the authors decided that having beginners deal with 26 contiguous characters was a heck of a lot easier than having to deal with some 52 or 53 non-contiguous ones, not counting the special characters.
  #7  
Old 02-May-2006, 17:02
WaltP's Avatar
WaltP WaltP is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Midwest US
Posts: 3,373
WaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to all

Re: somebody please tell me what I'm doing wrong...


Quote:
Originally Posted by earachefl
Walt, that was the assignment! I guess the authors decided that having beginners deal with 26 contiguous characters was a heck of a lot easier than having to deal with some 52 or 53 non-contiguous ones, not counting the special characters.
OK. It might help to review Guideline 4 for next project.
__________________

The 3 Laws of the Procrastination Society:
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
  #8  
Old 02-May-2006, 17:04
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Re: somebody please tell me what I'm doing wrong...


Quote:
Originally Posted by WaltP
OK. It might help to review http://www.gidforums.com/t-5566.html for next project.
Will do, sorry.
  #9  
Old 03-May-2006, 07:39
davis
 
Posts: n/a

Re: somebody please tell me what I'm doing wrong...


Morse.h
CPP / C++ / C Code:
#ifndef _Morse_h_
#define _Morse_h_

#include <iostream>
#include <string>
#include <map>
#include <cstring>

using namespace std;

typedef std::map<char, std::string>mapMorseCode;

class Morse
{
public:
    Morse();
    void print_char_to_code( const char c );
private:
    void init();
    mapMorseCode m_mapMorseCode;
};

#endif // ! _Morse_h_


Morse.cpp
CPP / C++ / C Code:
#ifndef _Morse_h_
#include <Morse.h>
#endif
Morse::Morse()
{
    init();
}

void
Morse::init()
{
    m_mapMorseCode.insert( pair<char,std::string>( 'A', ".-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'B', "-..." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'C', "-.-." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'D', "-.." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'E', "." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'F', "..-." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'G', "--." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'H', "...." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'I', ".." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'J', ".---" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'K', "-.-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'L', ".-.." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'M', "--" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'N', "-." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'O', "---" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'P', ".--." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'Q', "--.-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'R', ".-." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'S', "..." ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'T', "-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'U', "..-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'V', "...-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'W', ".--" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'X', "-..-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'Y', "-.--" ) );
    m_mapMorseCode.insert( pair<char,std::string>( 'Z', "--.." ) );
    m_mapMorseCode.insert( pair<char,std::string>( '.', ".-.-.-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( ',', "-..--" ) );
    m_mapMorseCode.insert( pair<char,std::string>( '?', "..--.." ) );
    m_mapMorseCode.insert( pair<char,std::string>( '0', "-----" ) );
    m_mapMorseCode.insert( pair<char,std::string>( '1', ".----" ) );
    m_mapMorseCode.insert( pair<char,std::string>( '2', "..---" ) );
    m_mapMorseCode.insert( pair<char,std::string>( '3', "...--" ) );
    m_mapMorseCode.insert( pair<char,std::string>( '4', "....-" ) );
    m_mapMorseCode.insert( pair<char,std::string>( '5', "....." ) );
    m_mapMorseCode.insert( pair<char,std::string>( '6', "-...." ) );
    m_mapMorseCode.insert( pair<char,std::string>( '7', "--..." ) );
    m_mapMorseCode.insert( pair<char,std::string>( '8', "---.." ) );
    m_mapMorseCode.insert( pair<char,std::string>( '9', "----." ) );
    m_mapMorseCode.insert( pair<char,std::string>( ' ', "_" ) );

}

void 
Morse::print_char_to_code( const char c )
{
    char l = c;
    if( isalpha( c ) )
    {
        l = toupper( c );
    }
    try
    {
        cout << m_mapMorseCode.find( l )->second;
    }
    catch( ... )
    {

    }
}

int main()
{
    Morse m;
    std::string str = "The quick brown fox jumps over the lazy dog.";
    for( int i = 0; i < (int)str.size(); i++ )
    {
        cout << str[i] << " = ";
        m.print_char_to_code( str[i] );
        cout << endl;
    }
    return 0;
}


Output:
Code:
T = - h = .... e = . = _ q = --.- u = ..- i = .. c = -.-. k = -.- = _ b = -... r = .-. o = --- w = .-- n = -. = _ f = ..-. o = --- x = -..- = _ j = .--- u = ..- m = -- p = .--. s = ... = _ o = --- v = ...- e = . r = .-. = _ t = - h = .... e = . = _ l = .-.. a = .- z = --.. y = -.-- = _ d = -.. o = --- g = --. . = .-.-.-

...I used an underscore for spaces, since in Morse code, a space is simply a pause in transmission of characters. This is a rather quick and dirty hack, but should give you an idea of at least one alternative that flexes C++ standard library features a bit more along the lines of what Matthew noted previously.

By changing the input string:
Code:
A = .- B = -... C = -.-. s = ... = _ a = .- r = .-. e = . = _ a = .- s = ... = _ s = ... i = .. m = -- p = .--. l = .-.. e = . = _ a = .- s = ... = _ 1 = .---- 2 = ..--- 3 = ...-- . = .-.-.-

...obviously a more robust class implementation would handle unknown characters better and offer much better interfaces for conversion to and from Morse code, etc.


:davis:
 
 

Recent GIDBlogVista ?Widgets? on Windows XP by LocalTech

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Here it is again! 35% - 40% off For Life! my-e-space Web Hosting Advertisements & Offers 0 20-Apr-2006 14:48
User defined headers davis Miscellaneous Programming Forum 6 16-Feb-2006 18:40
convert for to while loop zodisign C Programming Language 1 14-Aug-2005 06:38
Problem with int mixed with char,... leitz C++ Forum 17 07-Dec-2004 20:56
Morse Code for C sibyl03 C Programming Language 1 13-Oct-2004 00:00

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 10:34.


vBulletin, Copyright © 2000 - 2010, Jelsoft Enterprises Ltd.