Вот полный пример, который делает то, о чем я думаю, вы спросили.
Вещи, которые вы не просили, но в любом случае это делает:
- Он использует исключения для сообщения об ошибках формата файла данных, так что
GetModelForUser()
может просто вернуть объект (вместо логического или что-то в этом роде).
- Используется шаблонная функция для разбиения строки на поля. Это действительно сердце оригинального вопроса, и поэтому немного жаль, что это, возможно, слишком сложно. Но идея сделать ее шаблонной функцией заключается в том, что это разделяет задачи разделения строки на поля и выбора структуры данных для представления результата.
<pre>
/* Parses a file of user data.
* The data file is of this format:
* username:email-address:pincode
*
* The pincode field is actually one-way-encrypted with a secret salt
* in order to avoid catastrophic loss of customer data when the file
* or a backup tape is lost/leaked/compromised. However, this code
* simply treats it as an opaque value.
*
* Internationalisation: this code assumes that the data file is
* encoded in the execution character set, whatever that is. This
* means that updates to the file must first transcode the
* username/mail-address/pincode data into the execution character
* set.
*/</p>
<p>#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <iterator>
#include <exception></p>
<p>const char* MODEL_DATA_FILE_NAME = "test.txt";</p>
<p>// This stuff should really go in a header file.
class UserUnknown : public std::exception { };</p>
<p>class ModelDataIsMissing : public std::exception { };
class InvalidModelData : public std::exception { }; // base: don't throw this directly.
class ModelDataBlankLine : public InvalidModelData { };
class ModelDataEmptyUsername : public InvalidModelData { };
class ModelDataWrongNumberOfFields : public InvalidModelData { };</p>
<p>class UserModel {
std::string username_;
std::string email_address_;
std::string pincode_;</p>
<p>public:
UserModel(std::string username, std::string email_address, std::string pincode)
: username_(username), email_address_(email_address), pincode_(pincode) {
}
UserModel(const UserModel& other)
: username_(other.username_),
email_address_(other.email_address_),
pincode_(other.pincode_) {
}</p>
<pre><code>std::string GetUsername() const { return username_; }
std::string GetEmailAddress() const { return email_address_; }
std::string GetPincode() const { return pincode_; }
};
UserModel GetUserModelForUser (const std :: string & username)
throw (InvalidModelData, UserUnknown, ModelDataIsMissing);
// Этот материал является реализацией.
namespace {// использовать пустое пространство имен для модульности.
шаблон void SplitStringOnSeparator (
ввод std :: string, разделитель символов, вывод ForwardIterator)
{
std :: string :: const_iterator field_start, pos;
bool in_field = false;
for (pos = input.begin (); pos! = input.end (); ++ pos) {
if (! in_field) {
field_start = pos;
in_field = true;
}
if (* pos == разделитель) {
* output ++ = std :: string (field_start, pos);
in_field = false;
}
}
if (field_start! = input.begin ()) {
* output ++ = std :: string (field_start, pos);
}
}
}
// Возвращает экземпляр UserModel для указанного пользователя.
//
// Не вызывайте это более одного раза за вызов программы, потому что
// у вас получится квадратичная производительность. Вместо этого измените этот код
// вернуть карту от имени пользователя к данным модели.
UserModel GetUserModelForUser (const std :: string & username)
throw (InvalidModelData, UserUnknown, ModelDataIsMissing)
{
std :: string line;
std :: ifstream in (MODEL_DATA_FILE_NAME);
if (! in) {
throw ModelDataIsMissing ();
} * * Тысяча двадцать-один
while (std::getline(in, line)) {
std::vector<std::string> fields;
SplitStringOnSeparator(line, ':', std::back_inserter(fields));
if (fields.size() == 0) {
throw ModelDataBlankLine();
} else if (fields.size() != 3) {
throw ModelDataWrongNumberOfFields();
} else if (fields[0].empty()) {
throw ModelDataEmptyUsername();
} else if (fields[0] == username) {
return UserModel(fields[0], fields[1], fields[2]);
}
// We don't diagnose duplicate usernames in the file.
}
throw UserUnknown();
}
namespace {
Пример bool (const char * arg)
{
const std :: string username (arg);
пытаться
{
Мод UserModel (GetUserModelForUser (имя пользователя));
std :: cout << "Данные модели для" << username << ":"
<< "username =" << mod.GetUsername ()
<< ", адрес электронной почты =" << mod.GetEmailAddress ()
<< ", зашифрованный пин-код =" << mod.GetPincode ()
<< std :: endl;
вернуть истину;
}
catch (UserUnknown) {
std :: cerr << "Неизвестный пользователь" << username << std :: endl;
вернуть ложь;
}
}
} </p>
int main (int argc, char * argv [])
{
int i, returnval = 0;
для (i = 1; i
/ * Локальные переменные: /
/ c-file-style: "stroustrup" /
/ Конец: * /