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
  • 使用 std::string 代替 char* 和 strcat;
  • 为什么需要带空格的数组?似乎只有一个空间;
  • 您的两个 u16 参数的代码几乎相同 - 创建一个小函数并调用它两次;
  • 不要将结果写入全局变量 - 返回 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

非hacky,干净的解决方案:

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

这是一次完成的一种有点棘手的方法。它甚至可以扩展到最多 16 位,只要您确保wide掩码在具有 2 字符指示符的任何位置都设置了位。

#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 回答