Decoding a previously encoded message

  • Thread starter Thread starter Demon117
  • Start date Start date
AI Thread Summary
The discussion revolves around creating an encoder/decoder program in C++. The main issue is that the user is struggling to implement the decoding functionality, specifically reading from a file named "encode.txt" to decode text back to its original form. Several coding errors and suggestions for improvement are highlighted. Key points include the need to correct a logical error where '=' is used instead of '==' in a conditional statement, and the importance of reading the encoded text from the file for decoding. There are also recommendations for improving code readability, such as proper indentation and naming conventions for classes and variables. Participants emphasize the necessity of compiling the code with warnings enabled to catch potential issues, and there is a discussion about whether to keep certain member variables in the class or to pass data directly to methods. Overall, the conversation is focused on debugging and refining the encoder/decoder program.
Demon117
Messages
162
Reaction score
1
I am making a encoder/decoder program. I have made most of it but I am stuck on the last bit. I would like when i click decode the text it will read encode.txt from the same directory, read it and change it back to normal (undecode) and then show it on the screen.

Please can someone help?


Here is my code:

Code:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <fstream>
using namespace std;

const string cryptSymbols[]={"1","2","3","4","5","6","7","8","9","10","11","12",
"13","14","15","16","17","18","19","20","21","22","23","24","25","26","A","B","C",
"D","E","F","G","H","I","J","K","L","-"};

const string normalSymbols[]={"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","1","2","3","4","5","6","7","8",
"9","0",".",","," "};

class crypt{
      string inCode;
public:
       crypt(string input);
       string decode();
       string encode();
};

crypt::crypt(string input){
                    inCode = input;
}

string crypt::decode(){
       
       string output="";
       string cryptLetter="";
       char character;
       char right;
       int pointer=0;
       
       while(pointer<inCode.length())
       {character=inCode[pointer];
       
       if(pointer<inCode.length()-1)
           right=inCode[pointer+1];
       if(!(character=' '))
           cryptLetter+=character;
       
       else{
            for(int ctr=0;ctr<39;ctr++){
                    if(cryptLetter==cryptSymbols[ctr])
                        output+=normalSymbols[ctr];
            }
            cryptLetter="";
       }
       if((character==' ')&&(right==' ')){
                        output+=" ";
       }
       pointer++;
       }
return output;
}  

string crypt::encode(){
       string output="";
       string character="";
       for(int ctr=0;ctr<inCode.length();ctr++){
               character=inCode[ctr];
               if(character==" ")
                    output+=" ";
               for(int ctr2=0;ctr2<38;ctr2++){
                       if(character==normalSymbols[ctr2]){
                             output+=cryptSymbols[ctr2];
                             output+=" ";
                       }
               }
       }
       
       return output;
       
}

int main()
{
    string input;
    string output;
    char choice;
    char yn;
    char number;
    yn='y';
    while((yn!='n')&&(yn!='N')){
        cout<<"Welcome to the Magic Decoder Ring!\n";
        cout<<"Please choose an option:\n";
        cout<<"1 Encode Text\n";
        cout<<"2 Decode Text\n";
        
        cin>>choice;
        cin.clear();
        cin.ignore();
        
        if(choice=='1'){
           ofstream file; //Declares file
           file.open("encode.txt"); //Opens file
           cout<<"Type the text you want encoded\n";
           getline(cin,input);
           crypt cryptCode(input+" ");
           output=cryptCode.decode();
           cout<<output<<'\n';
           file<<cryptCode.encode()<<endl;
           file.close();//Closes the file
           cout<<"(Your code has been saved at encode.txt)\n";
                 cin.clear();
        cin.ignore();
        }
        else if(choice=='2'){
             ifstream infile("encode.txt");
             crypt cryptCode(input+" ");
             output=cryptCode.decode();
                   getline(cin,input);
             cout<<output<<'\n';
        cout<<"-Finished...";
        cin.clear();
        cin.ignore();
        }
        
    system("pause");
    return EXIT_SUCCESS;
}}
 
Technology news on Phys.org
matumich26 said:
I am making a encoder/decoder program. I have made most of it but I am stuck on the last bit. I would like when i click decode the text it will read encode.txt from the same directory, read it and change it back to normal (undecode) and then show it on the screen.

Please can someone help?
Does the code you show compile without errors? What exactly do you need help with?

I see at least one line where you are using = when you should be using ==
if(!(character=' ')) (in decode())

matumich26 said:
Here is my code:

Code:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <fstream>
using namespace std;

const string cryptSymbols[]={"1","2","3","4","5","6","7","8","9","10","11","12",
"13","14","15","16","17","18","19","20","21","22","23","24","25","26","A","B","C",
"D","E","F","G","H","I","J","K","L","-"};

const string normalSymbols[]={"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","1","2","3","4","5","6","7","8",
"9","0",".",","," "};

class crypt{
      string inCode;
public:
       crypt(string input);
       string decode();
       string encode();
};

crypt::crypt(string input){
                    inCode = input;
}

string crypt::decode(){
       
       string output="";
       string cryptLetter="";
       char character;
       char right;
       int pointer=0;
       
       while(pointer<inCode.length())
       {character=inCode[pointer];
       
       if(pointer<inCode.length()-1)
           right=inCode[pointer+1];
       if(!(character=' '))
           cryptLetter+=character;
       
       else{
            for(int ctr=0;ctr<39;ctr++){
                    if(cryptLetter==cryptSymbols[ctr])
                        output+=normalSymbols[ctr];
            }
            cryptLetter="";
       }
       if((character==' ')&&(right==' ')){
                        output+=" ";
       }
       pointer++;
       }
return output;
}  

string crypt::encode(){
       string output="";
       string character="";
       for(int ctr=0;ctr<inCode.length();ctr++){
               character=inCode[ctr];
               if(character==" ")
                    output+=" ";
               for(int ctr2=0;ctr2<38;ctr2++){
                       if(character==normalSymbols[ctr2]){
                             output+=cryptSymbols[ctr2];
                             output+=" ";
                       }
               }
       }
       
       return output;
       
}

int main()
{
    string input;
    string output;
    char choice;
    char yn;
    char number;
    yn='y';
    while((yn!='n')&&(yn!='N')){
        cout<<"Welcome to the Magic Decoder Ring!\n";
        cout<<"Please choose an option:\n";
        cout<<"1 Encode Text\n";
        cout<<"2 Decode Text\n";
        
        cin>>choice;
        cin.clear();
        cin.ignore();
        
        if(choice=='1'){
           ofstream file; //Declares file
           file.open("encode.txt"); //Opens file
           cout<<"Type the text you want encoded\n";
           getline(cin,input);
           crypt cryptCode(input+" ");
           output=cryptCode.decode();
           cout<<output<<'\n';
           file<<cryptCode.encode()<<endl;
           file.close();//Closes the file
           cout<<"(Your code has been saved at encode.txt)\n";
                 cin.clear();
        cin.ignore();
        }
        else if(choice=='2'){
             ifstream infile("encode.txt");
             crypt cryptCode(input+" ");
             output=cryptCode.decode();
                   getline(cin,input);
             cout<<output<<'\n';
        cout<<"-Finished...";
        cin.clear();
        cin.ignore();
        }
        
    system("pause");
    return EXIT_SUCCESS;
}}
 
There are so many problems in there, it's a ways yet from working, alas.

Firstly, your indentation is truly terrible, I'm sorry to say. I suggest setting up an IDE to indent things automatically for you, at this point.

Doesn't compile for me because I believe there's a function called crypt in the std namespace. Renaming the class to Crypt (with upper case at the start) gets rid of that problem, but it should be named something more specific, or be in it's own namespace (won't get into that now). I prefer the convention where class names start with an upper case letter, personally.

EDIT: Not sure where the crypt function is coming from, to be honest, and you might not have it on your system. However, you should #include <cstdlib> and not #include <stdlib.h>. Also still a bad class name. Capitalizing the first letter of a class name prevents such problems, for the most part.

If you're appending repeatedly to a string, you might consider stringbuffer for it. That's what it's for.

In decode, you call an index "pointer". It's not a pointer. Might want to call it "index" or something like that.

The 'inCode' member variable should be private. Though one might question if it should be there at all rather than just passing the data to the encode/decode methods directly, is something to consider.

You're also not reading in the ciphertext from the input file, and so there's nothing for it to decode.

Mark already pointed out the line with '=' when you meant '=='.

Not sure what compiler you're using, but you should make sure warnings are on. One thing it should point out is that you're comparing an int and the return value of string::length(), when that method doesn't return an int. It returns size_t.

Why is there 'cin.ignore()' in those two places in main? Doesn't seem necessary.

That's what I see after a quick pass through. Not too sure about the logic in decode, either. But fix that stuff and see what happens, and we can give you more help if necessary.
 
Last edited:
Firstly, your indentation is truly terrible, I'm sorry to say. I suggest setting up an IDE to indent things automatically for you, at this point.

Frankly I understand the indentation so I'll just ignore that comment.

Doesn't compile for me because I believe there's a function called crypt in the std namespace. Renaming the class to Crypt (with upper case at the start) gets rid of that problem, but it should be named something more specific, or be in it's own namespace (won't get into that now). I prefer the convention where class names start with an upper case letter, personally.

It compiles just fine for me, but it does encode rather funny like.
This is just confusing but here is what I gather:

Code:
class Crypt{
      string inCode;
public:
       Crypt(string input);
       string decode();
       string encode();
};

If you're appending repeatedly to a string, you might consider stringbuffer for it. That's what it's for.

I don't know what a sringbuffer is so I would prefer just leaving it.

In decode, you call an index "pointer". It's not a pointer. Might want to call it "index" or something like that.

I will fix that.

The 'inCode' member variable should be private. Though one might question if it should be there at all rather than just passing the data to the encode/decode methods directly, is something to consider.

How do I fix that? I would like to simplify this a bit..

You're also not reading in the ciphertext from the input file, and so there's nothing for it to decode.

Hmm, have to play with that for a bit. I am assuming that it would be kinda similar to what I have in main for encode().

Not sure what compiler you're using, but you should make sure warnings are on. One thing it should point out is that you're comparing an int and the return value of string::length(), when that method doesn't return an int. It returns size_t.

I'm assuming that's why I get silly encoded messages. For example, when I put in
"My name is charlie." The encoded file becomes "13 k " which does not seem right at all. . . .
 
matumich26 said:
Frankly I understand the indentation so I'll just ignore that comment.
Don't you think it's an important courtesy to us to make it readable? It's, in fact, quite important to indent and format things well, for a number of reasons.

You're even indenting with a different number of spaces in different places.

I mean when is this ever acceptable:

Code:
       while(pointer<inCode.length())
       {character=inCode[pointer];

or later in the method:

Code:
       if((character==' ')&&(right==' ')){
                        output+=" ";
       }
       pointer++;
       }

There's a lot of room for formatting it how you like it. You don't have to indent it exactly the way I do, but this is how I would indent and format it (ignoring actual problems in the code except the =/== thing):

Code:
string crypt::decode() {
    string output = "";
    string cryptLetter = "";
    char character;
    char right;
    int pointer = 0;
       
    while (pointer < inCode.length()) {
        character = inCode[pointer];

        if (pointer < (inCode.length()-1))
            right = inCode[pointer+1];

        if (!(character == ' ')) {
            cryptLetter += character;
        } else {
            for (int ctr=0; ctr < 39; ctr++) {
                if (cryptLetter == cryptSymbols[ctr])
                    output += normalSymbols[ctr];
            }
            cryptLetter = "";
        }
        if ((character == ' ') && (right == ' ')) {
            output += " ";
        }
        pointer++;
    }
    return output;
}

I tend to prefer curly braces on their own lines, but that's a matter of choice and putting them at the end of the line is absolutely fine, but there should be a space before that opening curly brace. There's spaces added in many places that really improve clarity and readability.

There isn't a competent programmer on the planet that wouldn't rather work on the code as I indented it, nor a single one that would think your indentation is acceptable. If I was a teacher marking that, you'd lose points.

You're making extra work for us when we help you because we need to either put in extra effort to figure out the code structure, or re-indent it so it's readable. You can see where we'd be less inclined to want to help you in those circumstances. Help us help you.
 
Grep said:
Don't you think it's an important courtesy to us to make it readable? It's, in fact, quite important to indent and format things well, for a number of reasons.

You're even indenting with a different number of spaces in different places.

I mean when is this ever acceptable:

Code:
       while(pointer<inCode.length())
       {character=inCode[pointer];

or later in the method:

Code:
       if((character==' ')&&(right==' ')){
                        output+=" ";
       }
       pointer++;
       }

There's a lot of room for formatting it how you like it. You don't have to indent it exactly the way I do, but this is how I would indent and format it (ignoring actual problems in the code except the =/== thing):

Code:
string crypt::decode() {
    string output = "";
    string cryptLetter = "";
    char character;
    char right;
    int pointer = 0;
       
    while (pointer < inCode.length()) {
        character = inCode[pointer];

        if (pointer < (inCode.length()-1))
            right = inCode[pointer+1];

        if (!(character == ' ')) {
            cryptLetter += character;
        } else {
            for (int ctr=0; ctr < 39; ctr++) {
                if (cryptLetter == cryptSymbols[ctr])
                    output += normalSymbols[ctr];
            }
            cryptLetter = "";
        }
        if ((character == ' ') && (right == ' ')) {
            output += " ";
        }
        pointer++;
    }
    return output;
}

I tend to prefer curly braces on their own lines, but that's a matter of choice and putting them at the end of the line is absolutely fine, but there should be a space before that opening curly brace. There's spaces added in many places that really improve clarity and readability.

There isn't a competent programmer on the planet that wouldn't rather work on the code as I indented it, nor a single one that would think your indentation is acceptable. If I was a teacher marking that, you'd lose points.

You're making extra work for us when we help you because we need to either put in extra effort to figure out the code structure, or re-indent it so it's readable. You can see where we'd be less inclined to want to help you in those circumstances. Help us help you.

Ok, point taken. Frankly I didn't think it was that big of a deal; unfortunately my professor is rather incompetent so I have to come to these forums for help. I appreciate your comments on the matter.
 
matumich26 said:
Ok, point taken. Frankly I didn't think it was that big of a deal; unfortunately my professor is rather incompetent so I have to come to these forums for help. I appreciate your comments on the matter.

Poor you... Poor teachers are a pretty big barrier to learning well. Well, we're always here for you. At least there's that! :biggrin:

You might be interested in this site that provides pretty good online documentation on the C++ standard libraries:

http://www.cplusplus.com/reference/

About removing that member variable. You could add the string to be processed as a parameter to the function. Something like:

Code:
class crypt {
    public:
        crypt();
        string decode(string input);
        string encode(string input);
};

On the other hand, that makes using a class here kind of pointless anyways since it doesn't need to keep any state information. There's no need to even instantiate a class for this job. Could just define two functions in a namespace, but I won't get into that right now. Your teacher probably expects a class, and likely hasn't covered namespaces, so I wouldn't worry about that aspect yet.

Oh yeah, I'm wrong about 'stringbuffer' (it happens). Don't know why I was thinking that. Probably just doing too much Java. :smile:

Using 'string' is indeed the right thing to do here. Carry on. :biggrin:
 

Similar threads

Back
Top