Как уменьшить переключатель в операторе switch?


9

Поэтому я делаю метод для создания линии приветствия на основе двух человек из базы данных.

Существует четыре параметра: два имени ( name1и name2) и два пола ( genderи gender2).

Для каждой гендерной комбинации у меня есть разные результаты.

Например: если пол 1 M(мужчина) и пол 2 также M, результат должен быть примерно таким:

Dear Sir name1 and Sir name2,

На данный момент мой переключатель выглядит так:

switch(gender1){
    case 'M':
        switch(gender2){
            case 'M': printf("Dear Sir %s and Sir %s", name1, name2); break;
            case 'W': printf("Dear Sir %s and Madame %s", name1, name2); break;
            case 'R': ...
        }
        break;
    case 'W':
        switch(gender2){
            case 'M': printf("Dear Madame %s and Sir %s", name1, name2); break
            case 'W': printf("Dear Madame %s and Madame %s", name1, name2); break;
            case 'R': ...
        }
        break;
    case ...etc.
}

Обратите внимание, что у меня есть несколько вариантов пола, например, 'R'for "Dear Relation"и некоторые другие, которые у меня нет времени для перевода.

Как я могу уменьшить этот оператор двойного переключения?

Ввод второго переключателя в метод не является вариантом, потому что есть также случай, когда оба имени совпадают, и затем выходные данные должны быть объединены следующим образом: "Dear Sir and Madame name1,"



1
Если ваш язык это позволяет, включите выражение, которое варьируется в зависимости от обоих значений, например gender1+gender2.
Килиан Фот

3
С другой стороны, женский титул, который можно использовать здесь, - Madamнет Madame. Madameэто французская форма.
rojomoke

3
Немного ненужный, но тот факт, что ваша переменная «пол» может быть «мужской», «женский» или «отношение», немного тревожит ...
Пэдди

4
«Обратите внимание, что у меня есть несколько вариантов пола» Ну, это, безусловно, в моде в эти дни ...
Гонки Легкости на орбите

Ответы:


32

Добавьте заголовок к параметрам printf:

char* title1;
switch(gender1){
    case 'M':
        title1 = "Sir";
        break;
    case 'W':
       title1 = "Madam";
        break;
    case ...etc.
}
char* title2;
switch(gender2){
    case 'M':
        title2 = "Sir";
        break;
    case 'W':
       title2 = "Madam";
        break;
    case ...etc.
}
printf("Dear %s %s and %s %s", title1, name1, title2, name2);

Вы можете извлечь переключатель для его собственной функции для повторного использования и компактности.


1
Это иногда работает, иногда нет ...
Дедупликатор

4
@Deduplicator Делайте это по умолчанию и обрабатывайте исключительные случаи отдельно.
Val

17
... и сделать это функцией, genderToTitleчтобы вам не пришлось повторять это? (Или используйте петлю)
Берги

18

Радикальное решение: позвольте пользователю указать свой собственный заголовок (из предопределенного списка, который вы предоставляете).

Ваше решение (если смотреть глазами англичан) кажется только для лордов («сэр») и дам; большинство мужчин будут называться «мистер», большинство женщин - «мисс», «миссис» или «мисс», в зависимости от их семейного положения и личных мнений. Тогда есть целый ряд других почетных званий, основанных на профессиональных позициях - «Доктора», «Профессора», «Преподобные» и даже, если вы действительно оптимистично настроены по поводу вашего сайта, «Святость»!

Более простое решение: вам нужна [одна] функция, чтобы перевести «пол» в почетный. Запишите это один раз и назовите это для обоих людей:

printf("Dear %s %s and %s %s" 
   , getTitle( gender1 ), name1 
   , getTitle( gender2 ), name2 
   ) ; 

Проблема здесь: я не имею никакого контроля над базой данных вообще. но спасибо за вашу дополнительную информацию, ценю это :)
moffeltje

8
Dear Sirкак форма обращения вполне приемлема для всех мужчин. Я согласен, что в качестве титула сэр (как в Sir Phill) должен быть ограничен рыцарями (не лордами), но это другой вопрос.
rojomoke

1
Я не понимаю, как это потребует доступа к базе данных. Для меня это самый чистый способ сделать это. Есть и другие хорошие сокращения переключателей, но это самая чистая замена, а также хорошая модуляция логики.
Дан

4
@rojomoke Нет, это не другое дело. Этот вопрос касается «Уважаемый сэр (впишите имя здесь)», а не просто «Дорогой сэр». «Милостивый (вставить имя здесь)» в использовании «сэр» в качестве названия.
hvd

Страница регистрации часто летающих пассажиров BA, возможно, около 2003 года, имела «его святость» в выпадающем списке названий. Все еще делает для всех, что я знаю. Я помню, потому что выпадающий список был настолько длинным, что сломал переносной браузер, который мы интегрировали. Я бы порекомендовал свободное поле, за исключением того, что Б., в частности, вероятно, консультируется с Дебреттом и знает несколько форм каждого заголовка для разных контекстов (как минимум, разные адреса конвертов и приветствия)
Стив Джессоп

9

Названия действительно принадлежат базе данных, но вы заявили, что не можете это контролировать. Вы не указали языковой тег, но синтаксис в семействе C, так что это будет псевдокод, почти C ++:

map<string, string> titles;
titles.emplace("M", "Sir");
titles.emplace("F", "Madam");

cout << "Dear " << titles[gender1] << " " << name1 << " and "
     << titles[gender2] << " " << name2 << endl;

Преимущество этого заключается в том, что вы скрываете логику выбора в структуре данных, а не в структуре кода: это похоже на делегирование в базу данных и является более гибким. Если вы храните эту карту как статическую константу где-то, вы можете почти использовать ее как базу данных: она становится единой структурой для обновления, которая может использоваться во многих местах кода без необходимости писать больше кода.



Это может быть хорошей идеей , чтобы пойти с C ++ 11 инициализатора синтаксис и делает его static const: static const map<string, string> titles{make_pair("M", "Sir"), make_pair("F", "Madam")};. Ну, можно оставить constвне, если изменение должно быть разрешено.
Дедупликатор

@Deduplicator определенно, есть лучший способ. Я собирался сделать это для простоты, поскольку здесь нет языкового тега, но он выглядит как C ++. Но вы правы, предполагая, что C ++ 11.

3

ответ ratchet freak - хорошая идея, если все предложения имеют одинаковую структуру, но с двумя вставками, каждое из которых зависит только от gender1соответствующего gender2.

Ответ Фила У., пожалуй, самый гибкий, поскольку он позволяет явно контролировать приветствие, хотя он совершенно прав, это радикальное изменение. Вы можете не иметь данных в этой форме.

Ответ Килиана Фота, вероятно, является наилучшим для заданного вопроса, хотя он зависит от включения строки, что может быть невозможным или, по крайней мере, более дорогим.

Уточнение ответа Килиана заключается в вычислении одного значения из обоих входов и включении этого:

// Using a macro in C for readability. C++ would use a constexpr function
#define COMBINE(a, b) ((a<<CHAR_BIT)+b)

switch( COMBINE(gender1, gender2)) {
  case COMBINE('M', 'M'): 
    print "Dear Sirs";
    break;
  case COMBINE('M', 'F'): 
  case COMBINE('F', 'M'): 
    print "Dear Sir and Madam";
    break;
  ...
#undef COMBINE

Конечно, поскольку вы получаете все четыре входных данных (2 имени и 2 пола) из базы данных, добавление еще одной таблицы и присоединение к ней для получения правильного приветствия, вероятно, будет более гибким и, возможно, более простым, чем описанное выше.


2

Если ваш язык позволяет вам это сделать, вы можете написать

switch(gender1+gender2) {
  case "MM": 
    print "Dear Sirs";
    break;
  case "MF": 
  case "FM":
    print "Dear Sir and Madam";
    break;
  ...

Это не обязательно лучше, чем ваша версия, так как дублирование сохраняется, но оно позволяет избежать вложенности switch.


5
Если вы сделаете это, ради любви кексам поместите это в массив или что-то еще и избавьтесь от переключателя .... salutation ['MM'] = "Уважаемые господа"; salutation ['MF'] = "Дорогая мадам и сэр"; requiredSalutation = приветствие [пол1 + пол2];
JDT


Как это назвать, зависит от языка, но в основном это набор ключей и значений, да.
JDT

1
В этом есть небольшое уточнение, которое работает практически на любом языке: вычислить одно целое число из обоих символов ввода и включить его, а не строку.
Дедупликатор

0

Обычно вы хотели бы, чтобы подобные строки пользовательского интерфейса извлекались из таблицы строк, а не жестко кодировались в исходном коде для локализации и простоты обновления. Поэтому подход, который я бы выбрал, состоял бы в том, чтобы использовать входные данные для создания ключа поиска, что-то вроде:

var lookupKey = "SALUTATION_" + gender1 + "_" + gender2;
var format = GetLocalizedString(lookupKey);
printf(format, name1, name2);

Другие предложения о разрешении пользователям выбирать свои собственные названия действительны, если у вас есть возможность получить эту информацию. Я бы все еще использовал поиск таблицы строк в решении.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.