 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;
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;
cout << "Enter message to encode:" << "                 NOTE:Asterisk(*) symbol is not allowed\n";
cin >> plaintext;
int grid_row = {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
{
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;
}
{
REVIEW_OF_GRIDS_FIRST_79_CHARACTERS(0);
break;
}
case 5:
{
//not finished
}
}
}
cin.get();
return 0;
}
{
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";
}
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

Answered by Gonbe 32 in a post from

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 …

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..
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;
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:      
//
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)
{

switch(user_choice)
{
case 1:
{
//not finished
}
case 2:
{
//not finished
}
case 3:
{
cout << "There are " << plaintext.length() << " characters" << endl << endl;
break;
}
{
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.
{
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";
}

// 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;
} 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, learning, and sharing knowledge.