На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Как создать фунцию с неопределенным количеством параметров
    Здравствуйте!
    Подскажите, пожалуйста, как сделать чтобы в функцию можно было передоват раное колличество параметров, в данном случае, типа bool?
    Например, в эту функцию нужно передать, в одном случае, MySQLConnection& db, bool& backToMain и string PerfSearchBy, в друм случаеMySQLConnection& db, bool& backToMain, bool& searchMenu, bool& BackAgeSearchMenu, string PerfSearchBy.
    ExpandedWrap disabled
      bool handleSearch(MySQLConnection& db, bool& backToMain, bool& searchMenu, bool& BackAgeSearchMenu, string PerfSearchBy)
      Ну... по-разному можно. Например, разместив все bool в конце и предусмотрев для них значения по умолчанию. Передаваться будут все, но передавать необходимо будет только нужные. Или сформировав пакет параметров через эллипсис, можно в Плюсовом стиле, можно (в Плюсовом проекте не рекомендуется) в Cишном. Можно банально перегрузить функцию.
      Но мне кажется, ты неверно понимаешь задачу, возложив на одну функцию настолько архитектурно разный функционал. Функции придётся как-то ветвиться между вариантами, и коли каждый параметр обрабатывается отдельно, ты потеряешь в общности, несмотря на то, что собираешься добиться противоположного.
        Тут нормально расписано, даже с примерами.
        https://learn.microsoft.com/ru-ru/cpp/c-run...t?view=msvc-170
          DDim1000, тут я тебя немного огорчу - С++ язык программирования достаточно древний и архаичный, который обязан тащить за собой артефакты достаточно древних решений. Как-то переменное число аргументов функций. Но в современных, более адекватных языках программирования, прекрасных и просто замечательно-отличных :lol: (например Dart) , это решается на раз-два простым его синтаксисом - "именованными переменными". В С++ такого до сих пор нет... Пичялька :'(

          Но в С++ есть возможности:

          1) std::map - хранит "словарь" значений
          2) std::any - может хранить любое значение copy constructible типа

          Есть возможность скрестить ужа и ежа =)
            Вот как здесь лучше сделать? У меня выходит ошибка: слишком мало аргументов в вызове функции

            Функция.
            ExpandedWrap disabled
              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;        
                  }
              };


            Вызов функции.
            ExpandedWrap disabled
              // ...
                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;
                            }
              // ...
              Ну тебе ж дали мануал. Cшный, правда. На ещё Плюсовый в довесок
              ExpandedWrap disabled
                #include <array>
                 
                bool handleSearch(MySQLConnection& db, string PerfSearchBy, auto ...bools)
                {
                  std::array<bool, sizeof...(bools)> values{bools...};
                /* ... */
                }
                А прямо обязательно ссылками на bool надо? Просто битовая карта не подойдет? Обычно забор из флагов никто не делает. А если еще пару-тройку флагов потребуется?
                Ты бы лучше свою задумку в целом описал. А то она какая-то противоречивая. Если у тебя функция с разным количеством аргументов имеет одно и то же поведение, то какой-то аргумент явно лишний. В ином случае напрашивается перегрузка (может быть с выносом какой-то общей части кода во вспомогательную функцию). Все иные попытки, включая использование variadic templates, приведут к такому же эффекту: тебе надо будет в любом случае проверить количество аргументов в пакете. Сделать это не сложно, но по сути ты неявно "изобретешь" старую, добрую перегрузку функции.

                Добавлено
                Посмотрел по диагонали твою handleSearch: тебе проще сделать две отдельный функции handleSearchByAge и handleSearchByName. Тогда последний параметр и не нужен будет. У тебя по сути попытка склеить две функции в одну. Или это цель лабораторной работы такая? Говори уж как есть :)
                Сообщение отредактировано: shm -
                  Цитата shm @
                  Ты бы лучше свою задумку в целом описал.
                  Я с этого начал
                    Цитата DDim1000 @
                    Подскажите, пожалуйста, как сделать чтобы в функцию можно было передоват раное колличество параметров, в данном случае, типа bool?

                    Для этого можно передавать в функцию один параметр - указатель на структуру.
                    В которой можно разместить потенциально полезные параметры и указать
                    используемые в конкретном вызове. Это Си шный приём.

                    Можно в качестве параметра передавать указатель на интерфейс.
                    С имеющимся у него методом, например, "work".
                    При вызове с конкретной реализацией произойдёт использование
                    заданного набора параметров.
                    По всей вероятности для решения проблемы таким способом
                    можно использовать паттерн "посетитель".
                    Сообщение отредактировано: ЫукпШ -
                    1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0385 ]   [ 15 queries used ]   [ Generated: 3.11.25, 04:14 GMT ]