web-dev-qa-db-ja.com

switchステートメントでswitchを減らす方法は?

データベースから2人に基づいて挨拶文を作成する方法を作成しています。

4つのパラメーターがあります。2つの名前(name1およびname2)および2つの性別(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'"Dear Relation"のように複数の性別オプションがあること、および翻訳する時間のないその他のオプションがあることに注意してください。

この二重のswitchステートメントをどのように減らすことができますか?

メソッドに2番目のスイッチを配置することはオプションではありません。両方の名前が同じで、出力を次のように組み合わせる必要がある場合もあります:"Dear Sir and Madame name1,"

9
moffeltje

タイトルを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);

スイッチを独自の機能に抽出して、再利用性とコンパクトさを実現できます。

32
ratchet freak

根本的な解決策:ユーザーがownタイトルを指定できるようにします(指定した定義済みリストから)。

あなたの解決策(英語の目で見た場合)は、領主(「サー」)と女性にのみ対応しているように見えます。ほとんどの男性は「夫人」、ほとんどの女性は「夫婦」、「夫人」または「夫婦」として扱われ、婚姻状況や個人的な意見に応じて異なります。それから、専門的な地位に基づく他の敬語がたくさんあります-「医師」、「教授」、「牧師」、そしてあなたが感じているなら本当に楽観的なサイト、「神聖さ」!

より簡単な解決策:「性別」を敬語に変換するには、[単一の]関数が必要です。一度コードを書いて、両方の人に電話してください:

printf("Dear %s %s and %s %s" 
   , getTitle( gender1 ), name1 
   , getTitle( gender2 ), name2 
   ) ; 
18
Phill W.

タイトルは実際にはデータベースに属していますが、これを制御することはできないと述べました。言語タグを指定していませんが、構文はCファミリに含まれているため、これはほぼC++の疑似コードになります。

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

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

これの利点は、コード構造ではなくデータ構造に選択ロジックを埋め込むことです。これは、データベースへの委任に似ており、より柔軟です。そのマップを静的定数としてどこかに保持すると、ほぼデータベースのように使用できます。これは、更新する単一の構造になり、コードの多くの場所で使用できます書き込みより多くのコード。

9
user22815

ラチェットフリークの答え は、文がすべて同じパターンであるが、2つのインセットがあり、それぞれがgender1それぞれgender2にのみ依存している場合、非常に良い考えです。

Phil W.の回答 は挨拶を明示的に制御できるため、おそらく最も柔軟な回答ですが、彼はまったく正しいので、根本的な変更です。その形式のデータがない可能性があります。

Kilian Fothの回答 は、質問されたとおりの質問におそらく最適ですが、文字列の切り替えに依存しているため、不可能であるか、少なくともコストが高くなる可能性があります。

キリアンの答えの改良点は、両方の入力から単一の値を計算し、それをオンにすることです。

// 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

もちろん、データベースから4つすべての入力(2つの名前と2つの性別)を取得しているので、別のテーブルを追加して適切な挨拶を得るために結合することは、おそらく上記よりも柔軟でおそらく簡単です。

3
Deduplicator

あなたの言語がそれを可能にするなら、あなたは書くことができます

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

重複があるため、バージョンよりもbetterである必要はありませんが、ネストされたswitchは回避されます。

2
Kilian Foth

ローカライズと更新を容易にするために、通常、このようなUI文字列は、ソースコードにハードコード化されているのではなく、文字列テーブルから取得する必要があります。したがって、私が取るアプローチは、入力を使用してルックアップキーを作成することです。

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

ユーザーが自分のタイトルを選択できるようにすることに関する他の提案は、その情報を入手する機会があれば有効です。ソリューションでは引き続き文字列テーブルルックアップを使用します。

0
bmm6o