文字列をXORし復号化したいです

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
texis

文字列をXORし復号化したいです

#1

投稿記事 by texis » 8年前

いつもお世話になっております。
現在私はアドベンチャーゲームを作成しており、
テキストメッセージのバックログをXORをかけて簡単な暗号化をし
外部ファイルにバイナリで書き出した後、読み込み復号化したいと思っています。

しかし、復号化の際「\t」「\n」をうまく判定することができていないのか
表示するところまでたどり着けません。
書き出したコードは以下の通りです。

OSはWindows10、VS2015を使用しています。
お知恵をお貸しいただければと思います。
よろしくお願いいたします。

コード:

#define CIPHER_KEY 12345

#include <string>
#include <vector>
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
	vector<vector<string>> backLog;
	vector<string> backLogStr;

	backLogStr.push_back("あいうえお");
	backLogStr.push_back("かきくけこ");
	backLogStr.push_back("さしすせそ");
	backLog.push_back(backLogStr);

	backLogStr.clear();
	
	backLogStr.push_back("たちつてと");
	backLogStr.push_back("なにぬねの");
	backLog.push_back(backLogStr);

	for (int i = 0; i < (int)backLog.size(); i++)
	{
		for (int j = 0; j < (int)backLog[i].size(); j++)
		{
			if (j != 0)
			{
				cout << '\t';
			}
			cout << backLog[i][j];
		}
		cout << '\n'<< endl;
	}

	//	XORをかけて書き出し
	ofstream fileSave("backLog.dat", ios::binary);
	for (int i = 0; i < (int)backLog.size(); i++)
	{
		for (int j = 0; j < (int)backLog[i].size(); j++)
		{
			if (j != 0)
			{
				fileSave << ('\t'^ CIPHER_KEY);
			}
			string str = backLog[i][j];
			char* cstr = new char[str.size() + 1];
			char_traits<char>::copy(cstr, str.c_str(), str.size() + 1);
			char byteStr = '\0';
			string outStr = "\0";
			for (int k = 0; k < (int)str.size(); k++)
			{
				outStr += cstr[k] ^ CIPHER_KEY;
				if (byteStr == '\\')
				{
					outStr += '\\';
				}
			}

			fileSave << outStr;
			delete cstr;
		}
		fileSave << ('\n'^ CIPHER_KEY);
	}


	backLogStr.clear();
	backLog.clear();

	//	読み込み
	ifstream ifs("backLog.dat", ios::binary);
	if (ifs)
	{
		char byte = '\0';
		string loadString = "\0";
		vector<string> vs;

		while (!ifs.eof())
		{
			ifs.read((char*)&byte, sizeof(char));
			byte = byte ^ CIPHER_KEY;

			//	現状どちらの条件にも引っかからない
			if (byte == '\t')
			{
				backLog.push_back(vs);
				vs.clear();
			}
			else if (byte == '\n')
			{
				vs.push_back(loadString);
				loadString = "\0";
			}
			else
			{
				loadString += byte;
			}
		}

		//	表示
		for (int i = 0; i < (int)backLog.size(); i++)
		{
			for (int j = 0; j < (int)backLog[i].size(); j++)
			{
				cout << backLog[i][j];
			}
		}

	}

    return 0;
}

かずま

Re: 文字列をXORし復号化したいです

#2

投稿記事 by かずま » 8年前

47行目: fileSave << char('\t'^ CIPHER_KEY); に変更
66行目: fileSave << char('\n'^ CIPHER_KEY); に変更
68行目: fileSave.close(); を追加
89行目: vs.push_back(loadString); に変更
90行目: loadString = "\0"; に変更
95行目: backLog.push_back(vs); vs.clear(); を追加

最後の表示は、if (j != 0) cout << '\t'; と cout << endl; を
追加したほうが見やすいでしょう。

これでどうでしょうか?

57行目の '\\' の処理の意味が分かりません。
余計なものを削除すると、次のように書けます。

コード:

#define CIPHER_KEY 12345
 
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
 
using namespace std;
 
int main()
{
    vector<vector<string>> backLog;
    vector<string> backLogStr;
 
    backLogStr.push_back("あいうえお");
    backLogStr.push_back("かきくけこ");
    backLogStr.push_back("さしすせそ");
    backLog.push_back(backLogStr);
 
    backLogStr.clear();
    
    backLogStr.push_back("たちつてと");
    backLogStr.push_back("なにぬねの");
    backLog.push_back(backLogStr);
 
    for (size_t i = 0; i < backLog.size(); i++) {
        for (size_t j = 0; j < (int)backLog[i].size(); j++) {
            if (j != 0) cout << '\t';
            cout << backLog[i][j];
        }
        cout << endl;
    }
 
    ofstream fileSave("backLog.dat", ios::binary);
    for (size_t i = 0; i < backLog.size(); i++) {
        for (size_t j = 0; j < backLog[i].size(); j++) {
            if (j != 0) fileSave.put('\t' ^ CIPHER_KEY);
            for (size_t k = 0; k < backLog[i][j].size(); k++)
                fileSave.put(backLog[i][j][k] ^ CIPHER_KEY);
        }
        fileSave.put('\n' ^ CIPHER_KEY);
    }
    fileSave.close();
 
    ifstream ifs("backLog.dat", ios::binary);
    if (!ifs) return 1;
    char byte;
    string loadString;
    vector<string> vs;
    vector<vector<string>> vvs;
    while (ifs.get(byte)) {
        byte = byte ^ CIPHER_KEY;
        if (byte != '\t' && byte != '\n')
            loadString += byte;
        else {
            vs.push_back(loadString);
            loadString.clear();
            if (byte == '\n') {
                vvs.push_back(vs);
                vs.clear();
            }
        }
    }

    for (size_t i = 0; i < vvs.size(); i++) {
        for (size_t j = 0; j < vvs[i].size(); j++) {
            if (j != 0) cout << '\t';
            cout << vvs[i][j];
        }
        cout << endl;
    }
}

texis

Re: 文字列をXORし復号化したいです

#3

投稿記事 by texis » 8年前

素早いお返事をありがとうございます。

なるほど、キャストをすればよかったのですね。勉強になりました。
細かいミスも多かったようで、申し訳ございませんでした。
また、ほかの部分でも勉強になる点が多々ございましたので
頂いたコードをよくよく読み解いてみようと思います。

57行目の処理はダメ文字回避のつもりでしたが、
よくよく考えたら不要な処理だったようですね。
ご指摘ありがとうございました。

重ね重ねになりますが、本当にありがとうございました!

返信

“C言語何でも質問掲示板” へ戻る