#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
using namespace std;
typedef unsigned long long uint64;
// Словарь, с которым работаем
map<string, uint64> dict;
// Вывод сообдения об ошибке
void err(const string & message)
{
cerr << "ERROR: " << message << "\n";
}
// Вывод обычного сообщения
void out(const string & str)
{
cout << str << "\n";
}
// Проверка, является си строка словом
// Считаем строку словом, если она содержит лишь символы A-Za-z
bool isWord(const string & str)
{
return find_if(str.begin(), str.end(), [](char c) { return !isalpha(c); }) == str.end();
}
// Является ли строка допустимым словом
// Т.е. не слишком длинным
bool isValidWord(const string & str)
{
return isWord(str) && str.length() <= 256;
}
// Сохранение словаря в файл
// Формат файла:
// тройки (L,W,V), где
// L - байт, содержащий длину слова(слова не более 256 символов)
// W - L байт - по байту на символ слова
// V - sizeof(unsigned long long) - 8 байт, содержащих значение, соответствующее слову
void save(const string & path)
{
ofstream file(path, ios::out | ios::binary | ios::trunc );
if (file.is_open())
{
for (const auto & pair : dict)
{
const string & key = pair.first;
unsigned char keyLen = key.length();
file.write(reinterpret_cast<const char *>(&keyLen), 1); // remember that key string is no more than 256 characters
file.write(key.data(), keyLen);
const uint64 & val = pair.second;
file.write(reinterpret_cast<const char *>(&val), sizeof(uint64));
}
file.close();
out("OK");
}
else
{
err("Unable to open file " + path + " for writing");
}
}
// Загрузка данных из файла
// Макрос проверки состояния файлового потока
#define CHECK_FS_GOOD(fs) if (!fs.good()) \
{ \
err("Bad file format"); \
fs.close(); \
return; \
}
void load(const string & path)
{
ifstream file(path, ios::in | ios::binary );
if (file.is_open())
{
vector<char> buf;
while (file.good())
{
unsigned char keyLen;
file.read(reinterpret_cast<char *>(&keyLen), 1);
// If EOF is after full data group it is OK.
if (file.eof())
{
break;
}
// But the other fails are not.
CHECK_FS_GOOD(file)
buf.reserve(keyLen+1); // one more character to a terminal symbol
file.read(buf.data(), keyLen);
CHECK_FS_GOOD(file)
buf[keyLen] = 0; // add a terminal symbol to the raw string data
string key(buf.data());
uint64 val;
file.read(reinterpret_cast<char *>(&val), sizeof(uint64));
CHECK_FS_GOOD(file)
//cout << "keyLen = " << (int)keyLen << "; key = " << key << "; val = " << val << "\n";
dict[key] = val;
}
file.close();
out("OK");
}
else
{
err("Unable to open file " + path + " for reading");
}
}
// Обработка команды
// Макрос проверки состояния строкового потока
#define CHECK_SS_GOOD(ss) if (!ss.good()) \
{ \
err("Invalid command"); \
return; \
}
// Макрос проверки строки
#define CHECK_WORD(word) if (!isValidWord(word)) \
{ \
err("String " + key + " is not valid"); \
return; \
}
// Преобразование символов строки в нижний регистр
void lowercase(string * str)
{
transform(str->begin(), str->end(), str->begin(), ::tolower);
}
void process(const string & command)
{
stringstream ss;
ss << command;
CHECK_SS_GOOD(ss)
string tok;
ss >> tok;
if (tok == "+")
{
CHECK_SS_GOOD(ss)
string key;
ss >> key;
// String validity check.
CHECK_WORD(key)
lowercase(&key);
CHECK_SS_GOOD(ss)
uint64 val;
ss >> val;
if (dict.count(key) == 0)
{
dict[key] = val;
out("OK");
}
else
{
out("Exist");
}
}
else if (tok == "-")
{
CHECK_SS_GOOD(ss)
string key;
ss >> key;
CHECK_WORD(key)
lowercase(&key);
if (dict.count(key) > 0)
{
dict.erase(key);
out("OK");
}
else
{
out("NoSuchWord");
}
}
else if (tok == "!")
{
CHECK_SS_GOOD(ss)
ss >> tok;
if (tok == "Save")
{
CHECK_SS_GOOD(ss)
string path;
ss >> path;
save(path);
}
else if (tok == "Load")
{
CHECK_SS_GOOD(ss)
string path;
ss >> path;
load(path);
}
else
{
err("Invalid command");
}
}
else if (isValidWord(tok))
{
lowercase(&tok);
if (dict.count(tok) > 0)
{
out("OK: " + dynamic_cast<std::ostringstream &>(std::ostringstream() << dict[tok]).str());
}
else
{
out("NoSuchWord");
}
}
else
{
err("Invalid command");
}
}
int main(int argc, char *argv[])
{
/*while (true)
{
string command;
getline(cin, command);
if (command == "exit") break;
process(command);
}*/
if (argc < 2)
{
cout << "Usage: my_cool_prog input_file" << endl;
return 1;
}
ifstream file(argv[1]);
if (file.is_open())
{
while (file.good())
{
string command;
getline(file, command);
process(command);
}
}
else
{
err("Unable to open file " + string(argv[1]) + " for reading");
}
return 0;
}
+ a 1
+ b 2
+ qwerty 512345678942
- b
qwerty
+ abc4 2
! Save database
- qwerty
qwerty
! Load database
qwerty
+ aBc 42
AbC
OK
OK
OK
OK
OK: 512345678942
ERROR: String abc4 is not valid
OK
OK
NoSuchWord
OK
OK: 512345678942
OK
OK: 42
Если Вы уже зарегистрированы на Портале - войдите в систему, если Вы еще не регистрировались - пройдите простую процедуру регистрации.