Преобразование шестнадцатеричного в строковое C ++ / C / Qt? - PullRequest
3 голосов
/ 11 августа 2009

Я взаимодействую с внешним устройством, которое отправляет данные в шестнадцатеричном формате. Это имеет форму

> %abcdefg,+xxx.x,T,+yy.yy,T,+zz.zz,T,A*hhCRLF
  • CR LF - перевод строки возврата каретки
  • hh-> Контрольная сумма
  • % abcdefg -> header

Каждый символ в вышеуказанном пакете отправляется в виде шестнадцатеричного представления (xx, yy, abcd и т. Д. Заменяются действительными числами). Проблема в моем конце, я храню его в const char *, и во время неявного преобразования контрольная сумма говорит, что 0x05 преобразуется в \ 0x05. Здесь \ 0, являющийся нулевым символом, завершает мою строку. Это воспринимается как неправильные кадры, когда это не так. Хотя я могу изменить реализацию для обработки необработанных байтов (в шестнадцатеричной форме), но мне просто интересно, есть ли другой выход, потому что это значительно упрощает обработку байтов. И это то, что программисты должны делать.

Также в 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 является "строковым" клоном Qt. Библиотека здесь не проблема, я мог бы использовать и STL, но библиотека C ++ также делает то же самое. Кто-нибудь пробовал подобный эксперимент раньше? Делитесь своими взглядами.

EDIT

Это пример кода, который вы также можете проверить сами:

#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 ]

12 голосов
/ 11 августа 2009
QByteArray text = QByteArray::fromHex("517420697320677265617421");
text.data();            // returns "Qt is great!" 
8 голосов
/ 11 августа 2009

Если ваш 0x05 конвертируется в char '\x05', то у вас не шестнадцатеричные значения (это имеет смысл, если у вас все равно есть числа в виде строк), но двоичные. В C и C ++ char - это просто еще один целочисленный тип с очень небольшим количеством добавленной магии. Так что, если у вас есть 5 и вы присвоите его char, вы получите любой символ, который кодировка вашей системы определяет как пятый символ. (В ASCII это будет символ ENQ, что бы это ни значило в наши дни.)

Если вместо этого вам нужен символ '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"

Конечно, библиотека C std также предоставляет функции для этого преобразования. Если потоковая передача слишком медленная для вас, вы можете попробовать это.

0 голосов
/ 11 августа 2009

Как я вижу, вы хотите исключить контрольные символы 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;
}

Приведенный выше код выводит на консоль следующее:

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*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
0 голосов
/ 11 августа 2009

Я думаю, что строковые классы c ++ обычно предназначены для обработки нулевых последовательностей символов. Если ваши данные имеют известную длину (как кажется), вы можете использовать std :: vector. Это обеспечит некоторые функциональные возможности строкового класса, игнорируя при этом пустые значения в данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...