2009-08-11 18 views
3

私は、16進形式でデータを送信している外部デバイスと接続しています。これは16進数からストリングへの変換C++/C/Qt?

> %abcdefg,+xxx.x,T,+yy.yy,T,+zz.zz,T,A*hhCRLF 
  • CR LFは、キャリッジリターンラインフィードである形態である
  • hh->チェックサム
  • % ABCDEFG - >上記パケット内の各文字をとして送信さ

ヘッダ(xx、yy、abcdなどは実際の数字に置き換えられます)。問題は私の最後でconst char *に格納され、暗黙の変換中にチェックサムは0x05が\ 0x05に変換されると言う。ここで\ 0はヌル文字で、私の文字列は終了します。これは正しくないフレームとして認識されます。実装を生のバイト(16進形式で)を処理するように変更することはできますが、別の方法があるかどうかは、バイトの処理を大幅に簡素化するためです。そして、これはプログラマーのためのものです。

また、私はシリアルポートのデータをチェックしました。また、チェックサムの代わりに\0x05に気付きました。着信データを格納するために、私は

//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++の文字列ライブラリも同じことをしています。誰かがこのタイプの実験を試みたことがありますか?あなたの意見を共有してください。

#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(); 
} 
+0

コードタグにエンコードする際にご注意ください。 – rocknroll

+0

出力として取得しようとしていますか?ソース配列 '0x00、0x00、0x03、0x84、0x78、0x9c、0x3b、0x76、0xec、0x18、0xc3、0x31、0x0a、0xf1、0xcc、0x99' –

+0

@ Jla3ep 私はシリアルポートのデータを、私がunsigned char [FIXED SIZE]バッファで読み込んだ場所から取得します。これは私の記事で述べたように文字列に変換します。私が見ているのは、受け取ったデータの\ 0文字や、16進値の前に\ 0を前に付けて暗黙的に変換しない変換を取り除く方法です。 – rocknroll

答えて

8

0x05char'\x05'に変換された場合、16進数の値はありません(numとにかく文字列としてbers)、バイナリです。 CとC++では、charは基本的にまったく別の整数型であり、魔法の追加はほとんどありません。したがって、5があり、これをcharに割り当てると、システムのエンコーディングで定義されている文字が5番目の文字になります。 (ASCIIでは、それはENQ 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" 

もちろん、C stdライブラリはこの変換のための関数も提供します。ストリーミングが遅すぎる場合は、ストリーミングを試してみてください。

+2

1回の投票で回答を得ずに、10,000回の意見を寄せた質問と回答。今まで。 –

+0

@Duncan:確かに、私はこれを見つけるために自分自身に驚いています。これは 'qt'タグのせいだと思います。これは、QtファンがC++標準ライブラリを信用していない傾向があります。 ':)' upvoteに感謝します! – sbi

0

は、私はC++文字列クラスは、通常はゼロ終端文字列を処理するために設計されていると思う:

EDIT

これは、あなたも自分のためにチェックすることができるサンプルコードです。あなたのデータが既知の長さのものであれば、std :: vectorを使うことができます。これは文字列クラスのいくつかの機能を提供しますが、データ内のNULLを無視します。

+0

'std :: string'は実際に' '\ 0' 'を含むcharシーケンスを扱うことができます。 – sbi

+0

「非常によく」を定義します。真ん中にnullを持つ9文字の文字列を作成します - "abcd \ 0efgh"文字列のすべての操作は、最初の4文字のみを考慮します。長さは4などを返します。 –

+2

これはそうではありません。std :: stringは実際にはバイナリデータを保持できます。たとえば、上記の例ではstr.size()は9を返します。 – igor

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

char *やconst char *: – rocknroll

+0

ありがとうございますので、あなたが提案したtext.data()と同じ問題があります。これは私をたくさん助けました。 – Preetam

0

制御ASCIIシンボルを削除したいと思っています。あなたは次のようにそれを行うことができます:

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*. 

#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; 
} 

上記のコードは、コンソールで次の印刷します

+0

そこに問題jlaepがある。私はA *の後に5が欲しかったし、それは印刷された。 "あなたは今問題を理解していますか? 5は0x05として与えられているが、印刷されていないチェックサムです – rocknroll

+0

例えばチェックサムが0x49の場合、印刷すると思われるものは何ですか? 「私」か「49」? –

+0

文字1を出力すると期待しています – rocknroll

関連する問題