#c #file #object #fstream #stdstring
#c #файл #объект #fstream #stdstring
Вопрос:
У меня есть класс User с двумя атрибутами std::string . Когда я пытаюсь прочитать его из файла, я получил исключение из uxitility из строки 222: (*_Pnext)->_Myproxy = nullptr;
Это происходит после функции isUserInFile()
Некоторые моменты моего кода:
Class User {
protected:
std::string login;
std::string password;
public:
friend std::istreamamp;operator>>(std::istreamamp;in, User amp;obj) {
//std::cout << "Логин: "; //"Login: "
in >> obj.login;
//std::cout << "Пароль: "; //"Password: "
in >> obj.password;
return in;
}
friend std::ostreamamp;operator<<(std::ostreamamp;out, Useramp;obj) {
out << obj.login << " " << obj.password;
return out;
}
void encrypt() {
char key[3] = { 'K','E','Y' };
std::string buf = password;
for (int i = 0; i < buf.size(); i )
buf[i] = password[i] ^ key[i % (sizeof(key) / sizeof(char))];
password = buf;
//buf.clear();
}
bool isUserInFile() {
User user;
std::ifstream file;
file.open("Users.txt");
while (!file.eof() amp;amp; file.read((char*)amp;user, sizeof(User)))
if (login == user.login) {
file.close();
return true;
}
file.close();
return false;
}
};
bool registration() {
User user;
std::fstream file;
file.open("Users.txt", std::ios::in | std::ios::out | std::ios::app);
std::cout << "Регистрация:n"; //"Registration:n"
std::cin >> user;
user.encrypt();
if (!user.isUserInFile()) {
file.write((char*)amp;user, sizeof(User));
file.close();
return true;
}
std::cout << "Пользователь с данным логином уже существуетn"; //"User with this login already existsn"
file.close();
system("pause");
return false;
}
Комментарии:
1.
User
является классом, не являющимся членами POD. Вы не можете просто перенести его представление на диск и обратно. Вам либо нужен некоторый код сериализации (или, при нажатии, используйте что-то вродеchar
массивов вместоstd::strings
)2. Согласен. Ошибка здесь:
file.write((char*)amp;user, sizeof(User));
3. Вы можете найти это интересным: isocpp.org/wiki/faq/serialization
Ответ №1:
Комментарии пошли в правильном направлении, чтобы показать, в чем проблема. Но решение намного проще, у вас уже есть свои потоковые операторы, так что просто используйте их!
Для записи в файл вы можете использовать:
file << user << std::endl;
а затем для чтения вы просто:
file >> user;
Чтобы это продолжало работать, вам понадобятся некоторые вещи:
- Пользователь никогда не должен вводить пробелы в своем пароле.
- Вам необходимо убедиться, что запись и чтение всегда выполняются в одном и том же порядке.
В качестве альтернативы вы можете создать преобразование из string и в string в соответствии со строками:
static const char SEP1 = ' ', SEP2 = 'r';
friend std::string to_string(const Useramp; u)
{
std::string result = u.login SEP1 u.password SEP2;
return resu<
}
explicit User(std::string line)
{
size_t pos1 = s.find(SEP1);
size_t pos2 = s.find(SEP2, pos1);
login = s.substr(0, pos1);
password = s.substr(pos1 1, pos2-pos1);
}
Затем вы можете в своем основном вы можете прочитать блок данных и просто создать пользователя из него, в качестве альтернативы вы можете преобразовать пользователя в строку перед записью. Прелесть этого подхода в том, что вы выбираете разделители, и они стабильны между функциями.