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