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

7 に答える 7

4
  • char*とstrcatの代わりにstd::stringを使用します。
  • なぜスペース付きの配列が必要なのですか?たった1つのスペースかもしれません。
  • 2つのu16パラメーターに対してほぼ同じコードがあります。1つの小さな関数を作成して2回呼び出します。
  • 結果をグローバル変数に書き込まないでください-std::stringを返します
于 2009-04-01T17:12:59.273 に答える
3

基本的にC++ソリューションは次のようになります

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;
}

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_;
};

コードから文字列関数への変換は次のとおりです

std::string codesToString( const Codes& codes )
{
    std::ostringstream stringStream;
    std::copy( codes.begin(), codes.end(), 
               std::ostream_iterator<std::string>( stringStream ) );
    return stringStream.str();
}
于 2009-04-01T19:14:32.553 に答える
3

チェックするビット数が少ないように見えるため、ループを使用しない、もう少し明示的なものをお勧めします。これを数万ビットにスケーリングする必要がある場合は、必ずループを使用してください。

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

これが私がすることです:

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
}
于 2009-04-01T18:04:24.843 に答える
1

一部の動的割り当て (std::string 内) を犠牲にして、ハードコーディングされた数値を持たないことで、このコードをより簡単に変更できるようにすることができます。

#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;
}
于 2009-04-01T17:27:05.900 に答える
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;
}
于 2009-04-02T20:14:25.173 に答える
0

それでいいはずです。ただし、ボタンや軸を追加する場合は、少し一般化することをお勧めします。

于 2009-04-01T17:27:21.423 に答える
0

これを 1 回のパスで実行するためのちょっとした方法を次に示します。wide2 文字のシグニファイアがある場所にマスクのビットが設定されていることを確認する限り、最大 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';
}
于 2009-04-02T19:58:17.240 に答える