Можно ли изменять тип переменной к которой мы обращаемся у структуры в цикле?
struct stringTable {
string surname;
string name;
string patronymic;
int hash;
};
void seperation(string text, stringTable &personality){
for (int i = 0; i < text.size(); i++) {
bool skipSurname = false;
bool skipName = false;
if (text[i] != ' ' && !skipSurname) {
personality.surname += text[i];
}
if (text[i] == ' ') {
skipSurname = true;
continue;
}
if (text[i] != ' ' && skipSurname && !skipName) {
personality.name += text[i];
}
if (text[i] == ' ') {
skipName = true;
continue;
}
if (text[i] != ' ' && skipSurname && skipName) {
personality.patronymic += text[i];
}
}
};
В задании существует некоторая база данных, состоящая из таблицы, в строках которой находится ФИО, между словами стоит 1 пробел. Я считываю строку в string, а затем хочу заполнить собственную структуру на раздельные слова. Для этого я написал функцию seperation, которая кажется мне длинной из-за различных булевых переменных. Я задумался вопросом: "А возможно ли менять динамически тип переменной, к которой я хочу обращаться?" Т.е. я хотел, чтобы у меня существовал массив имен переменных в структуре, которым я мог пользоваться, чтобы менять их и обращаться к различным переменным. Если моя идея покажется непонятной, то я просто хотел бы увидеть более оптимизированный вариант заполнения моей структуры строкой.
Ответы (2 шт):
В C++ нету (до C++20, там ожидается) интроспекции, то есть, язык не способен "понимать", из каких полей состоит структура, или как-то по этим полям ходить циклом.
Имеются разные обходные пути для этого, которые используют макросы (boost) или специально написанный препроцессор (moc в Qt).
Еще один способ - избавиться от полей, написав что-то такое:
#define GET_PART(name, index) std::string& name() { return fio[index]; }
class FIO
{
std::vector<std::string> fio;
public:
FIO(const std::string& textToParse)
{
//возможно, это не самый оптимальный,
//зато короткий способ порезать по пробелам
std::istringstream iss(textToParse);
fio.insert(std::istream_iterator<std::string>{iss},
std::istream_iterator<std::string>());
fio.resize(3); //гарантировать, чтобы все три части ФИО были на месте
//и выкинуть лишнее
}
GET_PART(LastName , 0)
GET_PART(FirstName , 1)
GET_PART(MiddleName, 2)
};
#undef GET_PART
Массив имен сделать несложно - используя в качестве имен указатели, например -
string* arr[3] = {
&personality.surname,
&personality.name,
&personality.patronymic
};
Так что
void seperation(const string& text, stringTable &personality)
{
string* arr[3] = {
&personality.surname,
&personality.name,
&personality.patronymic
};
istringstream is(text);
for(int i = 0; i < 3; ++i) is >> *arr[i];
};
Или еще проще...
void seperation(const string& text, stringTable &personality)
{
istringstream is(text);
is >> personality.surname >> personality.name >> personality.patronymic;
};
Кстати, адекватно отработает отсутствие третьего (или даже второго с третьим) полей.
Только вот не понимаю, где у вас разные типы:
"А возможно ли менять динамически тип переменной, к которой я хочу обращаться?"