物件導向算是C++裡面蠻重要的一個東西的,他看起來很困難,不過只要大概了解他的運作邏輯之後就會覺得,其實物件導向也不會太複雜,而且還可以讓整個版面更加的整潔,那因為只是需要改檔案,所以這次大部分的變數我就拿取要被更改的檔案裡的,這樣子也比較好釐清。
一開始要來創建類別,但是因為我們的 標頭檔
可能會在一個程式中被重複引用,在不同的文件進行引用時,會發生大量的聲明衝突,讓程式發生錯誤,因此需要使用 #ifndef
來做區分,將我們 標頭檔
的內容寫在他與 #endif
之間。
#ifndef PROGRAM_H
#define PROGRAM_H
#include <iostream>
using namespace std;
#endif
接下來要創建類別,一樣先匯入基本函示庫,之後定義類別的名稱,我這邊是用 encryption
,在類別當中有 public
、private
以及 protected
三種他們分別代表的是 公有
任何使用這個類別的人都可以修改及取用當中的值、私有
在當中的值,僅限在這個類別當中修改及取用,其他人無法取用,最後一個 保護
如果是繼承類別的成員,能夠修改當中得值,但一樣不能進行取用。
#ifndef PROGRAM_H
#define PROGRAM_H
#include <iostream>
using namespace std;
class encryption
{
};
#endif
接下來我們要為類別定義變數以供後續做使用,這邊在 公有
及 私有
當中都有進行定義,這是為了方便某些值進行取用,以及防止某些值被修改。在 私有
當中的 location_table
是我們加密的方式依照原檔案,是環對稱這裡就直接把它搬過來。
public:
char spec[4][64];
int encypt_table[16];
private:
int location_table[4][16][2] = {{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {2, 0}, {2, 1}, {2, 2}, {2, 3}, {3, 0}, {3, 1}, {3, 2}, {3, 3}},
{{0, 7}, {1, 7}, {2, 7}, {3, 7}, {0, 6}, {1, 6}, {2, 6}, {3, 6}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {0, 4}, {1, 4}, {2, 4}, {3, 4}},
{{7, 7}, {7, 6}, {7, 5}, {7, 4}, {6, 7}, {6, 6}, {6, 5}, {6, 4}, {5, 7}, {5, 6}, {5, 5}, {5, 4}, {4, 7}, {4, 6}, {4, 5}, {4, 4}},
{{7, 0}, {6, 0}, {5, 0}, {4, 0}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {7, 3}, {6, 3}, {5, 3}, {4, 3}}};
char enc[8][8][2];
接下來就是本次的重點,函示那這些基本上都是寫在 公有
當中,因為函式就是為了縮短程式碼,以及方便調用類別當中的物件,所以基本是函式都是寫在 公有
當中。
這個函式是對應到了原始檔案中的 encypt_table
密碼表,是用來進行編碼使用的,當中的引數 a
是陣列,l
的話則是陣列的長度
。
void setEnc_table(int a[], int l) {
for (int i = 0; i < l; i++) {
encypt_table[i] = a[i];
}
}
這個函示呢,對應到的是原始檔案中將讀取到的文字變化為矩陣的那一段,這邊引數 j
跟 i
代表的是位置,c
的話則是文字。
void read_encryption(int j, int i, char c)
{
spec[j][i] = c;
}
這個函示對應到的可以說是核心,是原始檔案當中將文字打亂並重新排列為8*8矩陣的那一段。
void random()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 16; j++)
{
int table_no = (encypt_table[j] + i) % 4;
int row = location_table[table_no][j][0];
int column = location_table[table_no][j][1];
for (int k = 0; k < 2; k++)
{
enc[row][column][k] = spec[i][j * 2 + k];
}
}
}
}
最後這個函示是將檔案做儲存,把已經打亂的文字矩陣,存入指定的檔案當中,那這個指定檔案的名稱就是來自引數 f
。
void saveFile(FILE *f)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 2; k++)
{
printf("%c", enc[i][j][k]);
fprintf(f, "%c", enc[i][j][k]);
}
}
printf("\n");
fprintf(f, "\n");
}
}
#ifndef PROGRAM_H
#define PROGRAM_H
#include <iostream>
using namespace std;
class encryption
{
public:
char spec[4][64];
int encypt_table[16];
void setEnc_table(int a[], int l) {
for (int i = 0; i < l; i++) {
encypt_table[i] = a[i];
}
}
void read_encryption(int j, int i, char c)
{
spec[j][i] = c;
}
void random()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 16; j++)
{
int table_no = (encypt_table[j] + i) % 4;
int row = location_table[table_no][j][0];
int column = location_table[table_no][j][1];
for (int k = 0; k < 2; k++)
{
enc[row][column][k] = spec[i][j * 2 + k];
}
}
}
}
void saveFile(FILE *f)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 2; k++)
{
printf("%c", enc[i][j][k]);
fprintf(f, "%c", enc[i][j][k]);
}
}
printf("\n");
fprintf(f, "\n");
}
}
private:
int location_table[4][16][2] = {{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {2, 0}, {2, 1}, {2, 2}, {2, 3}, {3, 0}, {3, 1}, {3, 2}, {3, 3}},
{{0, 7}, {1, 7}, {2, 7}, {3, 7}, {0, 6}, {1, 6}, {2, 6}, {3, 6}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {0, 4}, {1, 4}, {2, 4}, {3, 4}},
{{7, 7}, {7, 6}, {7, 5}, {7, 4}, {6, 7}, {6, 6}, {6, 5}, {6, 4}, {5, 7}, {5, 6}, {5, 5}, {5, 4}, {4, 7}, {4, 6}, {4, 5}, {4, 4}},
{{7, 0}, {6, 0}, {5, 0}, {4, 0}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {7, 3}, {6, 3}, {5, 3}, {4, 3}}};
char enc[8][8][2];
};
#endif
這樣子 標頭檔
的部分就算完成了接下來就是主程式的部分了。
那一開始要先導入必要的涵式庫這裡的話我有做修改,跟原本的不同只需要載入兩個就行了,一個是基礎函示庫 iostream
,來載入基本元件以供使用,第二個則是這次的重點物件導向所使用的 標頭檔
副檔名為 .h
,那我這裡就叫做 program.h
這可以自行更改。
#include <iostream>
#include "program.h"
using namespace std;
int main(){
}
在主程式中我們寫有所需的變數要定義總共有三個,分別是類別變數,讀取檔案時文字所要寄放的變數,還有密碼表。
encryption enc;
char c[132];
int encypt[16] = { 0, 1, 2, 2, 1, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
這邊使用 setEnc_table()
來將這個類別變數當中的密碼表設置起來,之後再開啟兩個檔案,分別是要讀取的檔案及輸出時使用的檔案。
enc.setEnc_table(encypt, 16);
FILE *input_file1 = fopen("source.txt", "r");
if (!input_file1)
return 1;
FILE *output_file = fopen("output.txt", "w");
if (!output_file)
return 1;
這邊將我們檔案中的文字給讀取出來放在 c
這個變數當中。之後使用 read_encryption()
將文字按照順序排入類別變數當中。
for (int i = 0; i < 132; i++)
{
fscanf(input_file1, "%c", &c[i]);
}
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 32; i++)
{
enc.read_encryption(j, i, c[j * 32 + i + j]);
}
printf("\n");
}
這邊呢使用類別變數的 random()
將我們剛剛存入的矩陣給打亂拼成8*8樣子,之後再使用 saveFile()
儲存檔案。
enc.random();
enc.saveFile(output_file);
最後將我們上面開啟的兩個檔案做關閉避免記憶體溢出,這次的作業就倒此結束。
fclose(input_file1);
fclose(output_file);
return 0;
#include <iostream>
#include "progam.h"
using namespace std;
int main()
{
encryption enc;
char c[132];
int encypt[16] = { 0, 1, 2, 2, 1, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
enc.setEnc_table(encypt, 16);
FILE *input_file1 = fopen("source.txt", "r");
if (!input_file1)
return 1;
FILE *output_file = fopen("output.txt", "w");
if (!output_file)
return 1;
for (int i = 0; i < 132; i++)
{
fscanf(input_file1, "%c", &c[i]);
}
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 32; i++)
{
enc.read_encryption(j, i, c[j * 32 + i + j]);
}
printf("\n");
}
printf("\n");
enc.random();
enc.saveFile(output_file);
fclose(input_file1);
fclose(output_file);
return 0;
}