编写一个C ++程序,添加两个长度小于100位的十六进制数字。使用数组将十六进制数字存储为字符数组。解决方案是直接以十六进制格式添加相应的数字。如果当前数字的总和超过16,从右到左,在左边的数字上加一个。当两个数字有不同的数字时,你应该能够处理这个情况。
获取输入的正确方法是存储为字符数组。您可以先存储在字符串中并转换为字符数组,也可以使用cin.getline(),
getc()
,cin.get()
等方法读取字符。
我不知道我的程序有什么问题,而且我不知道如何使用函数getline()
和eof()
char a[number1],b[number1],c[number2],h;
int m,n,p(0),q(0),k,d[number1],z[number1],s[number2],L,M;
cout<<"Input two hexadecimal numerals(both of them within 100 digits):\n";
cin.getline(a,100);
cin.getline(b,100);
int x=strlen(a) ;
int y=strlen(b);
for(int i=0;i<(x/2);i++)
{
m=x-1-i;
h=a[i];
a[i]=a[m];
a[m]=h;
}
for(int j=0;j<(y/2);j++)
{
n=y-1-j;
h=b[j];
b[j]=b[n];
b[n]=h;
}
if(x>y)
{
for(int o=0;o<x;o++)//calculate a add b
{
if(o>=(y-1))
z[o]=0;//let array b(with no character)=0
if(a[o]=='A')
d[o]=10;
else if(a[o]=='B')
d[o]=11;
else if(a[o]=='C')
d[o]=12;
else if(a[o]=='D')
d[o]=13;
else if(a[o]=='E')
d[o]=14;
else if(a[o]=='F')
d[o]=15;
else if(a[o]=='0')
d[o]=0;
else if(a[o]=='1')
d[o]=1;
else if(a[o]=='2')
d[o]=2;
else if(a[o]=='3')
d[o]=3;
else if(a[o]=='4')
d[o]=4;
else if(a[o]=='5')
d[o]=5;
else if(a[o]=='6')
d[o]=6;
else if(a[o]=='7')
d[o]=7;
else if(a[o]=='8')
d[o]=8;
else if(a[o]=='9')
d[o]=9;
if(b[o]=='A')
z[o]=10;
else if(b[o]=='B')
z[o]=11;
else if(b[o]=='C')
z[o]=12;
else if(b[o]=='D')
z[o]=13;
else if(b[o]=='E')
z[o]=14;
else if(b[o]=='F')
z[o]=15;
else if(b[o]=='0')
z[o]=0;
else if(b[o]=='1')
z[o]=1;
else if(b[o]=='2')
z[o]=2;
else if(b[o]=='3')
z[o]=3;
else if(b[o]=='4')
z[o]=4;
else if(b[o]=='5')
z[o]=5;
else if(b[o]=='6')
z[o]=6;
else if(b[o]=='7')
z[o]=7;
else if(b[o]=='8')
z[o]=8;
else if(b[o]=='9')
z[o]=9;
p=d[o]+z[o]+q;
if(p>=16)//p is the remained number
{
q=1;
p=p%16;
}
else
q=0;
if(p==0)
c[o]='0';
else if(p==1)
c[o]='1';
else if(p==2)
c[o]='2';
else if(p==3)
c[o]='3';
else if(p==4)
c[o]='4';
else if(p==5)
c[o]='5';
else if(p==6)
c[o]='6';
else if(p==7)
c[o]='7';
else if(p==8)
c[o]='8';
else if(p==9)
c[o]='9';
else if(p==10)
c[o]='A';
else if(p==11)
c[o]='B';
else if(p==12)
c[o]='C';
else if(p==13)
c[o]='D';
else if(p==14)
c[o]='E';
else if(p==15)
c[o]='F';
}
k=x+1;
if(q==1)//calculate c[k]
{
c[k]='1';
for(int f=0;f<=(k/2);f++)
{
m=k-f;
h=c[f];
c[f]=c[m];
c[m]=h;
}
}
else
{
for(int e=0;e<=(x/2);e++)
{
m=x-e;
h=c[e];
c[e]=c[m];
c[m]=h;
}
}
}
if(x=y)
{
for(int o=0;o<x;o++)//calculate a add b
{
if(a[o]=='A')
d[o]=10;
else if(a[o]=='B')
d[o]=11;
else if(a[o]=='C')
d[o]=12;
else if(a[o]=='D')
d[o]=13;
else if(a[o]=='E')
d[o]=14;
else if(a[o]=='F')
d[o]=15;
else if(a[o]=='0')
d[o]=0;
else if(a[o]=='1')
d[o]=1;
else if(a[o]=='2')
d[o]=2;
else if(a[o]=='3')
d[o]=3;
else if(a[o]=='4')
d[o]=4;
else if(a[o]=='5')
d[o]=5;
else if(a[o]=='6')
d[o]=6;
else if(a[o]=='7')
d[o]=7;
else if(a[o]=='8')
d[o]=8;
else if(a[o]=='9')
d[o]=9;
if(b[o]=='A')
z[o]=10;
else if(b[o]=='B')
z[o]=11;
else if(b[o]=='C')
z[o]=12;
else if(b[o]=='D')
z[o]=13;
else if(b[o]=='E')
z[o]=14;
else if(b[o]=='F')
z[o]=15;
else if(b[o]=='0')
z[o]=0;
else if(b[o]=='1')
z[o]=1;
else if(b[o]=='2')
z[o]=2;
else if(b[o]=='3')
z[o]=3;
else if(b[o]=='4')
z[o]=4;
else if(b[o]=='5')
z[o]=5;
else if(b[o]=='6')
z[o]=6;
else if(b[o]=='7')
z[o]=7;
else if(b[o]=='8')
z[o]=8;
else if(b[o]=='9')
z[o]=9;
p=d[o]+z[o]+q;
M=p;
if(p>=16)
{
q=1;
p=p%16;
}
else
q=0;
s[o]=p;
if(p==0)
c[o]='0';
else if(p==1)
c[o]='1';
else if(p==2)
c[o]='2';
else if(p==3)
c[o]='3';
else if(p==4)
c[o]='4';
else if(p==5)
c[o]='5';
else if(p==6)
c[o]='6';
else if(p==7)
c[o]='7';
else if(p==8)
c[o]='8';
else if(p==9)
c[o]='9';
else if(p==10)
c[o]='A';
else if(p==11)
c[o]='B';
else if(p==12)
c[o]='C';
else if(p==13)
c[o]='D';
else if(p==14)
c[o]='E';
else if(p==15)
c[o]='F';
}
k=x+1;
if(q==1)
{
c[k]='1';
for(int f=0;f<=(k/2);f++)
{
m=k-f;
h=c[f];
c[f]=c[m];
c[m]=h;
}
}
else
{
for(int e=0;e<=(x/2);e++)
{
m=x-e;
h=c[e];
c[e]=c[m];
c[m]=h;
}
}
}
答案 0 :(得分:2)
让我们看看cin.getline
做了什么:
从流中提取字符直到行尾。建成后 并检查哨兵对象,从* this和中提取字符 将它们存储在第一个元素的数组的连续位置 s指出,直到发生以下任何一种情况(在 订单显示):
- 文件结束条件发生在输入序列中(在这种情况下执行setstate(eofbit))
- 下一个可用字符c是分隔符,由Traits :: eq(c,delim)确定。提取分隔符(与basic_istream :: get()不同)并计入gcount(),但不存储。
- 已提取count-1个字符(在这种情况下执行setstate(failbit))。
如果函数不提取任何字符(例如,如果count <1),则setstate(failbit) 被执行。在任何情况下,如果count> 0,则它存储空字符 CharT()进入数组的下一个连续位置并进行更新 gcount的()。
结果就是在所有情况下,s
现在指向一个以空字符结尾的字符串,最多为count-1
个字符。
在您的使用中,您最多可以使用99位数,并且可以使用strlen
来计算确切数量。 eof
不是字符,也不是char
的成员函数。
然后,您可以反转输入,然后进行过度重复的转换。
然而,使用函数要简单得多,无论是你自己写的还是标准提供的函数。
// translate from '0' - '9', 'A' - 'F', 'a' - 'f' to 0 - 15
static std::map<char, int> hexToDec { { '0', 0 }, { '1', 1 }, ... { 'f', 15 }, { 'F', 15 } };
// translate from 0 - 15 to '0' - '9', 'A' - 'F'
static std::map<int, char> decToHex { { 0, '0' }, { 1, '1' }, ... { 15, 'F' } };
std::pair<char, bool> hex_add(char left, char right, bool carry)
{
// translate each hex "digit" and add them
int sum = hexToDec[left] + hexToDec[right];
// we have a carry from the previous sum
if (carry) { ++sum; }
// translate back to hex, and check if carry
return std::make_pair(decToHex[sum % 16], sum >= 16);
}
int main()
{
std::cout << "Input two hexadecimal numerals(both of them within 100 digits):\n";
// read two strings
std::string first, second;
std::cin >> first >> second;
// reserve enough for final carry
std::string reverse_result(std::max(first.size(), second.size()) + 1, '\0');
// traverse the strings in reverse
std::string::const_reverse_iterator fit = first.rbegin();
std::string::const_reverse_iterator sit = second.rbegin();
std::string::iterator rit = reverse_result.begin();
bool carry = false;
// while there are letters in both inputs, add (with carry) from both
for (; (fit != first.rend()) && (sit != second.rend()); ++fit, ++sit, ++rit)
{
std::tie(*rit, carry) = hex_add(*fit, *sit, carry);
}
// now add the remaining digits of first (will do nothing if second is longer)
for (; (fit != first.rend()); ++fit)
{
// we need to account for a carry in the last place
// potentially all the way up if we are adding e.g. "FFFF" to "1"
std::tie(*rit, carry) = hex_add(*fit, *rit++, carry);
}
// or add the remaining digits of second
for (; (sit != second.rend()); ++sit)
{
// we need to account for a carry in the last place
// potentially all the way up if we are adding e.g. "FFFF" to "1"
std::tie(*rit, carry) = hex_add(*sit, *rit++, carry);
}
// result has been assembled in reverse, so output it reversed
std::cout << reverse_result.reverse();
}
答案 1 :(得分:1)
这是一个很长的答案。因为你的代码中有很多错误。你使用getline是好的。但是你正在调用像e.eof()
这样的eof(),这是错误的。如果你看过你的编译错误,你会发现它抱怨在变量e
上调用eof(),因为它是非类型的。简单的含义它不是某个类的对象。您不能将点运算符.
放在这样的基本类型上。我想你想要做的是,当你到达行尾时终止循环。这样index1和index2就可以得到字符串输入的长度。如果我是你,我会使用C ++内置strlen()
函数。首先,您应该使用C ++类string
来处理字符串。字符串也有一个空终止字符&#39; \ 0&#39;在他们的最后。如果你不了解它,我建议你花些时间阅读字符串。
其次,您的代码中存在许多错误和错误。你反转字符串的方式是不正确的。问问自己,位置上的数组a
和b
的内容是什么,其索引的索引高于字符串的长度?您应该使用reverse()
来反转字符串和数组。
添加循环时也有错误。请注意,对于具有相应小数值10,11的十六进制值,您要更改数组值A
,B
,C
,D
等等, 12,13等。但是你应该改变角色的价值&#39; 0&#39; - &#39; 9&#39;也。因为当数组保持&#39; 0&#39;它不是整数0.但是ASCII是&#39; 0&#39;它的整数值为48.而字符&#39; 1&#39;整数值为49,依此类推。您还希望将此值替换为相应的整数值。当您还将结果值存储在c
中时,您只处理那些大于9的值并用相应的字符替换它们。您还应该用相应的ASCII字符替换整数0 - 9。也不要忘记在结果的末尾添加一个空终止字符。
此外,当p
大于15时,您只是更改了随身携带,但您也应相应更改p
。
我相信你可以以更优雅的方式反转结果数组c
。仅在完全执行计算时进行反转。您可以为此简单地致电reverse()
。
我相信你可以多思考一下,并以正确的方式编写代码。我有一些建议,不要使用变量名,如a,b,c,o。尝试用他们真正做的事来命名变量。此外,您可以通过算法中的一个简单更改来改进算法并缩短代码和头痛。首先找到a
的长度,然后找到b
的长度。如果长度不相等,找出长度较短的长度。然后在它前面添加0以使两个长度相等。现在,您可以从后面开始,然后执行添加。此外,您应该使用内置方法,例如reverse()
,swap()
和string
类,以使您的生活更轻松;)
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main(){
string firstVal,secondVal;
cout<<"Input two hexadecimal numerals(both of them within 100 digits):\n";
cin >> firstVal >> secondVal;
//Adjust the length.
if(firstVal.size() < secondVal.size()){
//Find out the number of leading zeroes needed
int leading_zeroes = secondVal.size() - firstVal.size();
for(int i = 0; i < leading_zeroes; i++){
firstVal = '0' + firstVal;
}
}
else if(firstVal.size() > secondVal.size()){
int leading_zeroes = firstVal.size() - secondVal.size();
for(int i = 0; i < leading_zeroes; i++){
secondVal = '0' + secondVal;
}
}
// Now, perform addition.
string result;
int digit_a,digit_b,carry=0;
for(int i = firstVal.size()-1; i >= 0; i--){
if(firstVal[i] >= '0' && firstVal[i] <= '9') digit_a = firstVal[i] - '0';
else digit_a = firstVal[i] - 'A' + 10;
if(secondVal[i] >= '0' && secondVal[i] <= '9') digit_b = secondVal[i] - '0';
else digit_b = secondVal[i] - 'A' + 10;
int sum = digit_a + digit_b + carry;
if(sum > 15){
carry = 1;
sum = sum % 16;
}
else{
carry = 0;
}
// Convert sum to char.
char char_sum;
if(sum >= 0 && sum <= 9) char_sum = sum + '0';
else char_sum = sum - 10 + 'A';
//Append to result.
result = result + char_sum;
}
if(carry > 0) result = result + (char)(carry + '0');
//Result is in reverse order.
reverse(result.begin(),result.end());
cout << result << endl;
}
答案 2 :(得分:1)
关于问题的文字:“如果当前数字的总和超过16”,则向左边的数字添加1; 它应该是15,而不是16。
关于您的代码:我没有耐心阅读您的所有代码,但是:
if/else
。使用switch
(但您不需要)。isxdigit
(#include <cctype>
)。toupper
/ tolower
将它们转换为相同的大小写。解决问题:
“长度不足100位”这是关于如何存储数据的明确指示:一个简单的100长数组,没有std::string
,没有{{1 }}:
std::vector
换句话说,您的号码最多为100位数。
决定如何存储号码:最低有效数字的第一个还是最后一个?我会选择存储最不重要的第一个。 123存储为{3,2,1,0,... 0}
使用函数简化代码。您需要三个功能:#define MAX_DIGITS 100
typedef int long_hex_t[MAX_DIGITS];
,read
和print
:
add
最简单的写作函数是int main()
{
long_hex_t a;
read( a );
long_hex_t b;
read( b );
long_hex_t c;
add( c, a, b );
print( c );
return 0;
}
,然后是add
和print
。
read
使用read
和get
分析输入流:putback
从流中提取下一个字符,get
将其插入流中(如果我们不知道如何处理它)。
这是完整解决方案(try it):
putback