将带有前导“0x”的十六进制字符串转换为C++中的有符号短字符串?
Posted
技术标签:
【中文标题】将带有前导“0x”的十六进制字符串转换为C++中的有符号短字符串?【英文标题】:Convert hexadecimal string with leading "0x" to signed short in C++? 【发布时间】:2010-12-02 00:39:12 【问题描述】:我找到了使用strtol
将十六进制字符串转换为signed int
的代码,但我找不到短整数(2 个字节)的内容。这是我的一段代码:
while (!sCurrentFile.eof() )
getline (sCurrentFile,currentString);
sOutputFile<<strtol(currentString.c_str(),NULL,16)<<endl;
我的想法是读取具有 2 字节宽值的文件(如 0xFFEE),将其转换为带符号的 int 并将结果写入输出文件。执行速度不是问题。
我可以找到一些方法来避免这个问题,但我想使用“单线”解决方案,所以也许你可以为此提供帮助:)
编辑:文件如下所示:
0x0400
0x03fe
0x03fe
...
编辑:我已经尝试过使用十六进制运算符,但在这样做之前我仍然需要将字符串转换为整数。
// This won't work as currentString is not an integer
myInt << std::hex << currentString.c_str();
【问题讨论】:
您的输入文件是什么样的?如果没有这些信息,很难提出任何建议。 请看 strtol 返回 long , not signed int, sscanf 返回一个 int,但 scanf 系列函数的返回值是它们成功转换的字段数。虽然我很欣赏这种宣传,但你抄错了。 :) edit : 我的错,我想减少代码并且没有看我在做什么 - 这是我工作日的结束:) 看起来 Loki 是唯一真正回答这个问题的人。 【参考方案1】:您是否考虑过带有“%hx”转换限定符的sscanf
?
【讨论】:
或者,如果您没有任何特别需要使用 C++ I/O 流,请直接使用 fscanf... 取决于您控制的代码量。 fscanf 和 sscanf 是我通常处理这个问题的方式。我现在有一个程序可以读取与此类似的 CRC 十六进制字符串:sscanf(cstr_fileCRC, "%lX", &ul_fileCRC); 问题标记为 C++。另外,sscanf
通常不受欢迎,因为它带有与安全相关的问题。【参考方案2】:
您可能可以将stringtream 类的 >> 运算符与十六进制操纵器一起使用。
【讨论】:
正是我需要的,它只有一行大! 你应该提供一个例子。前导0x
似乎会导致解析失败。【参考方案3】:
如果您确定来自currentString.c_str()
的数据可以信任,那么您也可以轻松做到
myInt << std::hex << atoi(currentString.c_str());
【讨论】:
当 C++ 流已经完成所有工作时,为什么还要使用 C 函数。 问题标记为 C++,而不是 C。【参考方案4】:如果您知道数据总是采用这种格式,您就不能这样做:
myInt << std::hex << currentString.c_str() +2; // skip the leading "0x"
【讨论】:
这里 std::hex 在处理字符串时什么都不做。您只是重新打印您读取的字符串(减去前两个字符)。【参考方案5】:这应该很简单:
std::ifstream file("DataFile");
int value;
while(file >> std::hex >> value) // Reads a hex string and converts it to an int.
std::cout << "Value: " << std::hex << value << "\n";
当我们谈论文件时: 您应该不这样做:
while (!sCurrentFile.eof() )
getline (sCurrentFile,currentString);
... STUFF ...
这是因为当您阅读最后一行时,它确实不设置了 EOF。因此,当您循环然后读取最后一行之后的行时,getline() 将失败,您将对 currentString 中的内容从上次设置时开始执行 STUFF。所以实际上你将处理最后一行两次。
循环文件的正确方法是:
while (getline(sCurrentFile,currentString))
// If the get fails then you have read past EOF and loop is not entered.
... STUFF ...
【讨论】:
【参考方案6】:// convert unsigned-integer to it's hexadecimal string represention
// 0x12345678 -> '12345678'
// N is BYTE/WORD/UINT/ULONGLONG
// T is char or wchar_t
template <class N, class T> inline T* UnsignedToHexStr(N n , // [i ]
T* pcStr , // [i/o] filled with string
UINT nDigits , // [i ] number of digits in output string / 0 (auto)
bool bNullTerminate ) // [i ] whether to add NULL termination
if ((N)-1 < (N)1) // if type of N is floating-point / signed-integer
if (::IsDebuggerPresent())
::OutputDebugString(_T("UnsignedToHexStr: Incorrect type passed\n"));
::DebugBreak();
if (!nDigits)
nDigits= GetUnsignedHexDigits(n);
if (1 == sizeof(T))
const char _czIntHexConv[]= "0123456789ABCDEF";
for (int i= nDigits-1; i>= 0; i--)
char* pLoc= (char*)&pcStr[i];
*pLoc= _czIntHexConv[n & 0x0F];
n >>= 4;
else
const wchar_t _czIntHexConv[]= L"0123456789ABCDEF";
for (int i= nDigits-1; i>= 0; i--)
wchar_t* pLoc= (wchar_t*)&pcStr[i];
*pLoc= _czIntHexConv[n & 0x0F];
n >>= 4;
if (bNullTerminate)
pcStr[nDigits]= 0;
return pcStr;
// --------------------------------------------------------------------------
// convert unsigned-integer in HEX string represention to it's numerical value
// '1234' -> 0x1234
// N is BYTE/WORD/UINT/ULONGLONG
// T is char or wchar_t
template <class N, class T> inline bool HexStrToUnsigned(const T* pczSrc ,
N& n ,
bool bSpecificTerminator= false, // whether string should terminate with specific terminating char
T cTerminator = 0 ) // specific terminating char
n= 0;
if (!pczSrc)
return false;
while ((32 == *pczSrc) || (9 == *pczSrc))
pczSrc++;
bool bLeadZeros= *pczSrc == _T('0');
while (*pczSrc == _T('0')) // skip leading zeros
pczSrc++;
BYTE nMaxDigits= 2*sizeof(N);
BYTE nDigits = 0 ;
while (true)
if ( (*pczSrc >= _T('0')) && (*pczSrc <= _T('9')))
if (nDigits==nMaxDigits) return false; n= (n<<4) + (*pczSrc-_T('0') ); pczSrc++; nDigits++; continue;
if ( (*pczSrc >= _T('A')) && (*pczSrc <= _T('F')))
if (nDigits==nMaxDigits) return false; n= (n<<4) + (*pczSrc-_T('A')+10); pczSrc++; nDigits++; continue;
if ( (*pczSrc >= _T('a')) && (*pczSrc <= _T('f')))
if (nDigits==nMaxDigits) return false; n= (n<<4) + (*pczSrc-_T('a')+10); pczSrc++; nDigits++; continue;
if (bSpecificTerminator)
if (*pczSrc != cTerminator)
return false;
break;
return (nDigits>0) || bLeadZeros; // at least one digit
【讨论】:
你显然很生气 :-)以上是关于将带有前导“0x”的十六进制字符串转换为C++中的有符号短字符串?的主要内容,如果未能解决你的问题,请参考以下文章