Полнофункциональная система тестирования

Ответить

Код подтверждения
Введите код в точности так, как вы его видите. Регистр символов не имеет значения.

BBCode ВКЛЮЧЁН
[img] ВКЛЮЧЁН
[url] ВКЛЮЧЁН
Смайлики ОТКЛЮЧЕНЫ

Обзор темы
   

Развернуть Обзор темы: Полнофункциональная система тестирования

Re: Полнофункциональная система тестирования

Romeo » 05 авг 2017, 01:15

Код: Выделить всё

                    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
                        }
                    }
А кто будет j увеличивать внутри внутреннего цикла?
И условие внешнего цикла неверное. Вот такое выражение

Код: Выделить всё

i < qAmount, j < qAmount * 4;
обозначает "вычислить i < qAmount, результат игнорировать, вычислить j < qAmount * 4, результат вернуть в качестве значения выражения".
То есть, другими словами, выражение с использованием запятых имеет значение последнего операнда.
Если хочешь получить сложное условие, то используй логические операции && и ||, которые обозначают И и ИЛИ соответственно.

Re: Полнофункциональная система тестирования

Absurd » 04 авг 2017, 21:39

angrystrike писал(а):Ошибка: vector out of range
Ну там в Вижуал Студии можно поставить брейкпоинт и посмотреть в рантайме какого у тебя массив создается размера, куда ты пытаешься записать свой элемент и почему он не влазит. Если у тебя mingw, то можно к нему подключить Eclipse CDT или QtCreator. Какие вообще могут быть проблемы с отладкой однопоточного приложения?

Re: Полнофункциональная система тестирования

angrystrike » 04 авг 2017, 08:30

Ошибка: vector out of range

Код: Выделить всё

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();
					}
Хочу чтобы спрашивался сам вопрос, в какой тест он входит, далее 4 варианта ответа, всё работает, но при вводе последнего варианта ответа вылазит ошибка

Re: Полнофункциональная система тестирования

Romeo » 31 июл 2017, 11:38

1) Глянь тут, transform в первом варианте принимает как раз 4 параметра. Если никак, то перепиши на обычный цикл. Я просто одной строкой хотел сделать.

2) Должно работать на 15-й студии даже если length не константная. Это 11-й стандарт.

В любом случае я сразу предупредил, что это только наброски. Их нельзя взять и вставить, чтобы сразу всё заработало. Их нужно разобрать, понять как это должно работать и потом использоваться у себя не готовый код, а сам подход.

Re: Полнофункциональная система тестирования

angrystrike » 31 июл 2017, 10:27

На функции read и write string вылазит с десяток ошибок про то что для transform нужно 5 аргументов, а есть 4 и char buffer не инициализируется length, хотя почему если lenght - const, я так и не понял.
У меня VS 2015

Re: Полнофункциональная система тестирования

Romeo » 28 июл 2017, 15:46

Предлагаю писать все данные просто в бинарный поток через 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);
}

Re: Полнофункциональная система тестирования

Absurd » 28 июл 2017, 15:45

angrystrike писал(а):Так я вроде и исходил от того чтобы не пришлось писать один и тот же код помногу раз, что конкретно не так?
А что методы get() и delete() делают? Просто по моему метод get() разрушает представления ООП об идентичности объекта, а delete превращает объект в невалидный. То есть после get() у тебя вместо одного объекта получается другой объект, а после delete() у тебя получается объект которого больше нет.

Обычно в ООП создают метод, который может любой объект унаследованный от базового класса записать в поток. Это виртуальный абстрактный метод serialize(std :: ostream& o), который каждый класс реализует по своему. Прочитать объект из потока намного сложнее. Обычно делают так что несколько первых байт которые записал serialize - это метка типа. Тогда при чтении сначала читают метку типа, создают болванку объекта подходящего типа при помощи т.н. фабрики классов, а потом передают этой болванке поток (virtual void read(std :: istream& i) ) чтобы она прочитала все остальное.

Re: Полнофункциональная система тестирования

angrystrike » 28 июл 2017, 14:47

Так я вроде и исходил от того чтобы не пришлось писать один и тот же код помногу раз, что конкретно не так?

Re: Полнофункциональная система тестирования

Absurd » 28 июл 2017, 13:17

angrystrike писал(а):Смотрится рационально(по крайней мере я так думаю ), но дайте какие нибудь советы по самой реализации и какую структуру данных стоит использовать для хранения в файле, последующем считывании?

ООП применяют для того чтобы не приходилось писать один и тот же код по многу раз, а не для того чтобы нарисовать красивую иерархию классов. Если ты замечаешь, что в программе много одинаковых кусков, то возможно имеет смысл нарисовать виртуальный метод или шаблон. Если ты можешь обосновать какого упрощения кода ты добился своим наследованием, то вперед. Иначе, скорее всего, нет смысла использовать ООП вообще.

В реальной жизни данные сериализуют в ключ=значение, csv, xml или json, а если нужен двоичный формат, то ProtoBuf или ASN.1.

Re: Полнофункциональная система тестирования

angrystrike » 28 июл 2017, 11:09

Долго думал, как реализовать эту задачу, ну вроде что-то надумал:

[CENTER]Базовый класс:
protected: key, FileName;
public:
save();
get();
delete();[/CENTER]
Остальные классы(классы юзера, категории, вопроса, вариантов ответа и отвева пользователя) от него наследуются:

Как я собрался реализовывать эти классы на примере класса юзер:

class user : BE
key = user_id;
FileName = users.txt
int _userId;
Role _role;
string _login;
int _pw;
string _addr;
size_t _phone;


Смотрится рационально(по крайней мере я так думаю ), но дайте какие нибудь советы по самой реализации и какую структуру данных стоит использовать для хранения в файле, последующем считывании?

Вернуться к началу