I am a newbie in C++. I am doing a C++ sign up form where I keep all the user datas in a text file named user.txt with formats like
name|password|address|postal|phone
Each user record will occupy one line.
So my first question how can I do this nicely in C++
As for the reading part, my main problem is how to separate the data by splitting "|" then put the records in a user array. So when I do a login function I can loop through the array to match users.
My current code for reading is
string User::readUser(){
ifstream fin("user.txt");
string line;
while(getline(line,fin)){
string name, password, address; int postal, phone;//put the records into a 2 dimention array
开发者_高级运维 }
//return array
}
Check out this answer.
In your case, the fields will be appended to the vector<string> in order, so you can access them directly from it. First position would correspond to the name, second to the password and so on.
Here's an example:
// The elements should be in this order: name, password, address, postal, phone
vector<string> v = split(line, '|');
string name = v[0], password = v[1], address = v[2];
As for your second question, you could create a structure or class that describes the user:
struct User {
// Using type string for all fields for convenience.
string name, password, address, postal, phone;
User(string n, string pw, string a, string p, string ph): name(n),
password(pw),
address(a),
postal(p),
phone(ph) {}
};
vector<User> uv;
// ...
// Split string, create user instance and append it to the user list
vector<string> v = split(line, '|');
uv.push_back(User(v[0], v[1], v[2], v[3], v[4]));
To iterate over the User vector:
for (int i = 0; i < uv.size(); ++i) {
if (uv[i].name == "John") {
// Process John...
}
}
Some time ago I wrote an answer with a C++ sscanf replacement. It fits perfectly for your case:
std::vector<boost::any> user_data;
sscanf(line, "%s|%s|%s|%i|%i", user_data);
Now constructing a User (a struct like in Matheus Moreira's answer) is very simple:
User(boost::any_cast<std::string>(user_data[0]), // name
boost::any_cast<std::string>(user_data[1]), // password
boost::any_cast<std::string>(user_data[2]), // address
boost::any_cast<int>(user_data[3]), // postal
boost::any_cast<int>(user_data[4])); // phone
This requires boost's any and lexical_cast.
The obvious solution would be to use boost::regex on each line: this will do input format checking as well as separate out the fields. Something like:
while ( getline( line, fin ) ) {
static boost::regex const pattern(
"\\([^|]+\\)\\|\\([^|]+\\)|\\([^|]+\\)|\\([^|]+\\)|\\([^|]+\\)" );
boost::smatch match;
if ( !regex_match( line, match, pattern ) ) {
// Error handling...
} else {
// match[1] is name, match[2] is password, etc.
}
}
More complex matching patterns are possible, requiring e.g. postal and phone to be numeric. You could also easily modify it to allow leading and trailing white space as well.
加载中,请稍侯......
精彩评论