2009-04-01 10 views
2

このコードは機能しますが、もっと良い方法があるのだろうかと思います。基本的に私はビットをテストし、ビットの状態に応じて適切な文字を文字列に書き出す必要があります。文字は固定幅のフォントで表示されるため、スペースが存在し、移動しないようにしたいと思います。 CまたはC++は問題ありません。ビットをテストして文字列を作成する - より良いアプローチがありますか?

const char* Letters[10] = {"A", "B", "Sl", "St", "R", "L", "U", "D", "RS", "LS"}; 
const char* Ext[2] = {"X", "Y"}; 
const char* Spaces[10] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " "}; 

char str[60]; 
char FinalString[60]; 

void MakeBitString(u16 data, u16 dataExt) { 

    int x; 
    strcpy(str, ""); 

    for (x = 0; x < 2; x++) { 

     //X and Y 
     if(dataExt & (1 << x)) { 
      strcat(str, Spaces[x]); 
     } 
     else 
      strcat(str, Ext[x]); 
    } 

    for (x = 0; x < 10; x++) { 

     //the rest 
     if(data & (1 << x)) { 
      strcat(str, Spaces[x]); 
     } 
     else 
      strcat(str, Letters[x]); 
    } 

    strcpy(FinalString, str); 
} 

答えて

4
  • 使用のstd ::文字列の代わりのchar *とSTRCAT。
  • なぜスペースを含む配列が必要ですか?それはちょうど1つのスペースかもしれません。
  • あなたは2つのu16パラメータのほぼ完全なコードを持っています。小さな関数を1つ作り、2回呼び出します。
  • は、グローバル変数に結果書いていない - いくつかの動的な割り当てのコストでリターンのstd ::文字列
+0

これは、幅がビットが設定されているかどうかと同じであることを確認しています。 – MSN

1

(のstd ::文字列の中で)、あなたがより簡単に変更可能な任意のを持っていないことで、このコードを作ることができますハードコード番号:

#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) 

std::string MakeBitString(u16 data, const std::string* letters, int count) { 
    std::string s; 
    for (int x = 0; x < count; x++) { 
     if (data & (1 << x)) 
      s.append(letters[x].size(), ' '); 
     else 
      s += letters[x]; 
    } 
    return s; 
} 

std::string MakeBitString(u16 data, u16 dataExt) { 
    const std::string Letters[] = {"A", "B", "Sl", "St", "R", "L", "U", "D", "RS", "LS"}; 
    const std::string Ext[] = {"X", "Y"}; 

    std::string s = MakeBitString(dataExt, Ext, ARRAYSIZE(Ext)); 
    s += MakeBitString(dataExt, Letters, ARRAYSIZE(Letters)); 
    return s; 
} 
0

これで問題はありません。しかし、ボタンや軸を追加したい場合は、少し一般化したいかもしれません。

3

私はループを使っていない何かを明示することをお勧めします。これは、チェックするビット数が少ないためです。これを数千ビットに拡張する必要がある場合は、必ずループを使用してください。

また、グローバル変数と固定長文字配列を使用する大きな理由があると仮定します。ここで

は、私がどうなるのかです:Converterがここ

struct Converter 
{ 
    Converter(std::size_t value): 
     value_(value), x_(0) 
    {} 
    std::string operator() (const std::string& bitPresentation) 
    { 
     return (value_ & (1 << x_++)) ? 
      std::string(bitPresentation.size(), ' '): 
      bitPresentation; 
    } 
    std::size_t value_; 
    std::size_t x_; 
}; 

のように実装されている

Codes convert(std::size_t data, 
       const Codes& ext, 
       const Codes& letters) 
{ 
    Codes result; 
    std::transform(ext.begin(), 
        ext.end(), 
        std::back_inserter(result), 
        Converter(data)); 

    std::transform(letters.begin(), 
        letters.end(), 
        std::back_inserter(result), 
        Converter(data)); 
    return result; 
} 

がコードからの変換である

よう

char FinalString[60]; 

void ConcatBitLabel(char ** str, u16 data, u16 bitMask, const char * label) 
{ 
    if (data & bitMask) 
    { 
     // append spaces for strlen(label) 
     while (*label) { *((*str)++) = ' '; label++; } 
    } 
    else 
    { 
     // append the label 
     while (*label) { *((*str)++) = *label; label++; } 
    } 
} 

void MakeBitString(u16 data, u16 dataExt) 
{ 
    char * strPtr = FinalString; 

    ConcatBitLabel(&strPtr, dataExt, 0x0001, "X"); 
    ConcatBitLabel(&strPtr, dataExt, 0x0002, "Y"); 

    ConcatBitLabel(&strPtr, data, 0x0001, "A"); 
    ConcatBitLabel(&strPtr, data, 0x0002, "B"); 
    ConcatBitLabel(&strPtr, data, 0x0004, "Sl"); 
    ConcatBitLabel(&strPtr, data, 0x0008, "St"); 
    ConcatBitLabel(&strPtr, data, 0x0010, "R"); 
    ConcatBitLabel(&strPtr, data, 0x0020, "L"); 
    ConcatBitLabel(&strPtr, data, 0x0040, "U"); 
    ConcatBitLabel(&strPtr, data, 0x0080, "D"); 
    ConcatBitLabel(&strPtr, data, 0x0100, "RS"); 
    ConcatBitLabel(&strPtr, data, 0x0200, "LS"); 

    *strPtr = 0; // terminate the string 
} 
3

基本的にC++ソリューションが見えます文字列関数

std::string codesToString(const Codes& codes) 
{ 
    std::ostringstream stringStream; 
    std::copy(codes.begin(), codes.end(), 
       std::ostream_iterator<std::string>(stringStream)); 
    return stringStream.str(); 
} 
+0

私はストア文字列(作成しやすい)のためにboost :: arrayまたは通常のarayを使用する方が良いと思います。また、あなたのコンバーターは電話をカウントします - 私はこの合法であるとは確信していません。 – bayda

+0

@bb:もちろん、初期化フェーズを変更することもできますし、コンバータでもパラメータとしてコレクションを受け入れることができます。ブーストが許可されている場合、boost :: arrayは良い考えです。一般的な配列を短時間だけ使う - 私はそれらが好きではない:)とそのサイズの計算。ファンクタのカウントについては、標準でチェックインする必要があります。 –

+0

複雑なコードを書く利点は何ですか? – alexk7

0

ここでは、1回のパスでそれを行うためのちょっとした方法があります。 wideマスクが2文字の記号を持つ場所にビットが設定されていることを確認している限り、最大16ビットまで拡張できます。

#define EXT_STR "XY" 
#define DATA_STR "ABSlStRLUDRSLS" 
const char FullStr[] = EXT_STR DATA_STR; 
#define EXT_SZ 2 //strlen(EXT_STR); 

void MakeBitStr(u16 data, u16 dataExt) { 
    char* dest = FinalString; 
    const char* src= FullStr; 
    u16 input = (data<<EXT_SZ)|dataExt; 
    u16 wide = (0x30C<<EXT_SZ)|0; //set bit for every 2char tag; 
    while ((src-FullStr)<sizeof(FullStr)) 
    { *dest++ = (input&1)?' ':*src; 
     if (wide&1) 
     { wide&=~1; 
     } 
     else 
     { input>>=1;wide>>=1; 
     } 
     src++; 
    } 
    *dest='\0'; 
} 
0

非ハック、クリーンなソリューション:

std::string MakeBitString(u16 data, u16 dataExt) { 
    std::string ret; 

    static const char *letters = "A B SlStR L U D RSLS"; 
    static const char *ext = "XY"; 
    static const char *spaces = " "; 

    for(int bit = 0; bit < 2; ++bit) { 
     const char *which = (dataExt & 1) ? &ext[bit] : spaces; 

     ret += std::string(which, 0, 1); 

     dataExt >>= 1; 
    } 

    for(int bit = 0; bit < 10; ++bit) { 
     const int length = letters[bit * 2 + 1] == ' ' ? 1 : 2; 
     const char *which = (dataExt & 1) ? &letters[bit * 2] : spaces; 

     ret += std::string(which, 0, length); 

     dataExt >>= 1; 
    } 

    return ret; 
} 
関連する問題