我想从流中获取接下来的两个十六进制字符,并将它们存储为char中关联的关联hex->十进制数值。
因此,如果输入文件包含2a3123
,我想抓取2a
,并将数值(小数42)存储在字符中。
我试过
char c;
instream >> std::setw(2) >> std::hex >> c;
但是这给了我垃圾(如果我用c
替换int
,我会得到signed int
的最大值。
任何帮助将不胜感激!谢谢!
编辑:我应该注意,字符保证在字符的适当范围内,并且文件是有效的十六进制。
答案 0 :(得分:3)
好吧我认为处理ASCII解码根本就不是一个坏主意,并没有真正回答这个问题。
我认为您的代码不起作用,因为setw()
或istream::width()
仅在您阅读std::string
或char*
时有效。我猜它来自here
您如何使用标准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/
答案 1 :(得分:0)
您可以将Char转换为int,int将保存char的ascii值。例如,'0'将为48,'5'将为53.字母出现更高,因此'a'将被转换为97,'b'将转换为98等。所以知道这一点你可以取int值并减去48,如果结果大于9,则减去另一个39.然后char 0将转为int 0,char 1转为int 1,一直到char a被设置为int 10,char b被转换为int 11等。
接下来,您需要将第一个值乘以16,然后将其加到第二个值以考虑位移。使用2a的例子。
char 2施放到int 50.减去48并得到2.乘以16得到32。 char a casts to int 97.减去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;
}
第一个函数实际上可以写成一行:
int HexToInt(char hi, char low)
{
return Convert((int)hi) * 16 + Convert((int)low);
}
注意:这仅用于小写字母,仅适用于使用ASCII的系统,即不基于IBM ebcdic的系统。