Hey, I am trying to make a C++ scrit that decodes and encodes tenis polar (search it on Google if you don't know what it is). After some testing, I found out my application stops after the strcpy. Any help? The code is below. Thanks!

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

using namespace std;

void encode(string str);

int main() {
    string scode;
    cout << "Code: ";
    cin >> scode;
    encode(scode);

}

void encode(string str) {
    char * ccode, * ncode = new char [str.size()+1];
    int str_size = str.size()+1;
    strcpy (ccode, str.c_str());
    for (int i=0; i!=str_size; i++) {
        if (ccode[i]=='t') {
            ncode[i]='p';
        }
        cout << ncode;
    }
}

Recommended Answers

All 18 Replies

Break line 18 into two lines.

    char * ccode, = new char [str.size()+1];
    char * ncode = new char [str.size()+1];

You need to allocate memory for BOTH strings. I assume that you are adding 1 to make room for the NULL terminator, correct? Beyond that, ccode has the NULL terminator. ncode, however, does not. ncode is going to be largely uninitialized. You are filling in ncode's values only for characters where ccode[i] is 't'. What about all of the other characters? ncode will be undefined for those characters, correct?

I googled "tenis polar" and got some non-English hits, then google seemed to turn "tenis" into "tennis", so I still don't know what "tenis polar" is, but it seems from the code that those are the problems.

Also, don't forget to free the memory you allocated with "new"!

Vern, from what I can gather from the little portuguese I know, it's kinda like a substitution cypher where the letters T E N I S are substituted for P O L A R and vice versa. Incidentally, tenis is portuguese for shoes!

So the sentence "A polar bear wearing tennis shoes" would end up being encoded as something like "I tenis bois woisalg pollar rheor"

void encode(string str) {
    char * ccode = new char [str.size()+1], * ncode = new char [str.size()+1];
    int str_size = str.size()+1;
    strcpy (ccode, str.c_str());
    for (int i=0; i!=str_size; i++) {
        if (ccode[i]=='t') {
            ncode[i]='p';
        }
        cout << ncode;
    }
    delete ccode, ncode;
}

Jason is right, that is tenis polar. Plus, I finished the encoder! Now I have to make a DOS window GUI and the decoder. I tryed it and it worked. Two questions... How can I make something go into the user's clipboard and how can I make it so when someone moves an arrow key or presses a key (without cin), it will do an action? Thanks

"DOS Window GUI"? Seems like a contradiction in terms. I assume "DOS" means "console" since no one uses DOS anymore. I assume you mean a GUI but not drawn in pixels with colors, but rather just displaying the regular old ASCII characters. cin is going to wait for that pesky newline character, so you can't use that. As far as arrow keys go, if you want to be able to go up, down, right, left, you might want to check out the ncurses library. If you simply want to be able to not have to wait for a newline, I imagine the easiest thing to do is use binary reads of single characters rather than cin.

As for the clipboard, "clipboard" has all sorts of meanings. If you want to be able to place characters into the "clipboard" so that it can be pasted into, say, "MS Word" the next time the user does a paste where the user does not have to do a manual copy using the operating system, that's not a trivial task. You're probably going to have to give more details.

Yes, I do mean copy/paste. And because the console GUI is too complicated, I'll stick to something like this:

Tenis Polar Coder

1. Encode
2. Decode

Selection:

So, how do i do the copy/paste thing?

Another bug :(
The replacing stops when there is a space. For example, the input of "Tenis Polar" would get the output of "Polar" and not "Polar tenis". Can anyone help? By the way, I still didn't add replacing capital letters so 'P' would not come out as 'T' but as 'P'. Here is the coder and please don't copy:

void encode() {
    string str;
    cout << "Code to encode: ";
    cin >> str;
    char * ccode = new char [str.size()+1];
    char * ncode = new char [str.size()];
    int str_size = str.size();
    strcpy (ccode, str.c_str());
    for (int i=0; i!=str_size; i++) {
        if (ccode[i]=='t') {
            ncode[i]='p';
        } else if (ccode[i]=='e') {
            ncode[i]='o';
        } else if (ccode[i]=='n') {
            ncode[i]='l';
        } else if (ccode[i]=='i') {
            ncode[i]='a';
        } else if (ccode[i]=='s') {
            ncode[i]='r';
        } else if (ccode[i]=='p') {
            ncode[i]='t';
        } else if (ccode[i]=='o') {
            ncode[i]='e';
        } else if (ccode[i]=='l') {
            ncode[i]='n';
        } else if (ccode[i]=='a') {
            ncode[i]='i';
        } else if (ccode[i]=='r') {
            ncode[i]='s';
        } else if (ccode[i]==' ') {
            ncode[i]=' ';
        } else {
            ncode[i]=ccode[i];
        }
    }
}

Nevermind. Now I am using 'getline(cin,str)' instead of 'cin >> str'. The problem is that the program just crashes when it's time to enter the input...

Forgot ALL OF THE ABOVE. I fixed everything. Now I just need two things. An alternitive to 'system("cls")' because everyone says it's bad with using a lot of \n. And a way to copy something to the copy/paste clipboard. In the meanwhile, I am adding file saving support. Thanks!

There's no alternative to system("cls") in C++, intentionally so. System calls are generally frowned on for a few reasons (one, they may be dependent on the operating system, so what works with Windows might not work with Mac or Linux, two they're not particularly efficient (generally not the biggest deal in the world), and three, potentially somelone can write some malware, name it "cls", stick it in the path somewhere before the real "cls", and your system("cls") will run it). If you understand the risks and still want to do that, go for it.

because everyone says it's bad with using a lot of \n.

Who is everyone? If you really want to "clear the screen" using C++, figure out how many lines the screen is and output that many newlines. If the console GUI is too complicated, you either have to find a library that does it for you, use system("cls"), or write a bunch of newlines. I recommend the newlines.

As far as copying and pasting to thje clipboard, again, it's not trivial, it's operating system specific, and not part of standard C++. You'll need to find a library, and that's going to be specific to the operating system. If using Windows, give this a read.

http://msdn.microsoft.com/en-us/library/ms648709(v=vs.85)

For Linux and Mac, you'll need to find something else.

Thanks for your help. I meant to say without but I said with. It doesn't matter so I might use the \n. The program is only for me and two other people and we all have windows, it is not meant for public release too. So the only big deal is the malware... I plan to use only the official libraries so I'll wont use copy/paste, I made a file saving system as an alternitive. Here is the code (still with 'system("cls")') if anyone finds it useful just don't post it and take credit :)

//Tenis Polar Coder
//by funkey100

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <conio.h>
#include <cstdlib>
#include <fstream>
#include <direct.h>

using namespace std;

void code(int ed); //declaring functions
void save(char * str);

int main() {
    string scode;
    int sel;
    cout << "Tenis Polar Coder\n\n"; //main menu
    cout << "1. Encode\n";
    cout << "2. Decode\n";
    cout << "3. Exit\n";
    cout << "\nSelection: ";
    cin >> sel;
    switch (sel) { //what each selection does
        case 1:
            system("cls");
            code(1);
            break;
        case 2:
            system("cls");
            code(2);
            break;
        case 3:
            return 0;
            break;
        default:
            cout << "Invalid selection. Please try again.";
            getch();
            system("cls");
            main();
    }
}

void code(int ed) {
    string str;
    if (ed == 1) { //asking for input
        cout << "Text to encode: ";
        cin.ignore();
    } else if (ed == 2) {
        cout << "Text to decode: ";
        cin.ignore();
    }
    getline(cin,str);
    char * ccode = new char [str.size()+1]; //creating
    char * ncode = new char [str.size()];   //and copying
    int str_size = str.size()+1;            //things
    strcpy (ccode, str.c_str());
    for (int i=0; i!=str_size; i++) {
        if (ccode[i]=='t') {        //replacing
            ncode[i]='p';           //lower case
        } else if (ccode[i]=='e') { //tenis and
            ncode[i]='o';           //polar letters
        } else if (ccode[i]=='n') {
            ncode[i]='l';
        } else if (ccode[i]=='i') {
            ncode[i]='a';
        } else if (ccode[i]=='s') {
            ncode[i]='r';
        } else if (ccode[i]=='p') {
            ncode[i]='t';
        } else if (ccode[i]=='o') {
            ncode[i]='e';
        } else if (ccode[i]=='l') {
            ncode[i]='n';
        } else if (ccode[i]=='a') {
            ncode[i]='i';
        } else if (ccode[i]=='r') {
            ncode[i]='s';
        } else if (ccode[i]=='T') { //replacing
            ncode[i]='P';           //upper case
        } else if (ccode[i]=='E') { //tenis and
            ncode[i]='O';           //polar letters
        } else if (ccode[i]=='N') {
            ncode[i]='L';
        } else if (ccode[i]=='I') {
            ncode[i]='A';
        } else if (ccode[i]=='S') {
            ncode[i]='R';
        } else if (ccode[i]=='P') {
            ncode[i]='T';
        } else if (ccode[i]=='O') {
            ncode[i]='E';
        } else if (ccode[i]=='L') {
            ncode[i]='N';
        } else if (ccode[i]=='A') {
            ncode[i]='I';
        } else if (ccode[i]=='R') {
            ncode[i]='S';
        } else {
            ncode[i]=ccode[i];
        }
    }
    if (ed == 1) {
        cout << "Encoded text: "; //displaying
    } else if (ed == 2) {         //output
        cout << "Decoded text: ";
    }
    int sel;
    cout << ncode;
    cout << "\n\n1. Back"; //what
    cout << "\n2. Exit";   //to do
    cout << "\n3. Save";   //next
    cout << "\n\nSelection: ";
    cin >> sel;
    switch (sel) {
        case 1:
            system("cls");
            main();
            break;
        case 2:
            return;
            break;
        case 3:
            system("cls");
            save(ncode);
            break;
        default:
            cout << "None of the above selected... Quiting...";
            getch();
            return;
            break;
    }
}

void save(char * str) {
    string fname;
    string pname = "./saves/";
    mkdir("./saves/");
    cout << "Save as txt file\n\n";
    cout << "Filename: "; //asks for file name
    cin.ignore();
    getline(cin,fname);
    pname.append(fname);
    pname.append(".txt");
    ifstream check(pname.c_str());
    if (!check.is_open()) { //checks if file exists or not
        check.close();
        cout << "File doesn't exist. Creating new file.";
        ofstream sav(pname.c_str()); //creates file if doesn't exist
        sav << str;
        sav.close();
        cout << "\nDone. File Saved at " << pname;
        getch();
        system("cls");
        main();
    } else {
        char yn;
        check.close();
        cout << "File exists. Overwrite file? Selection (y/n):";
        cin >> yn; //asks if you want to overwrite existing file
        if (yn == 'y') {
            ofstream sav(pname.c_str());
            sav << str; //overwrites file with new data
            sav.close();
            cout << "Done. File Saved at " << pname;
            getch();
            system("cls");
            main();
        } else if (yn == 'n') {
            cout << "OK. Will return to save menu.";
            getch();
            system("cls");
            save(str); //back to save menu
        }
    }
} //by funkey100

What happens if you don't type in an option on the menu and then try to exit? If you don't type a correct command in it calls main(), which is an integer. The exit command returns 0 so the function never returns anything. I suggest adding a return 0; after the main().

Calling main() explicitly is an extremely poor idea; in fact, it is actually forbidden in the C++ standard, and the compiler ought to be giving you an error message on that (not that all compilers do). The main() function is special in a number of ways - it performs a number of initializations steps which are hidden from the programmer, for example, gathering the command-line arguments - which should not be repeated by the program after the actual code begins.

As for clearing the screen, is it really necessary? It is, as said earlier, a system-dependent operation. Now, since you're already looking at a Windows-specific program (interacting with the clipboard, etc.), it wouldn't be particularly harmful to use a clear screen, but at the same time, it is not, strictly speaking, a requirement of the program, and using it is more chrome than functionality.

In any case, the system("cls") call isn't really the best way to go about this; calling out to the shell is a rather slow process, and if you're going to be system-dependent, you may as well use the system calls themselves - though putting them in a wrapper may make sense, to preserve some amount of portability. This MS knowledge base article gives an example of how to do it programmatically; the function thy give is fairly involved, as there is no existing API function for this purpose, but it should be more or less drop-in code (though you'll need to #include "windows.h" to make it work).

An alternative might be to use the PDCurses library, but given that you're already talking about moving to a GUI program, it probably doesn't make sense to introduce a new 3rd party library that you'll be moving away from later.

Getting to the meat of your code, I would recommend using a lookup table rather than the series of if statements you use now. You can implement the table fairly simply, and the overall code size will drop significantly, and it eliminates a number of points where errors could occur. A simple one-to-one table like this should work:

// use a null character for the delimiter of the lookup table
char lookup[][] = {{'P', 'T'}, {'O', 'E'}, {'L', 'N'}, {'A', 'I'}, {'R', 'S'}, {'\0', '\0'}};
char original, translated;

// .. later in the code ...

    translated = original;  // assume that it does not get translated

    // check for translations
    for (int i = 0; lookup[i][0] != '\0'; i++)
    {
        if (toupper(original) == lookup[i][0])
        {
            translated = lookup[i][1];
            if (islower(original))
            {
                translated = tolower(translated);
            }
            break;
        }
        if (toupper(original) == lookup[i][1])
        {
            translated = lookup[i][0];
            if (islower(original))
            {
                translated = tolower(translated);
            }                
            break;
        }
    }

This should make for a simpler and more elegant approach overall.

Well, I'm not very good with C++ and I just started. So can you explain that code to me? I won't learn anything and get better if I use other people's code and don't understand it, so I understand everything before I use it. Thanks.

I researched about the isupper, islower and toupper and I think I understand... Just that that for loop would have to be in another loop because it only translates one character... And original and translated will have to have something like [var] at their end.

I fixed everything. I removed the menu from main() and added menu(). I also used Schol's translater with a few changes because it wasn't working for me. Here it is if you want it but to copy it:

#include <string>
#include <cstdio>
#include <conio.h>
#include <cstdlib>
#include <fstream>
#include <direct.h>
#include <locale>


using namespace std;

void menu();
void code(int ed);
void save(char * str);

int main() {
    menu();
}

void menu() {
    string scode;
    int sel;
    cout << "Tenis Polar Coder\n\n";
    cout << "1. Encode\n";
    cout << "2. Decode\n";
    cout << "3. Exit\n";
    cout << "\nSelection: ";
    cin >> sel;
    switch (sel) {
        case 1:
            system("cls");
            code(1);
            break;
        case 2:
            system("cls");
            code(2);
            break;
        case 3:
            return;
            break;
        default:
            cout << "Invalid selection. Please try again.";
            getch();
            system("cls");
            menu();
    }
}

void code(int ed) {
    string str;
    if (ed == 1) {
        cout << "Text to encode: ";
        cin.ignore();
    } else if (ed == 2) {
        cout << "Text to decode: ";
        cin.ignore();
    }
    getline(cin,str);
    char lookup[6][2] = {{'T', 'P'}, {'E', 'O'}, {'N', 'L'}, {'I', 'A'}, {'S', 'R'}, {'\0', '\0'}};
    char ccode[str.size()+1];
    char ncode[str.size()+1];
    int str_size = str.size()+1;
    strcpy (ccode, str.c_str());
    for (int x = 0; str_size != x; x++) {
        for (int i = 0; lookup[i][0] != '\0'; i++) {
            if (toupper(ccode[x]) == lookup[i][0]) {
                ncode[x] = lookup[i][1];
                if (islower(ccode[x])) {
                    ncode[x] = tolower(ncode[x]);
                }
                break;
            } else if (toupper(ccode[x]) == lookup[i][1]) {
                ncode[x] = lookup[i][0];
                if (islower(ccode[x])) {
                    ncode[x] = tolower(ncode[x]);
                }
                break;
            } else {
                ncode[x] = ccode[x];
            }
        }
    }
    if (ed == 1) {
        cout << "\nEncoded text: ";
    } else if (ed == 2) {
        cout << "\nDecoded text: ";
    }
    int sel;
    cout << ncode;
    cout << "\n\n1. Back";
    cout << "\n2. Exit";
    cout << "\n3. Save";
    cout << "\n\nSelection: ";
    cin >> sel;
    switch (sel) {
        case 1:
            system("cls");
            menu();
            break;
        case 2:
            return;
            break;
        case 3:
            system("cls");
            save(ncode);
            break;
        default:
            cout << "None of the above selected... Quiting...";
            getch();
            return;
            break;
    }
}

void save(char * str) {
    string fname;
    string pname = "./saves/";
    mkdir("./saves/");
    cout << "Save as txt file\n\n";
    cout << "Filename: ";
    cin.ignore();
    getline(cin,fname);
    pname.append(fname);
    pname.append(".txt");
    ifstream check(pname.c_str());
    if (!check.is_open()) {
        check.close();
        cout << "File doesn't exist. Creating new file.";
        ofstream sav(pname.c_str());
        sav << str;
        sav.close();
        cout << "\nDone. File Saved at " << pname;
        getch();
        system("cls");
        main();
    } else {
        char yn;
        check.close();
        cout << "File exists. Overwrite file? Selection (y/n):";
        cin >> yn;
        if (yn == 'y') {
            ofstream sav(pname.c_str());
            sav << str;
            sav.close();
            cout << "Done. File Saved at " << pname;
            getch();
            system("cls");
            menu();
        } else if (yn == 'n') {
            cout << "OK. Will return to save menu.";
            getch();
            system("cls");
            save(str);
        }
    }
}

I made a few modifications to the program for you; while most of them are minor (and somewhat pedantic) corrections, the main thing I did was to separate out the encoding function from the function code(). The reason I did this was separate view from functionality: by having the actual encoding operation distinct from the user interface, it makes it easier to change either of them without changing the other. This would make a big difference if you were to decide to change to a Windows-style interface instead of a console interface.

I also made all of the strings explicitly C++ string objects rather than C-strings. This means that you aren't relying on the older C libraries as much, and specifically, that you can drop the #include <cstdio> header. I furthermore moved the references to system("cls") into a separate function, clearscreen(), so as to mitigate the system-dependence somewhat (that is to say, if you go to a different type of system, you now only need to change it in one place, rather than all over the code).

If any part of this is unclear, let me know and I'll do my best to explain it.

For the future, I recommend turning on all warnings and error messages, so that you get as much information back from the compiler as possible. If you are using Code::Blocks for your IDE (a good choice IMAO), you can go into the Compiler and Debugger under the Settings menu, and look in the Compiler Settings tab for a sub-tab called Compiler Flags (it should be already visible by default). In the Flags tab will be a list of options; the main one you want to set is "Enable all compiler warnings (-Wall)", which will automatically set it to one of the highest warning levels.

#include <iostream>
#include <string>
#include <conio.h>
#include <cstdlib>
#include <fstream>
#include <direct.h>

using namespace std;

void menu();
void clearscreen();
void code(int ed);
void save(string str);
string translate(string str);

int main()
{
    menu();
    return 0;
}

void menu()
{
    string scode;
    int sel;
    cout << "Tenis Polar Coder\n\n";
    cout << "1. Encode\n";
    cout << "2. Decode\n";
    cout << "3. Exit\n";
    cout << "\nSelection: ";
    cin >> sel;
    switch (sel)
    {
    case 1:
        clearscreen();
        code(1);
        break;
    case 2:
        clearscreen();
        code(2);
        break;
    case 3:
        return;
        break;
    default:
        cout << "Invalid selection. Please try again.";
        getch();
        clearscreen();
        menu();
    }
}

void code(int ed)
{
    string str;
    if (ed == 1)
    {
        cout << "Text to encode: ";
        cin.ignore();
    }
    else if (ed == 2)
    {
        cout << "Text to decode: ";
        cin.ignore();
    }
    getline(cin,str);
    string ncode = translate(str);

    if (ed == 1)
    {
        cout << "\nEncoded text: ";
    }
    else if (ed == 2)
    {
        cout << "\nDecoded text: ";
    }
    int sel;
    cout << ncode;
    cout << "\n\n1. Back";
    cout << "\n2. Exit";
    cout << "\n3. Save";
    cout << "\n\nSelection: ";
    cin >> sel;
    switch (sel)
    {
    case 1:
        clearscreen();
        menu();
        break;
    case 2:
        return;
        break;
    case 3:
        clearscreen();
        save(ncode);
        break;
    default:
        cout << "None of the above selected... Quiting...";
        getch();
        return;
        break;
    }
}


string translate(string plaintext)
{
    char lookup[6][2] = {{'T', 'P'}, {'E', 'O'}, {'N', 'L'}, {'I', 'A'}, {'S', 'R'}, {'\0', '\0'}};
    string ncode;

    for (unsigned x = 0; x < plaintext.size(); x++)
    {
        ncode.append(1, plaintext[x]);
        for (int i = 0; lookup[i][0] != '\0'; i++)
        {
            if (toupper(plaintext[x]) == lookup[i][0])
            {
                ncode[x] = lookup[i][1];
                if (islower(plaintext[x]))
                {
                    ncode[x] = tolower(ncode[x]);
                }
                break;
            }
            else if (toupper(plaintext[x]) == lookup[i][1])
            {
                ncode[x] = lookup[i][0];
                if (islower(plaintext[x]))
                {
                    ncode[x] = tolower(ncode[x]);
                }
                break;
            }
        }
    }

    return ncode;
}


void save(string str)
{
    string fname;
    string pname = "./saves/";
    mkdir("./saves/");
    cout << "Save as txt file\n\n";
    cout << "Filename: ";
    cin.ignore();
    getline(cin,fname);
    pname.append(fname);
    pname.append(".txt");
    ifstream check(pname.c_str());
    if (!check.is_open())
    {
        check.close();
        cout << "File doesn't exist. Creating new file.";
        ofstream sav(pname.c_str());
        sav << str;
        sav.close();
        cout << "\nDone. File Saved at " << pname;
        getch();
        clearscreen();
        menu();
    }
    else
    {
        char yn;
        check.close();
        cout << "File exists. Overwrite file? Selection (y/n):";
        cin >> yn;
        if (yn == 'y')
        {
            ofstream sav(pname.c_str());
            sav << str;
            sav.close();
            cout << "Done. File Saved at " << pname;
            getch();
            clearscreen();
            menu();
        }
        else if (yn == 'n')
        {
            cout << "OK. Will return to save menu.";
            getch();
            clearscreen();
            save(str);
        }
    }
}

void clearscreen()
{
    system("cls");
}

Oh, and as for an alternative regarding clearing the console screen, this article covers the subject in great detail, including th reasons why system("cls") is a Bad Idea. It includes a Windows API based function for this purpose, and I tested it with my version of your program and had no trouble with it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.