This might be a very basic c/c++ question, but I am really struggeling at it right now.
I have a struct that looks something like this:
struct connection_details {
const char *server, *user, *password, *database, *mysql_port, *ssh_port;
};
And I have the data in a seperate text file.
So I would like to write a function, that takes a pointer to the struct, to write each line of the text file to the corresponding variable of the struct.
void get_config(const std::string &config_path, connection_details *mysql) {
ifstream file(config_path);
string str;
getline(file, str);
mysql->user = str.c_str();
getline(file, str);
mysql->server = str.c_str();
getline(file, str);
mysql->database = str.c_str();
//...
file.close();
}
But now the char pointer points to a variable that no longer exists, and even if it still existed, every part of the struct would point to the same variabe, not the content it was supposed to be.
I know this is a rather basic question, but I came to the point where I don’t now what to google anymore, so every help is welcome.
>Solution :
If you want to store string data in a way that is kept around as long as the struct is alive, then std::string does exactly that. So, ideally, you should replace the const char* members of connection_details with std::string:
struct connection_details {
std::string server, user, password, database, mysql_port, ssh_port;
};
Conveniently, this also allows you to just getline() directly into the members:
void get_config(const std::string &config_path, connection_details *mysql) {
ifstream file(config_path);
getline(file, mysql->user);
getline(file, mysql->server);
getline(file, mysql->database);
// ...
// No need to .close(), it's implicit.
}
Then, you can use .c_str() wherever you would have used the const char*
// Assuming you can't change this...
void some_function(const char* str);
int main() {
connection_details details;
get_config("path/to_config.txt", &details);
// before:
//some_function(details.server);
// after:
some_function(details.server.c_str());
}
Edit: Now, if you have no control over connection_details, then you can still use std::string, but you just have to add a layer of indirection:
struct connection_details {
const char* server, user, password, database, mysql_port, ssh_port;
};
struct connection_details_data {
std::string server, user, password, database, mysql_port, ssh_port;
// Make it convertible into connection_details
operator connection_details() const {
return {
server.c_str(), user.c_str(), password.c_str(),
database.c_str(), mysql_port.c_str(), ssh_port.c_str()
};
}
};
void get_config(const std::string &config_path, connection_details *mysql) {
// ...
}
int main() {
connection_details_data details_data;
get_config("path/to_config.txt", &details_data);
// Make sure details_data outlives details!
connection_details details = details_data;
// ...
}