我正在尝试编写一个输入 - 十六进制,八进制和小数 - 的程序,将它们存储在整数变量中,并将它们与它们转换为十进制形式一起输出。例如:
用户输入:0x43,0123,65
节目输出:
0x43 hexadecimal converts to 67 decimal
0123 octal converts to 83 decimal
65 decimal converts to 65 decimal
所以显然我需要一种解释数字的方法,但我不知道如何去做。我尝试了各种方法,例如将它们读入函数并将它们转换为字符串,反之亦然(请参阅here代码示例),但解释数字总是需要转换为某种格式来破坏原始输入。
我唯一能想到的是重载>>一次读取一个字符的运算符,如果它在输入的开头看到0x或0,那么它在将整个输入读入int之前将其存储到字符串中。然后程序将以某种方式在输出期间确定正确的操纵器。
不确定是否有更简单的方法可以做任何帮助。
编辑:这已经解决了,但如果有人有兴趣,我决定发布代码。
#include "std_lib_facilities.h"
void number_sys(string num, string& s)
{
if(num[0] == '0' && (num[1] != 'x' && num[1] != 'X')) s = "octal";
else if(num[0] == '0' && (num[1] == 'x' || num[1] == 'X')) s = "hexadecimal";
else s = "decimal";
}
int main()
{
cout << "Input numbers in hex, dec, or oct. Use 0xx to cancel.\n";
string a;
while(cin >> a){
if(a == "0xx")break;
string atype;
number_sys(a, atype);
int anum = strtol(a.c_str(), NULL, 0);
cout << a << setw(20-a.length()) << atype << setw(20) << "converts to" << setw(10)
<< anum << setw(10) << "decimal\n";
}
keep_window_open();
}
答案 0 :(得分:11)
看一下strtol函数。
char * args[3] = {"0x43", "0123", "65"};
for (int i = 0; i < 3; ++i) {
long int value = strtol(args[i], NULL, 0);
printf("%s converts to %d decimal\n", args[i], value);
}
输出:
0x43 converts to 67 decimal
0123 converts to 83 decimal
65 converts to 65 decimal
答案 1 :(得分:1)
您始终可以将其存储为要启动的字符串,并查看前两个字符以查看它们是否为0x:
std::string num;
std::cin >> num;
if (num[0] == '0' && num[1] == 'x')
{
//handle
}
答案 2 :(得分:1)
我不确定是否有C ++方法可以做到这一点,但是如果你不介意一点C-ishness,你可以将这个东西读成char
数组并使用类似{{{ 1}}。 sscanf(buffer, "%i", &output)
将输入解释为十六进制,八进制或十进制,具体取决于其格式,就像您描述的那样。
编辑:啊,不知道%i
也可以这样做。不理我。
答案 3 :(得分:1)
如果要保留基本信息(十六进制/八进制/十进制),则需要将该信息与整数值本身分开存储,并且需要至少解析输入的前几个字符string(sscanf(),strtol()等不会为你保留这些信息)。
你可以滚动自己的迷你解析器来保存输入库并进行转换(代码偏离我的头顶,未经测试):
char inputStr[MAX_INPUT_LENGTH+1];
char *p;
int result = 0;
char values[128];
/**
* This enumeration serves double duty; it keeps track of what
* base the input was entered in, and it controls the state machine
* used to parse the input; from a didactic POV, this is probably bad form
*/
enum {
eStart,
eHexOrOctal,
eOctal,
eDecimal,
eHexadecimal,
eError
} eBase = eStart;
/**
* Use the values array as a table to map character constants to their corresponding
* integer values. This is safer than using an expression like *p - '0', in
* that it can work with character encodings where digits are not consecutive.
* Yes, this wastes a little space, but the convenience makes
* up for it IMO. There are probably better ways to do this.
*/
values['0'] = 0; values['1'] = 1; values['2'] = 2; values['3'] = 3;
values['4'] = 4; values['5'] = 5; values['6'] = 6; values['7'] = 7;
values['8'] = 8; values['9'] = 9; values['a'] = 10; values['b'] = 11;
values['c'] = 12; values['d'] = 13; values['e'] = 14; values['f'] = 15;
/**
* Insert code to get input string here
*/
for (p = inputStr; *p != 0; p++)
{
/**
* Cycle through each character in the input string, adjusting the state
* of the parser as necessary. Parser starts in the eStart state.
*/
switch(eBase)
{
/**
* Start state -- we haven't parsed any characters yet
*/
case eStart:
if (*p == '0') eBase = eHexOrOctal; // leading 0 means either hex or octal
else if (isdigit(*p))
{
eBase = eDecimal; // leading non-0 digit means decimal
result = values[*p];
}
else eBase = eError; // no other character may start an integer constant
break;
/**
* HexOrOctal -- we've read a leading 0, which could start either a hex or
* octal constant; we need to read the second character to make a determination
*/
case eHexOrOctal:
if (tolower(*p) == 'x') base = eHexadecimal;
else if (isdigit(*p) && *p != '8' && *p != '9')
{
base = eOctal;
result = values[*p];
}
else eBase = eError;
break;
/**
* Octal -- we are parsing an octal constant
*/
case eOctal:
if (isdigit(*p) && *p != '8' && *p != '9')
{
result *= 8;
result += values[*p];
}
else eBase = eError;
break;
/**
* Decimal -- we are parsing a decimal constant
*/
case eDecimal:
if (isdigit(*p))
{
result *= 10;
result += values[*p];
}
else eBase = eError;
break;
/**
* Hexadecimal -- we are parsing a hex constant
*/
case eHexadecimal:
if (isxdigit(*p))
{
result *= 16;
result += values[tolower(*p)];
}
else eBase = eError;
break;
/**
* String is not a properly formatted integer constant in
* any base; once we fall into the error state, we stay there.
*/
case eError:
default:
break;
}
}
if (eBase != eError)
{
printf("input: %s ", inputStr); fflush(stdout);
switch(eBase)
{
case eOctal: printf("octal "); break;
case eHexadecimal: printf("hexadecimal "); break
default: break;
}
fflush(stdout);
printf("converts to %d decimal\n", result);
}
else
{
/** Print a suitable error message here */
}
答案 4 :(得分:0)
如果您确实 使用单个整数变量来存储您显示最终输出所需的所有信息,那么您必须使用整数变量的一部分来存储输入所在的原始基础。否则它不可恢复。