• ベストアンサー

文字列を判断して処理をする書き方

2バイトの文字列の中身によって違う処理をするプログラムを作成しています。 数値ならば、 switch(no){ case 10: 処理1 break; case 20 処理2 break; ・ ・ ・ } と書けるのですが、文字列だと if(strncmp(no,"10",2) == 0){ <処理1> }else if(strncmp(no,"20",2) == 0){ <処理2> }else if ・ ・ ・ } というような書き方しか分かりません。数値同様にswitch文できれいに書くような方法はありませんでしょうか? もしくはこうすればスマートに書けるというようなものがあればお教えください。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.5

移植性をあきらめるならば, case'10'と 書いて動くようにswitch文を工夫すればよいです. i386なら,これで動くはず. switch(( no[1]&0xFF) | (no[0]<<8)&0xFF00) { case '10': ... bigndianのSokaris/sparcでもこれで動きます. メインフレームのCコンパイラの中には, switch(( ( no[0]<<24)&0xFF000000) | (no[1]<<16)&0xFF0000) { case '10': ... でうごく変な奴も居ますが. あと,文字定数の中に複数文字入れるとコンパイラがwarningを出すと思います. さもなくば, #define char2short(a,b) (( b&0xFF) | (a<<8)&0xFF00) switch(char2short( no[0],no[1]) ){ case char2short('1', '0'): ..... case char2short('2', '0'): ..... てな書き方もあり得ますね. 複数文字定数を使うよりこちらの方が行儀がいいとも言えます.

KXWonderful
質問者

お礼

2番目のやり方が一番良いと思いました。ありがとうございました。

その他の回答 (7)

  • passepied
  • ベストアンサー率50% (18/36)
回答No.8

文字列が数字だけと決まっているのならばatoiとか boost::lexical_cast(C++の場合)などで数値に返還してからswitchすればよいと思います。 数字だけじゃない場合はだめなので自信なしです。

KXWonderful
質問者

お礼

#5のやり方でいこうと思います。ありがとうございました。

回答No.7

マクロによるものなので、プロジェクト内で使用するのはお勧めしませんが、こんな方法もあります。 >> #include <stdio.h> #include <string.h> #define strswitch(s) { char* __s__ = s; if (0) #define strcase(t) } else if (strcmp(t, __s__) == 0) { #define strdefault } else #define strbreak int main() { char s[BUFSIZ]; while (fgets(s, BUFSIZ, stdin)) { s[strlen(s) - 1] = '\0'; strswitch(s) { strcase("12") printf("12OK\n"); strbreak; strcase("34") printf("34OK\n"); strbreak; strcase("56") printf("56OK\n"); strbreak; strdefault printf("defaultOK\n"); strbreak; } } } <<

KXWonderful
質問者

お礼

参考になりました。ありがとうございました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.6

2バイトと分かっているのであれば、#5の方が提案されている > #define char2short(a,b) (( b&0xFF) | (a<<8)&0xFF00) > switch(char2short( no[0],no[1]) ){ > > case char2short('1', '0'): ..... > case char2short('2', '0'): ..... という書き方が一番よいと思います。 ただし移植性と安全性を考慮するなら、もう一工夫して、 #include <limits.h> #define char2word(a,b) ((unsigned char)(b) | ((unsigned char)(a)<<CHAR_BIT)) とした方がよいでしょう。 (ただし、上記の書き方をしても、sizeof(char)==sizeof(int)の処理系では動作が未定義になります)

KXWonderful
質問者

お礼

私も#5のやり方が良いと思いました。ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

え~と, switch を捨ててしまうという方針もあるかと. 例えば, struct Item { char *name; void (*op)(const char *name); }; という構造体を用意して, その配列を Item tbl[] = { { "10", func1 }, { "20", func2 }, ..., { NULL, NULL } }; と作って, Item *p; for (p = tbl; p->name != NULL; ++p) { if (!strcmp(no, p->name)) { break; } } if (p->name) { p->op(p->name); } のようにしてしまう手もある. 無名関数が使えれば (ある意味) 完璧なんだけど.

KXWonderful
質問者

お礼

返事がおそくなり申し訳ございません。参考になりました。

  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.3

検索したい文字列の長さが固定で,4バイト(intのバイト長)以下なら,switch文でできなくもないです.2バイト固定長だとすると. switch(( no[0]&0xFF) | (no[1]<<8)&0xFF00) { case '10': ... case '20': ... } '20'と言う書き方はバイトオーダーの問題が生じるので,アスキーコード表を引いて case 0x3230 : とするほうがいいかもしれませんが. 読みにくいプログラムになるので,後の保守のためにコメントを適切に入れておく必要があります.

KXWonderful
質問者

お礼

ありがとうございます。 case '20':というふうに書けるならば望みどおりなのですが、case 0x320x30という記述をしなければならないのなら確かに少し観にくいですね。とにかくnoが”10”ならば処理1、”20”ならば処理2っていうのが観てわかりやすい書き方を考えています。どうしてもif文で条件にstrncmpとかの式を書くと観にくいので。

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.2

文字列のテーブルを検索すればできます。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> #include <string.h> int main(void) { char buf[BUFSIZ]; char *index[] = {"ab", "cd", "ef", NULL}; int i; fprintf(stderr, "二文字入力してね >> "); fgets(buf, BUFSIZ, stdin); for (i = 0; index[i] != NULL; i++) { if (strncmp(buf, index[i], 2) == 0) { break; } } switch (i) { case 0: printf("abです。\n"); break; case 1: printf("cdです。\n"); break; case 2: printf("edです。\n"); break; default: printf("その他です。\n"); } return 0; }

KXWonderful
質問者

お礼

ありがとうございます。 確かにswitch文でかけますが、判断する2byte文字列を追加する場合に、indexとswitch文を両方メンテしなければならなので、少し使いにくいと思いました。

  • ttyp03
  • ベストアンサー率28% (277/960)
回答No.1

C言語はswitch文に文字列を指定することはできません。 従って質問者さまのようにif文でやることになります。

KXWonderful
質問者

お礼

ありがとうございます。 if~else ifとかを使って書くと観にくいので、観やすい書き方を探しています。

関連するQ&A