C++ 测试位以创建字符串-有更好的方法吗?

C++ 测试位以创建字符串-有更好的方法吗?,c++,c,string,loops,bit-manipulation,C++,C,String,Loops,Bit Manipulation,这段代码很有效,但我想知道是否有更好的方法。基本上,我需要测试位,并根据位的状态将适当的字符写入字符串。空格是存在的,因为字符将以固定宽度字体显示,我想防止它们四处移动。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] = {" ", " ", "

这段代码很有效,但我想知道是否有更好的方法。基本上,我需要测试位,并根据位的状态将适当的字符写入字符串。空格是存在的,因为字符将以固定宽度字体显示,我想防止它们四处移动。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);
}
const char*字母[10]={“A”、“B”、“Sl”、“St”、“R”、“L”、“U”、“D”、“RS”、“LS”};
常量字符*Ext[2]={“X”,“Y”};
常量字符*空间[10]={“”、“”、“”、“”、“”、“”、“”、“”、“”、“”、“”、“”、“”、“”、“”};
char-str[60];
char FinalString[60];
void MakeBitString(u16数据,u16数据扩展){
int x;
strcpy(str,“”);
对于(x=0;x<2;x++){
//X和Y
如果(数据扩展和(1
  • 使用std::string代替char*和strcat
  • 为什么需要带空格的数组?看起来可能只有一个空格
  • 您有两个u16参数的几乎相同的代码-创建一个小函数并调用它两次
  • 不在全局变量中写入结果-返回std::string

以一些动态分配(在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;
}
定义数组大小(A)(sizeof(A)/sizeof((A)[0])) std::string MakeBitString(u16数据,常量std::string*字母,整数计数){ std::字符串s; 对于(int x=0;x如果(data&(1这应该没问题;但是如果你想添加按钮或轴,你可能想对其进行一点概括。

我建议使用更明确的方法,它不使用循环,因为你似乎只有少量的位需要检查。如果这需要扩展到数万位,那么一定要使用循环

我还假设您有充分的理由使用全局变量和固定长度字符数组

下面是我要做的:

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
}

基本上,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;
}
其中,
转换器
实现如下

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_;
};
struct转换器
{
转换器(标准:尺寸值):
值(值),x(0)
{}
std::string运算符()(常量std::string和bitPresentation)
{

return(value)&(1这里有一种在一次传递中使用一位的方法。它甚至可以扩展到16位,只要您确保
wide
掩码在任何有两个字符的能指的地方都设置了位

#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';
}
#定义EXT_STR“XY”
#定义数据\u STR“abslstrludsls”
const char FullStr[]=EXT_STR DATA_STR;
#定义EXT_SZ 2//strlen(EXT_STR);
void MakeBitStr(u16数据,u16数据扩展){
char*dest=最终字符串;
const char*src=FullStr;

u16输入=(数据非黑漆清洁溶液:

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;
}
std::string MakeBitString(u16数据,u16数据扩展){
std::字符串ret;
静态常量字符*letters=“A B SlStR L U D RSLS”;
静态常量字符*ext=“XY”;
静态常量字符*空格=”;
用于(整数位=0;位<2;++位){
const char*which=(dataExt&1)?&ext[bit]:空格;
ret+=std::string(其中,0,1);
dataExt>>=1;
}
用于(整数位=0;位<10;++位){
常量整数长度=字母[位*2+1]=''1:2;
常量char*which=(dataExt&1)&字母[位*2]:空格;
ret+=std::string(其中,0,长度);
dataExt>>=1;
}
返回ret;
}

无论是否设置位,都要确保宽度相同。我认为最好使用boost::array或普通aray来存储字符串(易于创建)。此外,您的转换器会计算调用数-我不确定这是否合法。@bb:当然初始化阶段可以更改,甚至转换器也可以接受集合作为参数。boost::array是一个好主意,以防boost被允许。使用常用数组只是为了简短-我不喜欢它们:)以及它们的大小计算。必须检查有关functor中计数的标准。不是。代码分为两部分:一部分处理位,另一部分处理位。当需要更改一部分时,不能触摸另一部分。有点低耦合。
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;
}