0

ストリームから次の 2 つの 16 進数文字を取得し、それらを関連付けられた 16 進数 -> 10 進数の数値として char に格納したいと思います。

したがって、入力ファイルに が含まれている場合、2a3123を取得して2a、数値 (10 進数の 42) を char に格納します。

私はもう試した

char c;
instream >> std::setw(2) >> std::hex >> c;

しかし、これは私にゴミを与えます( に置き換えるcと、intの最大値が得られますsigned int)。

どんな助けでも大歓迎です!ありがとう!

編集:文字は文字の適切な範囲内にあることが保証されており、ファイルは有効な16進数であることに注意してください。

4

2 に答える 2

3

OK ASCII デコードを扱うことはまったく悪い考えであり、実際には質問に答えていないと思います。

orを読んだときにのみsetw()orが機能するため、コードが機能しないと思います。推しはここからistream::width()std::stringchar*

標準の C++ iostream コンバーターの長所をどれだけ活用できるか。stringstreamクラスstringをバッファとして使用するアイデアを思いつきました。n問題は、文字をバッファに読み込みstringstream、コンバータ機能として使用することです。

これが最適なバージョンかどうかはわかりません。おそらくそうではありません。

コード:

#include <iostream>
#include <sstream>

int main(void){
    int c;
    std::string buff;
    std::stringstream ss_buff;
    std::cin.width(2);
    std::cin >> buff;
    ss_buff << buff;
    ss_buff >> std::hex >> c;
    std::cout << "read val: " << c << '\n';
}

結果:

luk32@genaker:~/projects/tmp$ ./a.out 
0a10
read val: 10
luk32@genaker:~/projects/tmp$ ./a.out 
10a2
read val: 16
luk32@genaker:~/projects/tmp$ ./a.out 
bv00   
read val: 11
luk32@genaker:~/projects/tmp$ ./a.out 
bc01
read val: 188
luk32@genaker:~/projects/tmp$ ./a.out
01bc
read val: 1

ご覧のとおり、エラー耐性はあまり高くありません。それにもかかわらず、特定の条件で機能し、ループに展開でき、最も重要なのはiostream変換機能を使用するため、ASCII マジックはありません。ただし、C/ASCII の方がおそらく高速です。

PS。改良版。単純なchar[2]バッファーを使用し、フォーマットされていない書き込み/読み取りを使用して、バッファーを介してデータを移動します ( get/writeではなくoperator<</ operator>>)。その理由は非常に単純です。2 バイトのデータを移動するために特別なことは必要ありません。ただし、フォーマットされたエクストラクタを使用して変換を行います。便宜上、ループ版にしました。しかし、それは非常に単純ではありませんでした。非常に重要な行を理解するのに40分かかりました。それらがないと、抽出は最初の 2 文字に対して機能します。

#include <iostream>
#include <sstream>

int main(void){
    int c;
    char* buff = new char[3];
    std::stringstream ss_buff;
    std::cout << "read vals: ";
    std::string tmp;
    while( std::cin.get(buff, 3).gcount() == 2 ){
       std::cout << '(' << buff << ") ";
       ss_buff.seekp(0); //VERY important lines
       ss_buff.seekg(0); //VERY important lines
       ss_buff.write(buff, 2);
       if( ss_buff.fail() ){ std::cout << "error\n"; break;}
       std::cout << ss_buff.str() << ' ';
       ss_buff >> std::hex >> c;
       std::cout << c << '\n';
    }
    std::cout << '\n';
    delete [] buff;
}

出力例:

luk32@genaker:~/projects/tmp$ ./a.out
read vals: 0aabffc
(0a) 0a 10
(ab) ab 171
(ff) ff 255

c意図したとおりに読まれていないことに注意してください。

ここで必要なものがすべて見つかりましたhttp://www.cplusplus.com/reference/iostream/

于 2012-09-20T02:23:45.517 に答える
0

Charをintにキャストすると、intはcharのASCII値を保持します。たとえば、「0」は48、「5」は53になります。文字は上にあるため、「a」は97に、「b」は98にキャストされます。したがって、これを知っていると、int値を取得して減算できます。 48、結果が9より大きい場合は、さらに39を引きます。次に、char0はint0に、char1はint1に、charaはint10に設定され、charbはint11に設定されます。

次に、最初の値に16を掛けて、ビットシフトを考慮して2番目の値に追加する必要があります。2aの例を使用します。

char2はint50にキャストします。48を減算して2を取得します。16を掛けて32を取得します。charaはint97にキャストします。48を減算して49を取得します。これは、9よりも大きいため、さらに39を減算して10を取得します。最後のもの(32)の最終結果で、42を取得します。

コードは次のとおりです。

int HexToInt(char hi, char low)
{
    int retVal = 0;
    int hiBits = (int)hi;
    int loBits = (int)low;
    retVal = Convert(hiBits) * 16 + Convert(loBits);
    return retVal;
}

int Convert(int in)
{
    int retVal = in - 48;
    //If it was not a digit
    if(retVal > 10)
        retVal = retVal - 7;
    //if it was not an upper case hex didgit
    if(retVal > 15)
        retVal = retVal - 32;
    return retVal;  
}

したがって、最初の関数は実際には1行で記述できます。

 int HexToInt(char hi, char low)
 {
    return Convert((int)hi) * 16 + Convert((int)low);       
 }

注:これは小文字のみを考慮し、ASCIIを使用するシステム、つまりIBMebcdicベースのシステムでは機能しません。

于 2012-09-20T01:56:08.030 に答える