• ベストアンサー

#defineの定数を文字列として読み込む

#define A "xxx" #define B "yyy" と定義しておいて scanf("%s", str) で読み込んだ文字列strが "xxx"だった場合、"yyy"だった場合のように分岐したいのですが このとき if(str == "xxx") のように中身を指定するのではなく if(str == AA) のように定数で分岐させることってできますか? 上記のままではできませんが、何か特別な関数とかでできるのでしょうか?

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

  • ベストアンサー
noname#144013
noname#144013
回答No.6

こんにちは。 やりたいことの解釈ですが、(※勘違いの場合はすみません。) 1)マクロの名前(定義名)が文字列として格納された文字列 str があるとする。  例)    #define A "xxx"  //マクロ名=A    char str[] = "A";   //"A"はマクロ名 2)上記の文字列 str を関数 func に渡す際に、マクロ名ではなくそのマクロで   定義された文字列を渡したい。  例)    func( str );    //←この場合     ↓    func( "xxx" );  //←として展開される ということで宜しいでしょうか? だとした場合、少し回りくどいやり方かもしれませんが、以下のような文字列 変換用のマクロを定義してみては如何でしょうか? ※基本的には、他の回答者の方と同じように strcmp関数 を使用します。 ■マクロ例 ============================== //文字列を定義したマクロ …※1 #define A "xxx" #define B "yyy" //引数を文字列として取得するマクロ #define GETSTR(x) #x //引数をマクロ名としてそのマクロで定義された文字列を取得するマクロ …※2 //注)<string.h>がインクルードされていることを前提とする #define STR2MAC(str) \ !strcmp(str,GETSTR(A))? A : \ !strcmp(str,GETSTR(B))? B : str ============================== 上記マクロを使用して、関数 func にマクロ名が格納された文字列 str を 渡す場合は、    func( STR2MAC( str ) ); のような記述になります。 前提として、※2のマクロ内でstrcmp関数を用いて文字列の照合を行って いますので、<string.h>のインクルードが必要になります。 また、※1の文字列を定義するマクロの種類(パターン)を増やす場合、 ※2のマクロの判定文もそれに合わせて増やす必要があります。 上記のマクロを使用したサンプルソースを下記に掲載致します。 注)エラー処理は行っていません。 ■サンプルソース ============================== #include <stdio.h> #include <string.h> //文字列を定義したマクロ #define A "xxx" #define B "yyy" //引数を文字列として取得するマクロ #define GETSTR(x) #x //引数をマクロ名としてそのマクロで定義された文字列を取得するマクロ //注)<string.h>がインクルードされていることを前提とする #define STR2MAC(str) \ !strcmp(str,GETSTR(A))? A : \ !strcmp(str,GETSTR(B))? B : str //プロトタイプ void funcHoge( const char *str ); int main(void) { char sArg[128]; printf( "A or B ?>" ); scanf( "%s", sArg ); printf( "string1: %s\n", sArg ); funcHoge( STR2MAC(sArg) ); return 0; } void funcHoge( const char *str ) { printf( "string2: %s\n", str ); } ============================== ■上記サンプルの実行結果 ≫実行その1≪ A or B ?>A string1: A string2: xxx ≫実行その2≪ A or B ?>B string1: B string2: yyy ≫実行その3≪ A or B ?>hoge string1: hoge string2: hoge 以上です。

oxfax
質問者

お礼

マクロをさらにマクロに変換すればいいのですね。 まさに、これがやりたいことでした。 ありがとうございます。

その他の回答 (8)

  • toshiyuk
  • ベストアンサー率41% (36/87)
回答No.9

no.8 です。 ズレてたので追加しました。 #define STRDEF "test2" void myFunc ( string& str ) { if ( str == STRDEF ) cout << "equal" << endl ; } int main ( ) { myFunc ( string ( STRDEF )) ; }

  • toshiyuk
  • ベストアンサー率41% (36/87)
回答No.8

C++ の string を使えばできます。 #include <string> #include <iostream> using namespace std ; string str = "test" ; string str2 = "test2" ; cout << str << "," << str2 << endl ; if ( str != str2 ) cout << "not equal" << endl ;

  • tadys
  • ベストアンサー率40% (856/2135)
回答No.7

文字列同士を比較する時に == 演算子は使えません。 strcmp() 関数を使いましょう。 char str[255]; if( strcmp( str, "xxx") ) {   /* 等しくない時 */ }else{   /* 等しい時 */ } #define を使っても動作します。 #define STRING "abc" char str[255]; if( strcmp( str, STRING ) ) {   /* 等しくない時 */ }else{   /* 等しい時 */ }

  • qwertfk
  • ベストアンサー率67% (55/81)
回答No.5

マクロ名による分岐というのは無理っぽいです。 基本的には名前と値を対応付けるテーブルを作ってそれを参照する という機能が必要になると思います。 cなら、たとえば struct MapElement {  char* name;  char* value; }; MapElement str_map[] = {  { "A" , "xxx" } ,  { "B" , "yyy" } }; char* NameToValue( char* name ) {  for( int i = 0 ; i < sizeof(str_map) ; ++i )  {   if( strcmp( str_map[i].name , name ) == 0 )    return str_map[i].value;  }  return ""; } として、 printf( "%s\n" , NameToValue( "A" ) ); // "xxx" と出力される とかでしょうか。 c++ならstd::mapを使うのがベストだと思います。

回答No.4

既に回答にある、連想配列がおすすめですが、 Cの範囲なら、こんな関数で対応可能。 ※ただ、Cの標準ライブラリに、文字列を変換する関数があった気がする。 でも、そもそも、Cの範囲で、 > if(str == "xxx") > のように中身を指定するのではなく という書き方はできないので注意。 #include <stdio.h> #include <string.h> struct strPair { char *src; char *terget; } strPairList[] = { {"A", "xxx"}, {"B", "yyy"}, {"C", "zzz"}, }; char *nextStr(char *search) { unsigned int i; for(i = 0; i < sizeof strPairList / sizeof strPairList[0]; i++) { if (! strcmp(search, strPairList[i].src)) return strPairList[i].terget; } return 0; } という関数を作れば、 func(nextStr("A")); は、 func("xxx"); のように動きます。 たとえば、 int main() { printf("%s", nextStr("A")); return 0; } の出力は、 xxx if (str == "xxx") は(Cの仕様として)できないけど、 if (! strcmp(str, nextStr("A"))) は可能で、この場合だと、 if (! strcmp(str, "xxx")) と同じ動きをする。

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.3

> strで"A"あるいは"B"という文字列を読みこんで 質問文がおかしいような。「str」は変数なのだから、手段を表す「で」というのはありえないかと。 「strに文字列を読み込む」というような、strが対象を表すのなら、あり得ると思います。 で、結局は「strcmp使え」が解答になりそうな。 あるいは、「連想配列が使いたかったら、C++でSTLを使え」とか。

参考URL:
http://www.ideone.com/VnvLd
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

#defineで定義したマクロでは、コンパイル前にソースを書き換える、ということは理解していますか? if(str == A) と書いても、コンパイル時には if(str == "xxx") と書いたのと同じになります。動作時は、マクロAから置換した"xxx"か、マクロCから置換した"xxx"か、直接書いた"xxx"か、区別できません。 文字列"A"とマクロAを結び付けるような仕組み(配列とかハッシュとか関数とか)を用意するのが常套手段でしょう。

  • papapa0427
  • ベストアンサー率25% (371/1472)
回答No.1

strcmp関数

oxfax
質問者

補足

すみません、質問を間違えました。 strで"A"あるいは"B"という文字列を読みこんで 条件分岐せずにそのままある関数に func(str) と代入する場合を考えます。 このときにfunc("A")という文字列が代入されるのではなく func(A)というdefineで定義された定数、実際にはfunc("xxx")が渡されるようにしたいのです。

関連するQ&A