Полнофункциональная система тестирования
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
-
- Сообщения: 8
- Зарегистрирован: 26 июл 2017, 18:52
Так я вроде и исходил от того чтобы не пришлось писать один и тот же код помногу раз, что конкретно не так?
-
- Сообщения: 1228
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
А что методы get() и delete() делают? Просто по моему метод get() разрушает представления ООП об идентичности объекта, а delete превращает объект в невалидный. То есть после get() у тебя вместо одного объекта получается другой объект, а после delete() у тебя получается объект которого больше нет.angrystrike писал(а):Так я вроде и исходил от того чтобы не пришлось писать один и тот же код помногу раз, что конкретно не так?
Обычно в ООП создают метод, который может любой объект унаследованный от базового класса записать в поток. Это виртуальный абстрактный метод serialize(std :: ostream& o), который каждый класс реализует по своему. Прочитать объект из потока намного сложнее. Обычно делают так что несколько первых байт которые записал serialize - это метка типа. Тогда при чтении сначала читают метку типа, создают болванку объекта подходящего типа при помощи т.н. фабрики классов, а потом передают этой болванке поток (virtual void read(std :: istream& i) ) чтобы она прочитала все остальное.
2B OR NOT(2B) = FF
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Предлагаю писать все данные просто в бинарный поток через write. Каждое поле записывать по правилу: сначала длина, потом чек-сумма, потом шифрованные данные. Поднимаем из файла в таком же порядке.
Небольшие наброски кода. Код писался в блокноте, так что могут быть опечатки.
Небольшие наброски кода. Код писался в блокноте, так что могут быть опечатки.
Код: Выделить всё
#include <string>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>
inline unsigned char CheckSum(const std::string& str)
{
const auto sum = std::accumulate(str.cbegin(), str.cend(), 0ul);
// Оставляем только младший байт от всей суммы.
return static_cast<unsigned char>(sum);
}
void WriteString(std: :o fstream& file, const std::string& str, unsigned char xor_key)
{
const auto length = str.length();
file.write(reinterpret_cast<const char*>(&length), sizeof(length));
const auto check_sum = CheckSum(str);
file.write(reinterpret_cast<const char*>(&check_sum), sizeof(check_sum));
char buffer[length];
std::transform(str.c_str(), str.c_str() + length, buffer, [xor_key](char c){ return (c ^ xor_key); });
file.write(buffer, length);
}
void ReadString(std::ifstream& file, std::string& str, unsigned char xor_key)
{
std::size_t length;
file.read(reinterpret_cast<char*>(&length), sizeof(length));
unsigned char check_sum;
file.read(reinterpret_cast<char*>(&check_sum), sizeof(check_sum));
char buffer[length];
file.read(buffer, length);
std::transform(buffer, buffer + length, buffer, [xor_key](char c){ return (c ^ xor_key); });
str.assign(buffer, buffer + length);
if (check_sum != CheckSum(str))
{
throw MyException();
}
}
class User
{
User();
~User();
void Save() const;
void Load();
private:
static const unsigned char sm_name_key = 0x13;
static const unsigned char sm_password_key = 0x57;
private:
std::string m_file_name;
std::string m_name;
std::string m_password;
};
void User::Save() const
{
std: :o fstream file(m_file_name.c_str(), std::ios_base::binary);
::WriteString(file, m_name, sm_name_key);
::WriteString(file, m_password, sm_password_key);
}
void User::Load()
{
std::ifstream file(m_file_name.c_str(), std::ios_base::binary);
::ReadString(file, m_name, sm_name_key);
::ReadString(file, m_password, sm_password_key);
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
-
- Сообщения: 8
- Зарегистрирован: 26 июл 2017, 18:52
На функции read и write string вылазит с десяток ошибок про то что для transform нужно 5 аргументов, а есть 4 и char buffer не инициализируется length, хотя почему если lenght - const, я так и не понял.
У меня VS 2015
У меня VS 2015
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
1) Глянь тут, transform в первом варианте принимает как раз 4 параметра. Если никак, то перепиши на обычный цикл. Я просто одной строкой хотел сделать.
2) Должно работать на 15-й студии даже если length не константная. Это 11-й стандарт.
В любом случае я сразу предупредил, что это только наброски. Их нельзя взять и вставить, чтобы сразу всё заработало. Их нужно разобрать, понять как это должно работать и потом использоваться у себя не готовый код, а сам подход.
2) Должно работать на 15-й студии даже если length не константная. Это 11-й стандарт.
В любом случае я сразу предупредил, что это только наброски. Их нельзя взять и вставить, чтобы сразу всё заработало. Их нужно разобрать, понять как это должно работать и потом использоваться у себя не готовый код, а сам подход.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
-
- Сообщения: 8
- Зарегистрирован: 26 июл 2017, 18:52
Ошибка: vector out of range
Хочу чтобы спрашивался сам вопрос, в какой тест он входит, далее 4 варианта ответа, всё работает, но при вводе последнего варианта ответа вылазит ошибка
Код: Выделить всё
vector<Question> quests;
vector<Option> options;
int qAmount;
cout << "Input quantity of questions, that you want create: ";
cin >> qAmount;
quests.resize(qAmount);
options.resize(qAmount * 4);
for (int i = 0, j = 0; i < qAmount, j < qAmount * 4; i++, j++)
{
quests[i].setData();
for (int k = 0; k < 4; k++)
{
options[j].setQuestName(quests[i].getQuest());
options[j].setData();
// ошибка вектор out of range
}
}
ofstream outQ(quests[0].getFile(), ofstream::binary);
ofstream outO(options[0].getFile(), ofstream::binary);
if (outQ.is_open() && outO.is_open())
{
for (int i = 0; i < qAmount; i++)
{
outQ << quests[i].getQuest() << endl;
outQ << quests[i].getTestName() << endl;
}
for (int i = 0; i < qAmount * 4; i++)
{
outO << options[i].getOption() << endl;
outO << options[i].getIsCor() << endl;
outO << options[i].getQuestName() << endl;
}
outQ.close();
outO.close();
}
-
- Сообщения: 1228
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
Ну там в Вижуал Студии можно поставить брейкпоинт и посмотреть в рантайме какого у тебя массив создается размера, куда ты пытаешься записать свой элемент и почему он не влазит. Если у тебя mingw, то можно к нему подключить Eclipse CDT или QtCreator. Какие вообще могут быть проблемы с отладкой однопоточного приложения?angrystrike писал(а):Ошибка: vector out of range
2B OR NOT(2B) = FF
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Код: Выделить всё
for (int i = 0, j = 0; i < qAmount, j < qAmount * 4; i++, j++)
{
quests[i].setData();
for (int k = 0; k < 4; k++)
{
options[j].setQuestName(quests[i].getQuest());
options[j].setData();
// ошибка вектор out of range
}
}
И условие внешнего цикла неверное. Вот такое выражение
Код: Выделить всё
i < qAmount, j < qAmount * 4;
То есть, другими словами, выражение с использованием запятых имеет значение последнего операнда.
Если хочешь получить сложное условие, то используй логические операции && и ||, которые обозначают И и ИЛИ соответственно.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.