Как создать фунцию с неопределенным количеством параметров
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.0] |
|
|
Как создать фунцию с неопределенным количеством параметров
|
|
|
|
|
Здравствуйте!
Подскажите, пожалуйста, как сделать чтобы в функцию можно было передоват раное колличество параметров, в данном случае, типа bool? Например, в эту функцию нужно передать, в одном случае, MySQLConnection& db, bool& backToMain и string PerfSearchBy, в друм случаеMySQLConnection& db, bool& backToMain, bool& searchMenu, bool& BackAgeSearchMenu, string PerfSearchBy. ![]() ![]() bool handleSearch(MySQLConnection& db, bool& backToMain, bool& searchMenu, bool& BackAgeSearchMenu, string PerfSearchBy) |
|
Сообщ.
#2
,
|
|
|
|
Ну... по-разному можно. Например, разместив все bool в конце и предусмотрев для них значения по умолчанию. Передаваться будут все, но передавать необходимо будет только нужные. Или сформировав пакет параметров через эллипсис, можно в Плюсовом стиле, можно (в Плюсовом проекте не рекомендуется) в Cишном. Можно банально перегрузить функцию.
Но мне кажется, ты неверно понимаешь задачу, возложив на одну функцию настолько архитектурно разный функционал. Функции придётся как-то ветвиться между вариантами, и коли каждый параметр обрабатывается отдельно, ты потеряешь в общности, несмотря на то, что собираешься добиться противоположного. |
|
Сообщ.
#3
,
|
|
|
|
Тут нормально расписано, даже с примерами.
https://learn.microsoft.com/ru-ru/cpp/c-run...t?view=msvc-170 |
|
Сообщ.
#4
,
|
|
|
|
DDim1000, тут я тебя немного огорчу - С++ язык программирования достаточно древний и архаичный, который обязан тащить за собой артефакты достаточно древних решений. Как-то переменное число аргументов функций. Но в современных, более адекватных языках программирования, прекрасных и просто замечательно-отличных
(например Dart) , это решается на раз-два простым его синтаксисом - "именованными переменными". В С++ такого до сих пор нет... Пичялька Но в С++ есть возможности: 1) std::map - хранит "словарь" значений 2) std::any - может хранить любое значение copy constructible типа Есть возможность скрестить ужа и ежа =) |
|
Сообщ.
#5
,
|
|
|
|
Вот как здесь лучше сделать? У меня выходит ошибка: слишком мало аргументов в вызове функции
Функция. ![]() ![]() bool handleSearch(MySQLConnection& db, bool& backToMain, bool& searchMenu, bool& BackAgeSearchMenu, string PerfSearchBy) { // PerfSearchBy - Perform a search by ... (Выполнить поиск по ...) string name; if (PerfSearchBy == "name") { system("cls"); cout << u8"\n=== ПОИСК ПО ИМЕНИ ===" << endl; while (true) { cout << u8"Введите имя: "; // Очищаем буфер только если есть лишние символы if (cin.rdbuf()->in_avail() > 0) { cin.ignore(numeric_limits<streamsize>::max(), '\n'); } getline(cin, name); // Убираем пробелы в начале и конце size_t start = name.find_first_not_of(" \t"); if (start == string::npos) { cout << u8"Вы не ввели имя для поиска.\n"; continue; } size_t end = name.find_last_not_of(" \t"); name = name.substr(start, end - start + 1); // Проверка на минимальную длину if (name.length() < 2) { cout << u8"Имя должно содержать минимум 2 символа!\n"; continue; } // перед формированием SQL-запросом меняем кодировку переменной name на utf8 name = cp866_to_utf8(name); // Безопасная проверка существования записей string condition = "name LIKE ?"; std::vector<std::string> params = { "%" + name + "%" }; // recordCount - кол-во записей int recordCount = db.checkRecordsExistSafe(condition, params); if (recordCount < 1) { // Обработка ошибки if (recordCount == 0) { cout << u8"❌ Записей с именем '" << name << u8"' не найдено!" << endl; cout << u8"📊 Попробуйте:" << endl; cout << u8" • Проверить правильность написания" << endl; cout << u8" • Использовать часть имени" << endl; cout << u8" • Поискать по фамилии или отчеству" << endl; } else { cout << u8"❌ Ошибка при поиске в базе данных!"; } // Меню дальнейших действий int continueChoice = showContinueMenu("name"); switch (continueChoice) { case 1: { // Продолжить поиск system("cls"); cout << u8"\n=== ПОИСК ПО ИМЕНИ ===" << endl; continue; } case 2: // Вернуться в меню поиска return true; case 3: // Вернуться в меню учащихся searchMenu = true; return true; case 4: // Вернуться в главное меню backToMain = true; searchMenu = true; return true; } } else { cout << u8"✅ Найдено записей: " << recordCount << endl; cout << u8"🔍 Результаты поиска по имени '" << name << "':" << endl; // Выполняем запрос и выводим результаты db.executeQuery("SELECT _group, name, sex, age, teleg_id, teleg_nickname FROM learners WHERE name LIKE '%" + name + "%' ORDER BY _group, name"); cout << "\n" << std::string(50, '=') << endl; // Меню дальнейших действий int continueChoice = showContinueMenu("name"); switch (continueChoice) { case 1: { // system("cls"); cout << u8"\n=== ПОИСК ПО ИМЕНИ ===" << endl; continue; // Продолжить поиск } case 2: return true; // Вернуться в меню поиска case 3: backToMain = true; return true; // Вернуться в меню учащихся case 4: // Вернуться в главное меню backToMain = true; searchMenu = true; return true; } } } return true; } if (PerfSearchBy == "age") { int age; while(1) { system("cls"); cout << u8"\n=== ПОИСК ПО КОНКРЕТНОМУ ВОЗРАСТУ ===" << endl; while (!getValidatedAge(u8"Введите возраст для поиска: ", age)) { // getValidatedAge - Функция для проверки возраста на валидность cout << u8"❌ Ошибка! Введите корректный возраст." << endl; } // Проверка валидности возраста if (age < 1 || age > 100) { cout << u8"❌ Возраст должен быть от 1 до 100 лет!" << endl; continue; } // Проверяем наличие записей string condition = "age = ?"; std::vector<std::string> params = { to_string(age) }; if (!db.checkRecordsExistSafe(condition, params)) { cout << u8"❌ Учащихся в возрасте " << age << u8" лет не найдено!" << endl; // Меню дальнейших действий int continueChoice = showContinueMenu("age"); switch (continueChoice) { case 1: { continue; // Продолжить поиск } case 2: return true; // Вернуться в меню поиска "Поиск по возрасту" case 3: BackAgeSearchMenu = true; case 4: backToMain = true; return true; // Вернуться в главное меню case 5: // Вернуться в главное меню backToMain = true; searchMenu = true; return true; } } // Выполняем поиск int count = db.checkRecordsExistSafe(condition, params); cout << u8"✅ Найдено учащихся в возрасте " << age << u8" лет: " << count << endl; cout << u8"🔍 Результаты поиска:" << endl; // Выполняем запрос и выводим результаты db.executeQuery("SELECT _group, name, sex, age, teleg_id, teleg_nickname FROM learners WHERE age = " + to_string(age) + " ORDER BY name"); // Меню дальнейших действий int continueChoice = showContinueMenu("age"); switch (continueChoice) { case 1: { continue; // Продолжить поиск } case 2: return true; // Вернуться в меню поиска case 3: backToMain = true; return true; // Вернуться в главное меню case 4: // Вернуться в главное меню backToMain = true; searchMenu = true; return true; } } return true; } }; Вызов функции. ![]() ![]() // ... case 4: { system("cls"); // Подменю "Поиск" bool BackSearchMenu = false; while (!BackSearchMenu) { system("cls"); cout << u8"\n=== ПОИСК ===" << endl; cout << u8"1. Поиск по имени" << endl; cout << u8"2. Поиск по возрасту" << endl; cout << u8"3. Поиск по Telegram" << endl; cout << u8"4. Вернуться к меню \"Работа с учащимися\"" << endl; cout << u8"5. Назад в главное меню" << endl; cout << u8"Выберите пункт: "; int searchMethod; if (cin >> searchMethod) { switch (searchMethod) { case 1: { handleSearch(db, backToMain, BackSearchMenu, "name"); break; } case 2: { bool BackAgeSearchMenu = false; while (!BackAgeSearchMenu) { system("cls"); cout << u8"\n=== ПОИСК ПО ВОЗРАСТУ ===" << endl; cout << u8"1. Поиск по указанному возрасту" << endl; cout << u8"2. Поиск по возрасту в диапазоне лет (“От” - ”До”)" << endl; cout << u8"Выберите пункт: "; int AgeSearchMethod; if (cin >> AgeSearchMethod) { switch (AgeSearchMethod) { case 1: { handleSearch(db, backToMain, BackSearchMenu, BackAgeSearchMenu,"age"); break; } default: cout << u8"Неверный пункт меню!" << endl; break; } } else { cout << u8"Ошибка ввода! Введите число." << endl; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); } } break; } // ... |
|
Сообщ.
#6
,
|
|
|
|
Ну тебе ж дали мануал. Cшный, правда. На ещё Плюсовый в довесок
![]() ![]() #include <array> bool handleSearch(MySQLConnection& db, string PerfSearchBy, auto ...bools) { std::array<bool, sizeof...(bools)> values{bools...}; /* ... */ } |
|
Сообщ.
#7
,
|
|
|
|
А прямо обязательно ссылками на bool надо? Просто битовая карта не подойдет? Обычно забор из флагов никто не делает. А если еще пару-тройку флагов потребуется?
Ты бы лучше свою задумку в целом описал. А то она какая-то противоречивая. Если у тебя функция с разным количеством аргументов имеет одно и то же поведение, то какой-то аргумент явно лишний. В ином случае напрашивается перегрузка (может быть с выносом какой-то общей части кода во вспомогательную функцию). Все иные попытки, включая использование variadic templates, приведут к такому же эффекту: тебе надо будет в любом случае проверить количество аргументов в пакете. Сделать это не сложно, но по сути ты неявно "изобретешь" старую, добрую перегрузку функции. Добавлено Посмотрел по диагонали твою handleSearch: тебе проще сделать две отдельный функции handleSearchByAge и handleSearchByName. Тогда последний параметр и не нужен будет. У тебя по сути попытка склеить две функции в одну. Или это цель лабораторной работы такая? Говори уж как есть |
|
Сообщ.
#8
,
|
|
|
|
Цитата shm @ Я с этого начал Ты бы лучше свою задумку в целом описал. |
|
Сообщ.
#9
,
|
|
|
|
Цитата DDim1000 @ Подскажите, пожалуйста, как сделать чтобы в функцию можно было передоват раное колличество параметров, в данном случае, типа bool? Для этого можно передавать в функцию один параметр - указатель на структуру. В которой можно разместить потенциально полезные параметры и указать используемые в конкретном вызове. Это Си шный приём. Можно в качестве параметра передавать указатель на интерфейс. С имеющимся у него методом, например, "work". При вызове с конкретной реализацией произойдёт использование заданного набора параметров. По всей вероятности для решения проблемы таким способом можно использовать паттерн "посетитель". |