この質問では、コンストラクターが呼び出すメソッドで奇妙なセグメンテーション違反が発生しますが、明らかに他の場所にはありません (定義が次のように見えるCodeBreaker::testVectorOfElements
呼び出し元でもありません)。main()
void CodeBreaker::testVectorOfElements(int size)
{
// try to do what you did in makeNumericCodes with the vector
while (this->numericCodes.size() < size)
{
this->numericCodes.push_back(this->Z[0]);
}
}
CodeBreaker
プライベートがありstd::vector<IntegerRing::Element> numericCodes
ます。
この問題の原因は、 である の私の宣言にIntegerRing
あるようIntegerGroup
です。両方のクラスの MCVE コードは次のとおりです。
IntegerGroup.h
#ifndef INTEGERGROUP_H
#define INTEGERGROUP_H
#include "Array.h"
#include <vector> // for some reason, this didn't work.
#include <iostream>
// This group is the integers mod n
// multiplication in integer group is simply integer addition modulo n
class IntegerGroup
{
public:
IntegerGroup();
IntegerGroup(int);
class GroupElement
{
protected:
int m;
IntegerGroup* group;
public:
GroupElement();
GroupElement(int);
GroupElement(int, IntegerGroup*);
~GroupElement();
};
int size() const;
protected:
int n;
Array<GroupElement> elements;
void createNewElement(int);
};
#endif
IntegerGroup.cpp
#include "IntegerGroup.h"
#include <new>
#include <iostream>
IntegerGroup::IntegerGroup()
{
}
IntegerGroup::IntegerGroup(int n)
: n(n), elements(Array<IntegerGroup::GroupElement>(n))
//elements(std::vector<IntegerGroup::GroupElement>(n))
{
//this is to have integers in [0,n-1]
for (int j = 0; j < n; j++)
{
this->createNewElement(j);
}
}
void IntegerGroup::createNewElement(int m)
{
// create new GroupElement
GroupElement newElement(m, this);
// store it at index m in elements
this->elements[m] = newElement;
}
IntegerGroup::GroupElement::GroupElement()
: group(0)
{
}
IntegerGroup::GroupElement::GroupElement(int x)
: m(x), group(0)
{
}
IntegerGroup::GroupElement::GroupElement(int m, IntegerGroup * g)
: group(g)
{
// this->m must be in [0, g->size() - 1], if g not null
if (g)
{
this->m = m % g->size();
if (this->m < 0) this->m = g->size() + this->m;
}
else
{
this->m = m;
}
}
IntegerGroup::GroupElement::~GroupElement()
{
if (this->group)
{
this->group = 0;
}
}
int IntegerGroup::size() const { return this->n; }
IntegerRing.h
#ifndef INTEGERRING_H
#define INTEGERRING_H
#include "IntegerGroup.h"
class IntegerRing : public IntegerGroup
{
public:
IntegerRing();
IntegerRing(int);
IntegerRing(const IntegerGroup&);
class Element : public IntegerGroup::GroupElement::GroupElement
{
public:
Element();
Element(int, IntegerGroup*);
//~Element();
operator IntegerGroup::GroupElement() { return IntegerGroup::GroupElement(); }
Element(const IntegerGroup::GroupElement&);
};
};
#endif
IntegerRing.cpp
#include "IntegerRing.h"
#include "IntegerGroup.h"
#include <iostream>
IntegerRing::Element::Element()
: IntegerGroup::GroupElement()
{
}
IntegerRing::IntegerRing(int n)
: IntegerGroup::IntegerGroup(n)
{
}
IntegerRing::Element::Element(int m, IntegerGroup * g)
: IntegerGroup::GroupElement(m, g)
{
}
IntegerRing::Element::Element(const IntegerGroup::GroupElement& el)
: IntegerGroup::GroupElement(el)
{
}
CodeBreaker.h
#ifndef CODEBREAKER_H
#define CODEBREAKER_H
#include <string>
#include <map>
#include <utility>
#include <vector>
#include "IntegerRing.h"
#include "PunctuationOccurrenceList.h"
class CodeBreaker
{
public:
CodeBreaker();
CodeBreaker(std::string&, bool);
void testVectorOfElements(int);
private:
PunctuationOccurrenceList punctuation;
IntegerRing Z;
void initCharMap();
void makeNumericCodes();
int getNumericCodeFor(char) const;
std::map<char, int> charFrequencyMap;
std::vector<IntegerRing::Element> numericCodes;
std::string ciphertext, plaintext;
std::string cipherFilename;
};
#endif
CodeBreaker.cpp
#include "CodeBreaker.h"
#include <iostream>
#include <fstream>
#include <algorithm>
CodeBreaker::CodeBreaker()
: Z(IntegerRing::IntegerRing(26)),
punctuation(PunctuationOccurrenceList::PunctuationOccurrenceList())
{
// initialize charFrequencyMap
this->initCharMap();
}
CodeBreaker::CodeBreaker(std::string& str, bool readFromFile)
: Z(IntegerRing::IntegerRing(26))
{
// if reading from file
if (readFromFile)
{
// str is filename to read from
// open file specified by str
std::ifstream input(str.c_str());
std::string line;
// read contents to ciphertext
while (std::getline(input, line))
{
this->ciphertext += line + "\n";
}
// close file
input.close();
}
// otherwise
else
{
// str is ciphertext itself
// write it to this->ciphertext
this->ciphertext = str;
}
// strip punctuation
this->punctuation = PunctuationOccurrenceList::PunctuationOccurrenceList(this->ciphertext);
// log numeric codes ('A' => 0, 'B' => 1, ... , 'Z' => 25)
this->makeNumericCodes();
}
void CodeBreaker::makeNumericCodes()
{
std::cout << "this->ciphertext.size() == " << this->ciphertext.size() << std::endl;
std::cout << "this->numericCodes.capacity() == " << this->numericCodes.capacity() << std::endl;
std::cout << "this->numericCodes.max_size() == " << this->numericCodes.max_size() << std::endl;
// if there isn't as many numeric codes as there are characters in ciphertext
while (this->numericCodes.size() < this->ciphertext.size())
{
std::cout << "Pushing dummy Element to numericCodes...\n";
this->numericCodes.push_back(this->Z[0]);
}
// for every character in ciphertext
for (int j = 0; j < this->ciphertext.size(); j++)
{
// if character's numerical code is not logged in numericCodes
int numericCode = this->getNumericCodeFor(ciphertext[j]);
if (numericCode != this->numericCodes[j].val())
// log it
this->numericCodes[j] = (IntegerRing::Element)this->Z[numericCode];
}
// while there are more numericCodes than characters in ciphertexts
while (this->numericCodes.size() > this->ciphertext.size())
// remove last character
this->numericCodes.pop_back();
}
void CodeBreaker::testVectorOfElements(int size)
{
// try to do what you did in makeNumericCodes with the vector
while (this->numericCodes.size() < size)
{
this->numericCodes.push_back(this->Z[0]);
}
}
int CodeBreaker::getNumericCodeFor(char c) const
{
// if character is in ['A', 'Z']
if ((c >= 'A') && (c <= 'Z'))
// return its int value minus 'A'
return (int)(c - 'A');
// otherwise, if it is in ['a', 'z']
if ((c >= 'a') && (c <= 'z'))
// return its int value minus 'a'
return (int)(c - 'a');
std::cout << "invalid character: " << c << std::endl;
return -1;
}
void CodeBreaker::initCharMap()
{
for (char c = 'A'; c <= 'Z'; c++)
{
this->charFrequencyMap[c] = 0;
}
}
main.cpp
#include <iostream>
#include <string>
#include "CodeBreaker.h"
//#include "IntegerRing.h"
using namespace std;
int main()
{
bool testInClass = true;
if (testInClass)
{
string str = "I'm plaintext, but deal with me anyways, because this is mock code.";
CodeBreaker c(str, false);
/*CodeBreaker d;
d.testVectorOfElements(64);*/
}
else
{
vector<IntegerRing::Element> a;
IntegerRing Z(26);
cout << "a.capacity == " << a.capacity() << endl;
while (a.size() < 2400)
{
a.push_back(Z[0]);
}
cout << "a.size() == " << a.size() << endl;
for (int j = 0; j < 26; j++)
{
cout << a[j] << " ";
}
cout << endl;
}
return 0;
}
Array
単純な DIYvector
です。これは、データ構造クラスのために何年も前に作成しなければならなかったものです。vector
ここで抱えている問題の代わりに使用しました。(問題認識?)
すべてのコードはこちらから入手できます。問題は、new
これらのポインターを割り当てるときに使用する必要があったかどうかです。がIntegerRing
作成されると、それIntegerRing::Elements
自体へのポインターを渡す を作成しようとします (必要に応じて、リングの数学的定義では、リングに加算と乗算を装備する必要があり、その数学的構造の要素はその演算子を使用します)。