十六进制转换为C++/C/Qt?

时间:2022-09-01 09:51:36

I am interfacing with an external device which is sending data in hex format. It is of form

我正在与一个外部设备接口,它以十六进制格式发送数据。它的形式

> %abcdefg,+xxx.x,T,+yy.yy,T,+zz.zz,T,A*hhCRLF
  • CR LF is carriage return line feed
  • CR LF是回车换行。
  • hh->checksum
  • hh - >校验和
  • %abcdefg -> header
  • %英语字母- >标题

Each character in above packet is sent as a hex representation (the xx,yy,abcd etc are replaced with actual numbers). The problem is at my end I store it in a const char* and during the implicit conversion the checksum say 0x05 is converted to \0x05. Here \0 being null character terminates my string. This is perceived as incorrect frames when it is not. Though I can change the implementation to processing raw bytes (in hex form) but I was just wondering whether there is another way out, because it greatly simplifies processing of bytes. And this is what programmers are meant to do.

上述数据包中的每个字符都以十六进制表示形式发送(xx、yy、abcd等用实际数字替换)。问题是,我将它存储在const char*中,在隐式转换中,校验和表示0x05转换为\0x05。这里\0为空字符终止我的字符串。这被认为是不正确的框架。虽然我可以更改实现以处理原始字节(以十六进制形式),但我只是想知道是否还有另一种方法,因为它极大地简化了字节的处理。这就是程序员应该做的事情。

Also in cutecom (on LINUX RHEL 4) I checked the data on serial port and there also we noticed \0x05 instead of 5 for checksum. Note that for storing incoming data I am using

同样在cutecom(在LINUX RHEL 4上)我检查了串行端口上的数据,我们也注意到了\0x05而不是5的校验和。注意,为了存储我正在使用的传入数据。

//store data from serial here
unsigned char Buffer[SIZE];  

//convert to a QString, here is where problem arises 
QString str((const char*)Buffer); of \0

QString is "string" clone of Qt. Library is not an issue here I could use STL also, but C++ string library is also doing the same thing. Has somebody tried this type of experiment before? Do share your views.

QString是Qt的“string”克隆,这里的库不是问题,我也可以使用STL,但是c++字符串库也在做同样的事情。以前有人尝试过这种实验吗?分享你的观点。

EDIT

编辑

This is the sample code you can check for yourself also:

这是你可以自己检查的样本代码:

#include <iostream>
#include <string>
#include <QString>
#include <QApplication>
#include <QByteArray>

using std::cout;
using std::string;
using std::endl;

int main(int argc,char* argv[])
{
    QApplication app(argc,argv);
    int x = 0x05;
    const char mydata[] = {
         0x00, 0x00, 0x03, 0x84, 0x78, 0x9c, 0x3b, 0x76,
               0xec, 0x18, 0xc3, 0x31, 0x0a, 0xf1, 0xcc, 0x99};
    QByteArray data = QByteArray::fromRawData(mydata, sizeof(mydata));
    printf("Hello %s\n",data.data());
    string str("Hello ");
    unsigned char ch[]={22,5,6,7,4};
    QString s((const char*)ch);
    qDebug("Hello %s",qPrintable(s));
    cout << str << x ;
    cout << "\nHello I am \0x05";
    cout << "\nHello I am " << "0x05";
    return app.exec();
}

4 个解决方案

#1


8  

If your 0x05 is converted to the char '\x05', then you're not having hexadecimal values (that only makes sense if you have numbers as strings anyway), but binary ones. In C and C++, a char is basically just another integer type with very little added magic. So if you have a 5 and assign this to a char, what you get is whatever character your system's encoding defines as the fifth character. (In ASCII, that would be the ENQ char, whatever that means nowadays.)

如果您的0x05被转换为char '\x05',那么您就没有十六进制的值(如果您有数字作为字符串的话,这是有意义的),但是二进制的值。在C和c++中,char基本上只是另一个整数类型,而且添加的魔法很少。如果你有一个5,把它分配给一个char,你得到的是你的系统编码定义为第五个字符的任何字符。(在ASCII中,这将是ENQ char,无论这意味着什么。)

If what you want instead is the char '5', then you need to convert the binary value into its string representation. In C++, this is usually done using streams:

如果您想要的是char '5',那么您需要将二进制值转换为它的字符串表示形式。在c++中,这通常是使用流来完成的:

const char ch = 5; // '\0x5'
std::ostringstream oss;
oss << static_cast<int>(ch);
const std::string& str = oss.str(); // str now contains "5"

Of course, the C std library also provides functions for this conversion. If streaming is too slow for you, you might try those.

当然,C std库也提供了这种转换的功能。如果流对你来说太慢,你可以试试。

#2


12  

QByteArray text = QByteArray::fromHex("517420697320677265617421");
text.data();            // returns "Qt is great!" 

#3


0  

I think c++ string classes are usually designed to handle zero-terminated char sequences. If your data is of known length (as it appears to be) then you could use a std::vector. This will provide some of the functionality of a string class, whilst ignoring nulls within data.

我认为c++ string类通常被设计用来处理零终止的字符序列。如果您的数据是已知长度(似乎是),那么您可以使用std::vector。这将提供string类的一些功能,同时忽略数据中的nulls。

#4


0  

As I see you want to eliminate control ASCII symbols. You could do it in the following way:

我看到你想要消除控制ASCII码。你可以这样做:

#include <iostream>
#include <string>
#include <QtCore/QString>
#include <QtCore/QByteArray>

using namespace std;

// test data from your comment
char data[] = { 0x49, 0x46, 0x50, 0x4a, 0x4b, 0x51, 0x52, 0x43, 0x2c, 0x31,
                0x32, 0x33, 0x2e, 0x34, 0x2c, 0x54, 0x2c, 0x41, 0x2c, 0x2b,
                0x33, 0x30, 0x2e, 0x30, 0x30, 0x2c, 0x41, 0x2c, 0x2d, 0x33,
                0x30, 0x2e, 0x30, 0x30, 0x2c, 0x41, 0x2a, 0x05, 0x0d, 0x0a };

// functor to remove control characters
struct toAscii
{
  // values >127 will be eliminated too
  char operator ()( char value ) const { if ( value < 32 && value != 0x0d && value != 0x0a ) return '.'; else return value; }
};

int main(int argc,char* argv[])
{
  string s;
  transform( &data[0], &data[sizeof(data)], back_inserter(s), toAscii() );

  cout << s; // STL string

  // convert to QString ( if necessary )
  QString str = QString::fromStdString( s );
  QByteArray d = str.toAscii();

  cout << d.data(); // QString

  return 0;
}

The code above prints the following in console:

以上代码在控制台打印如下:

IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.

If you have continuous stream of data you'll get something like:

如果你有连续的数据流,你会得到这样的信息:

IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.

#1


8  

If your 0x05 is converted to the char '\x05', then you're not having hexadecimal values (that only makes sense if you have numbers as strings anyway), but binary ones. In C and C++, a char is basically just another integer type with very little added magic. So if you have a 5 and assign this to a char, what you get is whatever character your system's encoding defines as the fifth character. (In ASCII, that would be the ENQ char, whatever that means nowadays.)

如果您的0x05被转换为char '\x05',那么您就没有十六进制的值(如果您有数字作为字符串的话,这是有意义的),但是二进制的值。在C和c++中,char基本上只是另一个整数类型,而且添加的魔法很少。如果你有一个5,把它分配给一个char,你得到的是你的系统编码定义为第五个字符的任何字符。(在ASCII中,这将是ENQ char,无论这意味着什么。)

If what you want instead is the char '5', then you need to convert the binary value into its string representation. In C++, this is usually done using streams:

如果您想要的是char '5',那么您需要将二进制值转换为它的字符串表示形式。在c++中,这通常是使用流来完成的:

const char ch = 5; // '\0x5'
std::ostringstream oss;
oss << static_cast<int>(ch);
const std::string& str = oss.str(); // str now contains "5"

Of course, the C std library also provides functions for this conversion. If streaming is too slow for you, you might try those.

当然,C std库也提供了这种转换的功能。如果流对你来说太慢,你可以试试。

#2


12  

QByteArray text = QByteArray::fromHex("517420697320677265617421");
text.data();            // returns "Qt is great!" 

#3


0  

I think c++ string classes are usually designed to handle zero-terminated char sequences. If your data is of known length (as it appears to be) then you could use a std::vector. This will provide some of the functionality of a string class, whilst ignoring nulls within data.

我认为c++ string类通常被设计用来处理零终止的字符序列。如果您的数据是已知长度(似乎是),那么您可以使用std::vector。这将提供string类的一些功能,同时忽略数据中的nulls。

#4


0  

As I see you want to eliminate control ASCII symbols. You could do it in the following way:

我看到你想要消除控制ASCII码。你可以这样做:

#include <iostream>
#include <string>
#include <QtCore/QString>
#include <QtCore/QByteArray>

using namespace std;

// test data from your comment
char data[] = { 0x49, 0x46, 0x50, 0x4a, 0x4b, 0x51, 0x52, 0x43, 0x2c, 0x31,
                0x32, 0x33, 0x2e, 0x34, 0x2c, 0x54, 0x2c, 0x41, 0x2c, 0x2b,
                0x33, 0x30, 0x2e, 0x30, 0x30, 0x2c, 0x41, 0x2c, 0x2d, 0x33,
                0x30, 0x2e, 0x30, 0x30, 0x2c, 0x41, 0x2a, 0x05, 0x0d, 0x0a };

// functor to remove control characters
struct toAscii
{
  // values >127 will be eliminated too
  char operator ()( char value ) const { if ( value < 32 && value != 0x0d && value != 0x0a ) return '.'; else return value; }
};

int main(int argc,char* argv[])
{
  string s;
  transform( &data[0], &data[sizeof(data)], back_inserter(s), toAscii() );

  cout << s; // STL string

  // convert to QString ( if necessary )
  QString str = QString::fromStdString( s );
  QByteArray d = str.toAscii();

  cout << d.data(); // QString

  return 0;
}

The code above prints the following in console:

以上代码在控制台打印如下:

IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.

If you have continuous stream of data you'll get something like:

如果你有连续的数据流,你会得到这样的信息:

IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.