Member Avatar for 111100/11000

http://en.wikipedia.org/wiki/Transposition_cipher#Columnar_transposition
This is wiki site of what am trying to do

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

char GRID[3][80];
int MENU(int menu_choice);
int REVIEW_OF_GRIDS_FIRST_79_CHARACTERS(int four);

int main()
{
    cout << "                         This is RAIL FENCE CIPHER\n" << endl;
//-----------------------------------------------------------------------------------------------------
//filing GRID with asterisks(*)
    char asterisk='*';
    int k=-1;
    int i=0;
        while(k<2)
        {
        k++;
            while(i<80)
            {
            GRID[k][i] = asterisk;
            i++;
            }
            cout << "\n" ;
        i=0;
        }
//-----------------------------------------------------------------------------------------------------
//plaintext input into GRID
    char plaintext[0];
    cout << "Enter message to encode:" << "                 NOTE:Asterisk(*) symbol is not allowed\n";
    cin >> plaintext;
    int grid_row[5] = {0,1,2,1,99};        //012101210121 is pattern and 99 is irrelevant
    int row_counter = 0;
    int grid_position_X = 0;
    for(int plaintext_counter = 0; plaintext_counter < strlen(plaintext); plaintext_counter++)
    {
        if(row_counter == 4)
        {
        row_counter = 0;
        }
            GRID[grid_row[row_counter]][grid_position_X] = plaintext[plaintext_counter];
            row_counter++;
            grid_position_X++;
    }
//-----------------------------------------------------------------------------------------------------
//user choice
    int user_choice = 0;
    while(user_choice != 6 || user_choice != 7)   //restarting and ending program still not finished
    {
        user_choice=MENU(0);
        switch(user_choice)
        {
            case 1:
            {
                //not finished
            }
            case 2:
            {
                //not finished
            }
            case 3:
            {
                cout << "There are " << strlen(plaintext) << " characters" <<endl<<endl;//shows always 2
                break;
            }
            case 4:                                                   //it doesnt show more than 5 chars
            {
                REVIEW_OF_GRIDS_FIRST_79_CHARACTERS(0);
                break;
            }
            case 5:
            {
                //not finished
            }
        }
    }
    cin.get();
    return 0;
}
int MENU(int menu_choice)
{
    cout << "Enter number of operation you would like to preform\n";
    cout << "1.Output encoded characters on screen\n";
    cout << "2.Save encoded characters to text file\n";
    cout << "3.Display length of characters\n";
    cout << "4.Review grids first 79 characters\n";
    cout << "5.\n";                                     //haven't decided what to put here yet
    cout << "6.Run program again\n";
    cout << "7.Exit program\n";
    cin >> menu_choice;
    return menu_choice;
}
int REVIEW_OF_GRIDS_FIRST_79_CHARACTERS(int four)       //int four is unimportant
{
    int k2=-1;
    int i2=0;
        while(k2<2)
        {
        k2++;
            while(i2<80)
            {
            cout << GRID[k2][i2] ;
            i2++;
            }
            cout << "\n" ;
        i2=0;
        }
}

PROBLEMS are that it doesn't show more than 5 chars on choice 4 and on choice 3 it shows always 2

Recommended Answers

All 4 Replies

I'm not familiar with Rail Fence cypher but at a first glance your code is full of odd things. Without knowing what rail fence cypher is or how it works I think I do understand what you are trying to do and I tried to correct it. Added some comments as remarks.

#include <iostream>
#include <cstring>
#include <cmath>

using namespace std;

const int GRID_ROWS     = 3;
const int GRID_COLUMNS  = 80;

// Global variables make bunnies cry. Pass it between functions instead.
char GRID[GRID_ROWS][GRID_COLUMNS];

// Wouldn't do function names in caps, but that's a style thing I guess..
int  MENU(int menu_choice);
void REVIEW_OF_GRIDS_FIRST_79_CHARACTERS();

int main()
{
    // High "This is sparta!" factor. But again a style thing. =)
    cout << "                         This is RAIL FENCE CIPHER\n" << endl;

//-----------------------------------------------------------------------------------------------------
//filing GRID with asterisks(*)

    // Changed it to make it easier to read and maintain.
    for (int k = 0; k < GRID_ROWS; k++)
    {
        for (int i = 0; i < GRID_COLUMNS; i++)
        {
            GRID[k][i] = '*';
        }
    }

//-----------------------------------------------------------------------------------------------------
//plaintext input into GRID

    // Why size 0? Use a string instead.
    // char plaintext[0];
    string plaintext;

    // Might want to use getline. (not sure what your requirements are)
    cout << "Enter message to encode:" << "                 NOTE:Asterisk(*) symbol is not allowed\n";
    cin >> plaintext;


    // If 99 is irrelvant, why include it? I removed it.
    int grid_row[] = {0,1,2,1};
    const unsigned int PATTERN_SIZE = sizeof(grid_row) / sizeof(int);

    // grid_position_X is equal to plaintext_counter? I removed it.
    // Also, what will you do when the entered plaintext has more than GRID_COLUMNS characters?
    // I guess that would be a limit of your program because it would otherwise overwrite grid items.
    for(unsigned int plaintext_counter = 0, row_counter = 0; plaintext_counter < plaintext.length(); plaintext_counter++, row_counter++)
    {
        // Prevent row_counter from going out of bounds.
        if(row_counter >= PATTERN_SIZE)
        {
            row_counter = 0;
        }

        // Apply the pattern to every character of the plaintext.
        // So if I understand correctly, the pattern desides the rows to write in while the character index determines the column?
        // e.g:
        // Plaintext:                   H       e      l      l     o
        // Pattern:                     0       1      2      1     0
        // Grid index to store char:  [0][0] [1][1] [2][2] [1][3] [0][4]
        //
        GRID[grid_row[row_counter]][plaintext_counter] = plaintext[plaintext_counter];
    }

//-----------------------------------------------------------------------------------------------------
//user choice
    int user_choice = 0;

    // Logic error. (user_choice != 6 || user_choice != 7) is always true as it can't assume 2 values at the same time.
    while(user_choice != 6 && user_choice != 7)
    {
        user_choice = MENU(0);

        switch(user_choice)
        {
            case 1:
            {
                //not finished
            }
            case 2:
            {
                //not finished
            }
            case 3:
            {
                cout << "There are " << plaintext.length() << " characters" << endl << endl;
                break;
            }
            case 4:                                                   //it doesnt show more than 5 chars
            {
                REVIEW_OF_GRIDS_FIRST_79_CHARACTERS();
                break;
            }
            case 5:
            {
                //not finished
            }
            default:
            {

            }
        }
    }

    return 0;
}

// What is the purpose of menu choice as a parameter? Either pass it by reference and don't return anything
// or omit and and return the selected menu item.
int MENU(int menu_choice)
{
    cout << "Enter number of operation you would like to preform\n";
    cout << "1.Output encoded characters on screen\n";
    cout << "2.Save encoded characters to text file\n";
    cout << "3.Display length of characters\n";
    cout << "4.Review grids first 79 characters\n";
    cout << "5.\n";                                     //haven't decided what to put here yet
    cout << "6.Run program again\n";
    cout << "7.Exit program\n";
    cin >> menu_choice;
    return menu_choice;
}

// Why is "four" there? I removed it. It's also 80 characters not 79 but it depends on the constant. Omit it from the function name.
// Also changed the return type to void as I don't know what you expect it to return.
void REVIEW_OF_GRIDS_FIRST_79_CHARACTERS()
{
    // Rewritten
    for (int i = 0; i < GRID_ROWS; i++)
    {
        for (int j = 0; j < GRID_COLUMNS; j++)
        {
            cout << GRID[i][j] << " ";
        }
        cout << endl;
    }
}

-edit-

Will read the wikipedia article you linked once some of these basic things are sorted out. I'm currently not in a position where I can afford reading such an article but can do so once at home..

-edit2-

Quickly looked over the article and the modifications seem to match what you're probably trying to do.

Quick lunch break experiment that doesn't use a two dimensional array. It's probably better to read with a 2D array though. Mainly done because it seemed fun, but posted it in case you find it useful..

#include <iostream>
#include <algorithm>
using namespace std;

const int AMOUNT_OF_RAILS = 3;
const int GROUP_WIDTH     = 5;

int  PyramidLineRows      (const int rowIndex);
int  PrintRail            (int rail, const string text, const int railcount, int groupRemainder, const int groupSize);
void PrintRailFenceSypher (string text, const int rails);


int PyramidLineRows(const int rowIndex)
{
    // The rail system consists of pyramids that alternate between inverted and non-inverted to form the zigzag-ing line.
    return (1 + (2 * rowIndex));
}


int PrintRail(int rail, const string text, const int railcount, int groupRemainder, const int groupSize)
{
    // We are starting inverted on anything but the last rail. Meaning visually the text is going downwards on the rail.
    bool isInverted = true;
    unsigned index      = rail;

    // The last rail is identical to the first rail aside from it's starting index.
    // Modify it's because it's index is used to calculate the row of the pyramid later on.
    if (rail == railcount - 1)
    {
        rail = 0;
    }

    // Go past the relevant character of the supplied string.
    while (index < text.length())
    {
        // It's time to print a new group.
        if (groupRemainder <= 0)
        {
            cout << " ";
            groupRemainder = groupSize;
        }

        // Print the character.
        cout << text[index];
        groupRemainder--;

        // The amount of places we have to advance is based on the shape of a pyramid and if we're going up
        // or down on the tracks. Advance over the "pyramid section". There need to be at least 2 rails to form a pyramid.
        if (railcount > 1)
        {
            if (isInverted || rail == 0)
            {
                index += PyramidLineRows(railcount - 2 - rail);
            }
            else
            {
                index += PyramidLineRows(rail - 1);
            }
        }

        // We skipped over the pyramid rows. Now advance to the index of the next character.
        index++;
        isInverted = !isInverted;
    }

    // Return the amount of characters left to be places on the current group.
    return groupRemainder;
}


void PrintRailFenceSypher (string text, const int rails)
{
    // The amount of characters per group. Only for display purposes.
    int groupRemainder = GROUP_WIDTH;

    // remove any non characters from the string.
    text.erase(remove_if(text.begin(), text.end(), not1(ptr_fun<int, int>(isalpha))), text.end());

    // Print every rail.
    for (int i = 0; i < rails; i++)
    {
        // PrintRail will inform how many characters remain to be filled in the last group.
        groupRemainder = PrintRail(i, text, rails, groupRemainder, GROUP_WIDTH);
    }
}


int main()
{
    const string example = "WE ARE DISCOVERED. FLEE AT ONCE";

    cout << "The rail fence sypher of \"" << example << "\" with " << AMOUNT_OF_RAILS << " rail(s) is:\n";
    PrintRailFenceSypher(example, AMOUNT_OF_RAILS);

    return 0;
}
Member Avatar for 111100/11000

works great but i dont understand this line

48.const unsigned int PATTERN_SIZE = sizeof(grid_row) / sizeof(int);

and how it's better here

if(row_counter >= PATTERN_SIZE)
{
row_counter = 0;
}

than this

if(row_counter == 4)
{
row_counter = 0;
}

PS:second code works great also but i can't understand it,it's not important

It's just to make things more flexible. (e.g. when you change the pattern to contain a different amount of elements, you don't have to update the size because it is derived. sizeof(grid_row) will return the size of grid_row in bytes. When you divide that by sizeof(int), which returns the size of a single integer in byte and is the type of the array, you get the amount of elements in grid_row. (e.g. if grid_row is 12 bytes, and an integer is 4 bytes then it will have 3 elements)

More is needed to make it fully flexible though, but this was just an easy fix so I just applied it when I saw 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.