2012-09-17 18 views
9

これを行うにはマクロ以外の方法が良いことがあることを無視しています(悲しいことに、良い理由があります)、マクロを使用して大量の汎用コードを書く必要があります。基本的には、いくつかの事前指定された型に対して多数の関数を生成するマクロライブラリです。プリプロセッサ(マクロ)を使用してC文字列リテラルを大文字に変換できますか?

既存の単体テストが数多く破壊されないようにするために、ライブラリで必要なことの1つは、すべての型に対して、その型の名前をすべて大文字で生成して印刷することです。例えば。タイプ "フラグ"は "フラグ"として印刷されなければならない。

各タイプの定数を手動で書き出すことができます。

の#define flag_ALLCAPSNAME FLAG

が、これは理想的ではありません。私はこれをプログラム的に行うことができるようにしたいと思います。

現時点では、私は一緒にこれをハッキングしました:(このコードのビットの後、capname_bufは、その内容として「FLAG」を持っているすなわち)私はある程度まで何をしたいん

char capname_buf[BUFSIZ]; 
#define __MACRO_TO_UPPERCASE(arg) strcpy(capname_buf, arg); \ 
for(char *c=capname_buf;*c;c++)*c = (*c >= 'a' && *c <= 'z')? *c - 'a' + 'A': *c; 
__MACRO_TO_UPPERCASE(#flag) 

が、私は希望代わりにマクロを使用して文字リテラルを定義することができ、この愚かなバッファの必要性を避けるソリューションを好む。

私はこれを行う方法がわかりませんが、おそらく私は何か明白なものを見逃していますか?

可変ループforeachループマクロ(this oneなど)が書かれていますが、#flagによって生成された文字列リテラルの内容を変更することはできません。また、いずれの場合でもループマクロには、繰り返し処理を繰り返します(つまり、リスト上で繰り返され、インデックス上で繰り返されることはありません)。

思考?

+0

[cantはプリプロセッサディレクティブで小文字を大文字に変換できません](http://stackoverflow.com/questions/3216049/cant-convert-lowercase-to-uppercase-a-string-by-preprocessor-directive ) – unwind

+0

@unwind私はそれを見ましたが、答えが正しくない(したがって役に立たない)b/cは、プリプロセッサでループを作ることができないと想定しています。 –

+0

どのようにですか?あなたの例では、プリプロセッサで実行されたループは表示されません。また、それを行う方法が分かっていれば、開始点の一部ではないはずですか? – unwind

答えて

15

ポータブルC99では、定数文字列をすべて大文字に変換するマクロを持つことはできません(特に、文字の概念は文字エンコーディングに関連しているためです)。UTF8文字はASCIIとは異なります。 。

ただし、他の解決策を検討することもできます。

  • これを行うには、エディタをカスタマイズします。たとえば、必要に応じて各Cソースファイルを更新するemacsコードを書くことができます。

  • Cソースコード(おそらく#include -dファイルに#defineの束を放出する単純なCコードジェネレータスクリプト)でプリプロセッサを使用してください。

  • 使用GCC extensionsは、おそらくあなたの__builtin_capitalize_constant行うための仕事を提供するために、(GCCを拡張するためにドメイン固有言語)MELTを使用して、おそらく

    #define TO_UPPERCASE_COUNTED(Str,Cnt) 
    #define TO_UPPERCASE(Str) TO_UPPERCASE_COUNTED(Str,__COUNT__) {(\ 
        static char buf_##Cnt[sizeof(Str)+4]; \ 
        char *str_##Cnt = Str; \ 
        int ix_##Cnt = 0; \ 
        for (; *str_##Cnt; str_##Cnt++, ix_##Cnt++) \ 
        if (ix_##Cnt < sizeof(buf_##Cnt)-1) \ 
         buf_##Cnt[ix_##Cnt] = toupper(*str_##Cnt); \ 
        buf_##Cnt;)} 
    
  • カスタマイズGCCを持っています。

+1

この回答はすべての選択肢をかなりカバーしています。ありがとう。 –

1

これは完全にcプリプロセッサを使用して行うことはできません。その理由は、プリプロセッサが入力を(アトミック)pp-tokensとして読み込み、出力を構成するからです。プリプロセッサーがpp-tokenをどのような方法でも個々の文字に分解するための構成はありません。

あなたの例では、プリプロセッサが文字列リテラル"flag"を読み込むと、それはプリプロセッサに基本的にアトミックチャンクのテキストです。このようなチャンクを条件付きで削除するか、それらを一緒に大きなチャンクに接着するための構造を持っています。

ある意味でpp-tokenを分解できる唯一の構文は、いくつかの式を介しています。しかし、これらの式は算術型でしか使えないので、ここではあなたを助けません。

あなたのアプローチは、C言語の構文を使用することでこの問題を回避します。つまり、実行時に変換を行います。プリプロセッサが行う唯一のことは、Cコードを挿入して文字列を変換することです。

関連する問題