• ベストアンサー

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

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

  • oxfax
  • お礼率27% (57/209)

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

  • ベストアンサー
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

  • defineで定数が置き換えられない?(C言語)

    #defineについて質問です。 #defineは、ソースコード内にこの文字を見つけたら、コンパイルする前にこの文字をこの定数に置き換えて、というプリプロセッサですよね?だから、printfで#defineで定義した定数を出力する場合で、変換指定が必要ない場合は #include <stdio.h> #define DEF 100 void main(){ printf("#defineで定義された定数はDEFです"); } でもいいと思うんです。ですがこのソースコードは間違いで、実行結果は #defineで定義された定数はDEFです(←置き換えられてない) となってしまします。プリプロセッサだけ実行しても、DEFは100に置き換えられずそのままです。printfで#defineで定義した定数を出力させたい場合は書式指定をしなければなりません。なぜ、このような場合は#defineで定義した定数は置き換えられないのでしょうか?回答よろしくお願いします。

  • IF関数の論理式が文字列??

    他人が作成したエクセル関数式を理解したいのですが、どう調べたものか手の付け所がわからず、質問をさせて頂きます。 関数は以下の様なものです(<XXX_YYY_10000>の部分はデフォルメしていますが、 XXX,YYY,1000はそれぞれもともと文字列と数字です)。 =IF(OR(A1="",A1<XXX_YYY_10000-2),1,IF(AND(A1>XXX_YYY_10000-2,A1<XXX_YYY_10000),2,IF(A1>=XXX_YYY_10000,3,1))) どなたか詳しいかた、この関数の動作について簡単で結構ですのでご教示頂けないでしょうか。 特に、論理式が<XXX_YYY_10000-2>の様に文字列と数字が混じっており、何を条件としているのか見当つかず躓いています。 すごく頓珍漢な質問をしている様な気もするのですが宜しくお願い致します。

  • $XXX を含んだ文字列の評価

    '$XXX + $yyy' という文字列($XXXと$yyyは単なる文字列)を評価したものを別の変数に格納したいのですがどうすればいいでしょう。 <?php $XXX = 10 ; $yyy = 5 ; $str = '$XXX + $yyy' ; $ans = なんとか文字列を評価; echo $ans ; ?> 表示 -- 15

    • ベストアンサー
    • PHP
  • 文字列内で定数を使いたいときに手間がかかる

    文字列内で定数を使いたいときにこういう手法があります。 $a = function($t){ return $t }; echo "{$a(TEISUU)}"; これをいろんな関数内でも気軽に使いたいのですが、いざやってみると  ・必要な場所で毎回上記を定義する  ・ライブラリ関数として別個定義しインクルードしておいて、使いたい関数内でglobal宣言する  ・$GLOBALSを使う このようにいずれも余計な手間や見た目が雑になってしまい使い勝手が悪いです。 どの関数内でも手間いらずで「$a(定数)」を使う方法はないでしょうか。

    • ベストアンサー
    • PHP
  • 文字列(丸数字)の文字化けについて

    今自分で関数を作成しているのですが、文字列(丸数字)の文字化けにかなり苦しんでいます。 (※注※)これ以降(1)など()の中に数字を入れて記述しているものは実際のソースコード上では丸数字で記入してます。教えてgooでは丸数字が記述できないようでして… 関数の内容としては、(1)あ(2)い(3)う……このように丸数字で区切られている文字列を配列名を$dataとすると、$data[0]には「あ」、$data[1]には「い」、$data[2]には「う」が入るような関数を作成しています。 この丸数字の数は(10)まで対応させようと考えてます。 実際のソースは function bunkai($str1){ if (strstr($str1, "(10)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)"); // 区切り文字 }else if (strstr($str1, "(9)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)(8)(9)"); // 区切り文字 }else if (strstr($str1, "(8)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)(8)"); // 区切り文字 }else if (strstr($str1, "(7)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)"); // 区切り文字 }else if (strstr($str1, "(6)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)"); // 区切り文字 }else if (strstr($str1, "(5)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)"); // 区切り文字 }else if (strstr($str1, "(4)") != NULL){ define("kugiri","(1)(2)(3)(4)"); // 区切り文字 }else if (strstr($str1, "(3)") != NULL){ define("kugiri","(1)(2)(3)"); // 区切り文字 }else if (strstr($str1, "(2)") != NULL){ define("kugiri","(1)(2)"); // 区切り文字 }else if (strstr($str1, "(1)") != NULL){ define("kugiri","(1)"); // 区切り文字 } $count = 0; $token = strtok($str1, kugiri); while ($token) { $data[$count] = $token; $token = strtok(kugiri); $count++; } $data[$count] = NULL; return $data; } なんですが、 $str1に"(3)した(名)(4)しも(名)(5)もと(名)(6)さ-げる(動ガ下一)(7)さ-がる(動ガ下一)(8)くだ-る(動ラ五[四])(9)くだ-す(動サ五[四])(10)くだ-さる(動ラ五[四])"という文字列を入れて $dataを表示させてみると $data[0]=した(名) $data[1]=しも(名) ここまではできるのですが、これ以降 $data[2]=も� $data[3]=(名) $data[4]=さ-げる(動ガ下一) $data[5]=さ-がる(動ガ下一) $data[6]=く� $data[7]=-る(動� : : となってしまい、ところどころでうまく丸数字を読み込めていません。特に$str1に違う文字列をいれてみても(1)(2)(3)(4)まではきちんと読み込めてその後の(5)でまず最初の文字化けが絶対発生してしまいます。でも(5)を通過したあとの(6)(7)はきちんと判別していたりとよく原因がわかりません……。 がんばってexplode関数で同じようなことしてもいいかなと考えているのですが、関数自体が長くなってしまうので、めんどくさいなーと思います。 どなたか、このバグの原因がわかるかた、または、こんな関数を使ってこんなことしたら丸数字を判別して配列に入れることができるよーという意見もあったら欲しいです。 お願いします。困ってます。

    • ベストアンサー
    • PHP
  • プログラミング ポインタを使った文字列比較

    プログラミング ポインタを使った文字列比較 2つの文字列str1, str2を入力し,それらが等しければ0,等しくなければ1を返す関数str_compareを作り、返り値によって以下のように表示するプログラムを作れ。ただし,関数strcmpを使ってはならない。 文字列の入出力はmain関数で行い,関数str_compareの仮引数にはポインタ変数を宣言し,ポインタと間接演算子*を用いた処理を行うこと。 % ./a.out input str1 = Worldcup input str2 = Worldcup same strings % ./a.out input str1 = World input str2 = cup different strings この問題に私は次のようにプログラミングしました。 #include <stdio.h> #define MAX 100 int str_compare(char *, char *); main() { char str1[MAX], str2[MAX]; printf("input str1 = %s", str1); scanf("%s", str1); printf("input str2 = %s", str2); scanf("%s", str2); str_compare(str1, str2); if (str_compare(str1, str2) == 0) printf("same strings\n"); else if (str_compare(str1, str2) == 1) printf("different strings\n"); } int str_compare(char *s1, char *s2) { int i; for (i = 0; s1[i] != '\0'; i++) { if (s1[i] != s2[i]) { break; } } if (s1[i] == s2[i]) { return 0; } else { return 1; } } これで実行したところ、「input str1 =」の右のスペースが文字化け?してしまいます。(半角カタカナや記号が出る)ただ、その後に文字列を入力すると、正しく機能します。 これは何が悪いなのでしょうか、どなたか教えてください。

  • scanfでの読み込み文字数制限

    scanf( "%10s" , file_name ); とすればfile_nameに読み込む文字数を10バイトに制限できるそうですが、10のところに定数(defineで定義したもの)を指定することはできないのでしょうか? 普通に #define NUM 10 scanf( "%NUMs" , file_name ); としてもできないようでした。

  • 文字列の扱い方

    初歩的な質問ですみません… str文字列からcという文字を見つけたら添字を返すという関数を作ったのですが、 iにこの関数を代入して、if文の制御式にiを使って比較するまでは正常なのですが、 真文にiを使うと何故か偽文(という言い方でいいのでしょうか…この場合("そんな値はありません。"というところです)が実行されてしまいます。 よろしければご教授お願い致します。 #include <stdio.h> int str_char(const char str[],int c) { int len = strlen(str); int i; for (i = 0;i < len;i++) { if (str[i] == c) return i; } return -1; } int main() { char str[64] = "Fucking Brutal Death Metal"; int ch,i; printf("どの文字を調べますか?"); scanf("%c",&ch); i = str_char(str,ch); if (i >= 0) printf("その文字は%d番目にあります。",str_char(str,ch) + 1); //何故かiだと動かない else printf("そんな値はありません。"); return 0; }

  • 定数の定義方法 #define

    いつもお世話になっております。 定数を定義したいのですが、 その数値が符号無し長整数の場合どのように 定義すれば宜しいのでしょうか。 符号有りの場合は特に指定しなくても宜しいのですか。 どうぞ宜しくお願いします。

  • ワードの置換で、文字列の前後に文字を追加

    ワードの置換について教えてください。 http://xxx/yyy/zzz という文字列があった場合、これを ABC-http://xxx/yyy/zzz-001 というように前後に文字列を追加したい場合はどうすれがいいのでしょうか? よろしくお願いします。

専門家に質問してみよう