Convert Hex String to Hex Value - c++

I have a large hex string
abcdef...
and I want to convert it to
0xab 0xcd 0xef
Are there any functions that do that?
Also could you tell me what I means when people ask are those inputs in ASCII or not?
abcdef are represented as a string. Not sure if that is ASCII or not. not sure what they mean. I am very new to programming so help here would be appreciated. I have a huge string that I need to use in my array and converting it into the aforementioned format will help me initialize my array with the hex string.

You can do this using string streams.
#include <iostream>
#include <sstream>
#include <vector>
int main( int , char ** )
{
const char *str = "AFAB2591CFB70E77C7C417D8C389507A5";
const char *p1 = str;
const char *p2 = p1;
std::vector<unsigned short> output;
while( *p2 != NULL ) {
unsigned short byte;
++p2;
if( *p2 != NULL ) {
++p2;
}
std::stringstream sstm( std::string( p1, p2 ) );
sstm.flags( std::ios_base::hex );
sstm >> byte;
output.push_back( byte );
p1 += 2;
}
for( std::vector<unsigned short>::const_iterator it = output.begin(); it != output.end(); ++it ) {
std::cout << std::hex << std::showbase << *it << "\t" << std::dec << std::noshowbase << *it << "\n";
}
std::cout << "Press any key to continue ...";
std::cin.get();
}
Note that if you use unsigned char instead of unsigned short the conversion from stringstream attempts to convert it into an ASCII character and it doesn't work.

Read in each character one by one and convert it to a hex value (which is pretty easy).
You then need to, before reading the next number multiply the value by 16 (or, indeed, shift it left by 4) and read the next digit before adding it to the number you have so far. Keep going until you reach the end of your string.
When someone asks if they inputs are ASCII they are referring to whether your hex string is encoded using ASCII encoding. There are, equally various other encoding methods that range from the obsolete EBCDIC to the far more modern Unicode (which has different encodings which are still all unicode).
Bear in mind that the numbers 0 to 9, a to f and A to F have ASCII (or indeed unicode) values that are after one another in the encoding. So for numbers you can calculate its REAL value by doing "character - '0'". For 0 this will give you 0 and up to 9 it will give you 9 ...

the kit of parts you need in C is
for (..,i+=2)
and
strtoul(..,16)

Approximately the following (I wish I could made it shorter and use some library functions, any ideas?):
The function string_to_vector takes a character string and its length as input. It goes over the string, processing two characters (str[ i ] and str[ i + 1 ]) at a time. (For odd values of n, the last pass process only one character (str[ i ] though.) Each character is converted to numeric value using the hex_char_to_int method. Then it constructs a number by "joining" the two numeric values by shifting and adding. Finally, the constructed numeric value is appended to a vector of numeric values which is returned at the end of the function.
std::vector< unsigned >
string_to_vector( const char * str, size_t n ) {
std::vector< unsigned > result;
for( size_t i = 0; i < n; i += 2 ) {
unsigned number = hex_char_to_int( str[ i ] ); // most signifcnt nibble
if( (i + 1) < n ) {
unsigned lsn = hex_char_to_int( str[ i + 1 ] ); // least signt nibble
number = (number << 4) + lsn;
}
result.push_back( number );
}
return result;
}
The following function converts characters in the range [0-9A-Za-z] to the corresponding unsigned int value.
unsigned
hex_char_to_int( char c ) {
unsigned result = -1;
if( ('0' <= c) && (c <= '9') ) {
result = c - '0';
}
else if( ('A' <= c) && (c <= 'F') ) {
result = 10 + c - 'A';
}
else if( ('a' <= c) && (c <= 'f') ) {
result = 10 + c - 'a';
}
else {
assert( 0 );
}
return result;
}

Related

Store HEX char array in byte array with out changing to ASCII or any thing else

My char array is "00000f01" and I want it to be like byte out[4]={0x00,0x00,0x0f,0x01}; I tried the code sent by #ChrisA and thanks to him the Serial.println( b,HEX ); shows exactly what I need but 1st I can not access this output array because when I try to print "out" array it seems empty I also tried this code:
void setup() {
Serial.begin(9600);
char arr[] = "00000f01";
byte out[4];
byte arer[4];
auto getNum = [](char c){ return c ; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
int co=0;
//Check converted byte values.
for( byte b : out ){
Serial.println( co );
Serial.println( b,HEX );
arer[co]=b;
co++;
}
// Serial.print(getNum,HEX);
// Serial.print(out[4],HEX);
// Serial.print(arer[4],HEX);
/*
none of this codes commented above worked*/
}
void loop() {
}
but it is not working neither. please help me.
The title of your question leads me to believe there's something missing in either your understanding of char arrays or the way you've asked the question. Often people have difficulty understanding the difference between a hexadecimal character or digit, and the representation of a byte in memory. A quick explanation:
Internally, all memory is just binary. You can choose to represent (ie. display it) it in bits, ASCII, decimal or hexadecimal, but it doesn't change what is stored in memory. On the other hand, since memory is just binary, characters always require a character encoding. That can be unicode or other more exotic encodings, but typically it's just ASCII. So if you want a string of characters, whether they spell out a hexadecimal number or a sentence or random letters, they must be encoded in ASCII.
Now the body of the question can easily be addressed:
AFAIK, there's no way to "capture" the output of Serial.println( b,HEX ) pragmatically, so you need to find another way to do your conversion from hex characters. The getNum() lambda provides the perfect opportunity. At the moment it does nothing, but if you adjust it so the character '0' turns into the number 0, and the character 'f' turns in to the number 15, and so on, you'll be well on your way.
Here's a quick and dirty way to do that:
void setup() {
Serial.begin(9600);
char arr[] = "00000f01";
byte out[4];
byte arer[4];
auto getNum = [](char c){ return (c <= '9' ? c-'0' : c-'a'+10) ; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
int co=0;
//Check converted byte values.
for( byte b : out ){
Serial.println( co );
if(b < 0x10)
Serial.print('0');
Serial.println( b,HEX );
arer[co]=b;
co++;
}
}
void loop() {
}
All I've done is to modify getNum so it returns 0 for '0' and 15 for 'f', and so on in between. It does so by subtracting the value of the character '0' from the characters '0' through '9', or subtracting the value of the character 'a' from the characters 'a' through 'f'. Fortunately, the value of the characters '0' through '9' go up by one at a time, as do the characters from 'a' to 'f'. Note this will fall over if you input 'F' or something, but it'll do for the example you show.
When I run the above code on a Uno, I get this output:
0
00
1
00
2
0F
3
01
which seems to be what you want.
Epilogue
To demonstrate how print functions in C++ can lead you astray as to the actual value of thing you're printing, consider the cout version:
If I compile and run the following code in C++14:
#include <iostream>
#include <iomanip>
#include <string>
typedef unsigned char byte;
int main()
{
char arr[] = "00000f01";
byte out[4];
byte arer[4];
auto getNum = [](char c){ return c ; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
int co=0;
//Check converted byte values.
for( byte b : out ){
std::cout << std::setfill('0') << std::setw(2) << std::hex << b;
arer[co]=b;
co++;
}
}
I get this output:
00000f01
appearing to show that the conversion from hex characters has occurred. But this is only because cout ignores std::hex and treats b as a char to be printed in ASCII. Because the string "00000f01" has '0' as the first char in each pair, which happens to have a hex value (0x30) with zero lower nybble value, the (getNum( *idx++ ) << 4) happens to do nothing. So b will contain the original second char in each pair, which when printed in ASCII looks like a hex string.
I'm not sure what you mean by "... with out changing to ASCII or any thing else" so maybe I'm misunderstanding your question.
Anyway, below is some simple code to convert the hex-string to an array of unsigned.
unsigned getVal(char c)
{
assert(
(c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F'));
if (c - '0' < 10) return c - '0';
if (c - 'A' < 6) return 10 + c - 'A';
return 10 + c - 'a';
}
int main()
{
char arr[] = "c02B0f01";
unsigned out[4];
for (auto i = 0; i < 4; ++i)
{
out[i] = 16*getVal(arr[2*i]) + getVal(arr[2*i+1]);
}
for (auto o : out)
{
std::cout << o << std::endl;
}
}
Output:
192
43
15
1
If you change the printing to
for (auto o : out)
{
std::cout << "0x" << std::hex << o << std::dec << std::endl;
}
the output will be:
0xc0
0x2b
0xf
0x1

Finding possible prefix palindromes

We are given a string S of length N. We have to calculate number of prefixes which can be rearranged into palindromes. E.g: Consider string "abba"- "a", "abb" and "abba" are the prefixes which can be rearranged into palindromes.
My approach:
I tried to use XOR for solving this problem. For example a string containing even number of characters can be made palindrome if the xor of all characters in the string is 0.In case of strings having odd characters, the xor of all characters should be between 97 and 122, i.e a single character.
Here's a part of my code-
string s;
cin>>s;
int a,n;
int ans=1;
n= s.length();
a=s[0];
for (int i=1;i<n;i++)
{
a=a^(s[i]);
if (i%2)
{
if (a==0)
{
ans++;
}
}
else
{
if ((a>=97)&&(a<=122))
{
ans++;
}
}
}
cout<< ans<< "\n";
I tried to run and it runs successfully for some test cases but fails for others. Any idea of what's wrong in this approach?
Better solution, based on the comments from OP:
#include <string>
#include <iostream>
#include <cctype>
int main() {
std::string input;
std::cin >> input;
unsigned char_xor = input[ 0 ];
unsigned pal = 1; // number of palindromes (initialized to 1,
// since a singular letter is always a
// palindrome)
for ( std::string::size_type i = 0; input.size() >= i; ++i ) {
char_xor ^= input[ i + 1 ];
// check whether length of current prefix is:
// - odd: check whether it is a lowercase character
// - even: check whether it is equal to 0
if ( ( i % 2 && std::islower( char_xor ) ) ||
( !( i % 2 ) && !char_xor ) ) {
++pal;
}
}
std::cout << "Amount of possible palindromes: " << pal << std::endl;
return 0;
}
The following assumption is incorrect (see comments below).
As having understood from
a string containing even number of characters can be made palindrome if the xor of all characters in the string is 0.In case of strings having odd characters, the xor of all characters should be between 97 and 122
you're making a mistake in checking whether the computed XOR is equal to 0/between 97 and 122 on each iteration (after XORing each character), whereas you should be checking it after iterating over the whole std::string. The following works with your given example of "abba" and, for instance, "aaaadcasdasdaffaaa" (having produced 12):
#include <string>
#include <iostream>
#include <cctype>
bool can_be_palindrome( const std::string& str ) {
unsigned char_xor = str[ 0 ];
// compute the xor of all characters
for ( std::string::size_type i = 1; str.size() != i; ++i ) {
char_xor ^= str[ i ];
}
// determine whether the input string has an even number of characters;
// if so, return whether char_xor is equal to 0;
// if not, return whether char_xor is a lowercase letter.
return !( str.size() % 2 ) ? !char_xor : std::islower( char_xor );
}
int main() {
std::string input;
std::cin >> input;
unsigned pal = 1; // number of palindromes (initialized to 1, since a
// singular letter is always a palindrome)
for ( std::string::size_type i = 2; input.size() >= i; ++i ) {
// extract a prefix from the range [0; i) and determine whether it
// can become a palindrome
if ( can_be_palindrome( input.substr( 0, i ) ) ) {
++pal;
}
}
std::cout << "Amount of possible palindromes: " << pal << std::endl;
return 0;
}

How to store in a string and convert to character array?

Write a C++ program to perform addition of two hexadecimal numerals which are less than 100 digits long. Use arrays to store hexadecimal numerals as arrays of characters.the solution is to add the corresponding digits in the format of hexadecimal directly. From right to left, add one to the digit on the left if the sum of the current digits exceed 16. You should be able to handle the case when two numbers have different digits.
The correct way to get the input is to store as character array. You can either first store in a string and convert to character array, or you can use methods such as cin.getline(), getc(), cin.get() to read in the characters.
I don't know what is wrong with my program and it I don't know how to use the function getline() and 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;
}
}
}
Lets look at what cin.getline does:
Extracts characters from stream until end of line. After constructing
and checking the sentry object, extracts characters from *this and
stores them in successive locations of the array whose first element
is pointed to by s, until any of the following occurs (tested in the
order shown):
end of file condition occurs in the input sequence (in which case setstate(eofbit) is executed)
the next available character c is the delimiter, as determined by Traits::eq(c, delim). The delimiter is extracted (unlike basic_istream::get()) and counted towards gcount(), but is not stored.
count-1 characters have been extracted (in which case setstate(failbit) is executed).
If the function extracts no characters (e.g. if count < 1), setstate(failbit)
is executed. In any case, if count>0, it then stores a null character
CharT() into the next successive location of the array and updates
gcount().
The result of that is in all cases, s now points to a null terminated string, of at most count-1 characters.
In your usage, you have up to 99 digits, and can use strlen to count exactly how many. eof is not a character, nor it is a member function of char.
You then reverse in place the inputs, and go about your overly repetitious conversions.
However, it's much simpler to use functions, both those you write yourself and those provided by the standard.
// 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();
}
Regarding the text of your problem: “add one to the digit on the left if the sum of the current digits exceed 16” is wrong; it should be 15, not 16.
Regarding your code: I did not have the patience to read all your code, however:
I have noticed one long if/else. Use a switch (but you do not need one).
To find out if a character is a hex digit use isxdigit (#include <cctype>).
The user might input uppercase and lowercase characters: convert them to the same case using toupper/tolower.
To convert a hex digit to an integer:
if the digit is between ‘0’ and ‘9’ simply subtract ‘0’. This works because the codes for ‘0’, ‘1’… are 0x30, 0x31... (google ASCII codes).
if the digit is between ‘A’ and ‘F’, subtract ‘A’ and add 10.
Solving the problem:
“less than 100 digits long” This is a clear indication regarding how your data must be stored: a simple 100 long array, no std::string, no std::vector:
#define MAX_DIGITS 100
typedef int long_hex_t[MAX_DIGITS];
In other words your numbers are 100 digits wide, at most.
Decide how you store the number: least significant digit first or last? I would chose to store the least significant first. 123 is stored as {3,2,1,0,…0}
Use functions to simplify your code. You will need three functions: read, print and 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;
}
The easiest function to write is add followed by print and read.
For read use get and putback to analyze the input stream: get extracts the next character from stream and putback is inserting it back in stream (if we do not know how to handle it).
Here it is a full solution (try it):
#include <iostream>
#include <cctype>
#define MAX_DIGITS 100
typedef int long_hex_t[MAX_DIGITS];
void add( long_hex_t c, long_hex_t a, long_hex_t b )
{
int carry = 0;
for ( int i = 0; i < MAX_DIGITS; ++i )
{
int t = a[i] + b[i] + carry;
c[i] = t % 16;
carry = t / 16;
}
}
void print( long_hex_t h )
{
//
int i;
// skip leading zeros
for ( i = MAX_DIGITS - 1; i >= 0 && h[i] == 0; --i )
;
// all zero
if ( i < 0 )
{
std::cout << '0';
return;
}
// print remaining digits
for ( i; i >= 0; --i )
std::cout << char( h[i] < 10 ? h[i] + '0' : h[i] - 10 + 'A' );
}
void read( long_hex_t h )
{
// skip ws
std::ws( std::cin );
// skip zeros
{
char c;
while ( std::cin.get( c ) && c == '0' )
;
std::cin.putback( c );
}
//
int count;
{
int i;
for ( i = 0; i < MAX_DIGITS; ++i )
{
char c;
if ( !std::cin.get( c ) )
break;
if ( !std::isxdigit( c ) )
{
std::cin.putback( c );
break;
}
c = std::toupper( c );
h[i] = c <= '9'
? ( c - '0' )
: ( c - 'A' + 10 );
}
count = i;
}
// reverse
for ( int i = 0, ri = count - 1; i < count / 2; ++i, --ri )
{
int t = h[i];
h[i] = h[ri];
h[ri] = t;
}
// fill the rest with zero
for ( int i = count; i < MAX_DIGITS; ++i )
h[i] = 0;
}
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;
}
This is a long answer. Because you have much bug in your code. Your using of getline is ok. But your are calling a eof() like e.eof() which is wrong. If you have looked at your compilation error, you would see that it was complaining about calling eof() on the variable e because it is of non-class type. Simple meaning it is not an object of some class. You cannot put the dot operator . on primitive types like that. I think what you are wanting to do, is to terminate the loop when you have reached the end of line. So that index1 and index2 can get the length of the string input. If I were you, I would just use C++ builtin strlen() function for that. And in the first place, you should use C++ class string to handle strings. Also strings have a null - terminating character '\0' at the end of them. If you don't know about it, I suggest you take some time to read about strings.
Secondly, you have many bugs and errors in your code. The way you are reversing your string is not correct. Ask yourself, what are the contents of the arrays a and b at position which have higher index than the length of the string? You should use reverse() for reversing strings and arrays.
You have errors on adding loop also. Note, you are changing the arrays value when they are A, B, C, D, and so on for hexadecimal values with the corresponding decimal values 10,11,12,13 and so on. But you should change the values for the character '0' - '9' also. Because when the array holds '0' it is not integer 0. But is is ASCII '0' which has integer value of 48. And the character '1' has integer value of 49 and so on. You want to replace this values with corresponding integer values also. When you are also storing the result values in c, you are only handling only those values which are above 9 and replacing them with corresponding characters. You should also replace the integers 0 - 9 with there corresponding ASCII characters. Also don't forget to put a null terminating character at the end of the result.
Also, when p is getting larger than 15, you are only changing your carry, but you should also change p accordingly.
I believe you can reverse the result array c in a much more elegant way. By only reversing when the calculation has been performed totally. You can simple call reverse() for that.
I believe you can think hard a little bit more, and write the code in the right way. I have a few suggestions for you, don't use variable names like a,b,c,o. Try to name variables with what are they really doing. Also, you can improve your algorithm and shorten your code and headache with one simple change in the algorithm. First find the length of a and then find the length of b. If there lengths are unequal, find out which has lesser length. Then add 0s in front of it to make both lengths equal. Now, you can simply start from the back, and perform the addition. Also, you should use builtin methods like reverse() , swap() and also string class to make your life easier ;)
#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;
}

Converting array of char into array of integers? [duplicate]

How could I change an array of character (string) to an integer number without using any ready function (ex atoi();) for example :-
char a[5]='4534';
I want the number 4534 , How can I get it ?
Without using any existing libraries, you have to:
Convert character to numeric digit.
Combine digits to form a number.
Converting character to digit:
digit = character - '0';
Forming a number:
number = 0;
Loop:
number = number * 10 + digit;
Your function will have to check for '+' and '-' and other non-digits characters.
First of all this statement
char a[5]='4534';
will not compile. I think you mean
char a[5]="4534";
^^ ^^
To convert this string to a number is enough simple.
For example
int number = 0;
for ( const char *p = a; *p >= '0' && *p <= '9'; ++p )
{
number = 10 * number + *p - '0';
}
Or you could skip leading white spaces.
For example
int number = 0;
const char *p = s;
while ( std::isspace( ( unsigned char )*p ) ) ++p;
for ( ; *p >= '0' && *p <= '9'; ++p )
{
number = 10 * number + *p - '0';
}
If the string may contain sign '+' or '-' then you can check at first whether the first character is a sign.
You can go like this
It's working
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
char a[5] = "4534";
int converted = 0;
int arraysize = strlen(a);
int i = 0;
for (i = 0; i < arraysize ; i++)
{
converted = converted *10 + a[i] - '0';
}
printf("converted= %d", converted);
return 0;
}
I prefer to use the std::atoi() function to convert string into a number data type. In your example you have an non-zero terminated array "\0", so the function will not work with this code.
Consider to use zero terminated "strings", like:
char *a = "4534";
int mynumber = std::atoi( a ); // mynumber = 4534

Octal conversion using loops in C++

I am currently working on a basic program which converts a binary number to an octal. Its task is to print a table with all the numbers between 0-256, with their binary, octal and hexadecimal equivalent. The task requires me only to use my own code (i.e. using loops etc and not in-built functions). The code I have made (it is quite messy at the moment) is as following (this is only a snippit):
int counter = ceil(log10(fabs(binaryValue)+1));
int iter;
if (counter%3 == 0)
{
iter = counter/3;
}
else if (counter%3 != 0)
{
iter = ceil((counter/3));
}
c = binaryValue;
for (int h = 0; h < iter; h++)
{
tempOctal = c%1000;
c /= 1000;
int count = ceil(log10(fabs(tempOctal)+1));
for (int counter = 0; counter < count; counter++)
{
if (tempOctal%10 != 0)
{
e = pow(2.0, counter);
tempDecimal += e;
}
tempOctal /= 10;
}
octalValue += (tempDecimal * pow(10.0, h));
}
The output is completely wrong. When for example the binary code is 1111 (decimal value 15), it outputs 7. I can understand why this happens (the last three digits in the binary number, 111, is 7 in decimal format), but can't be able to identify the problem in the code. Any ideas?
Edit: After some debugging and testing I figured the answer.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
while (true)
{
int binaryValue, c, tempOctal, tempDecimal, octalValue = 0, e;
cout << "Enter a binary number to convert to octal: ";
cin >> binaryValue;
int counter = ceil(log10(binaryValue+1));
cout << "Counter " << counter << endl;
int iter;
if (counter%3 == 0)
{
iter = counter/3;
}
else if (counter%3 != 0)
{
iter = (counter/3)+1;
}
cout << "Iterations " << iter << endl;
c = binaryValue;
cout << "C " << c << endl;
for (int h = 0; h < iter; h++)
{
tempOctal = c%1000;
cout << "3 digit binary part " << tempOctal << endl;
int count = ceil(log10(tempOctal+1));
cout << "Digits " << count << endl;
tempDecimal = 0;
for (int counterr = 0; counterr < count; counterr++)
{
if (tempOctal%10 != 0)
{
e = pow(2.0, counterr);
tempDecimal += e;
cout << "Temp Decimal value 0-7 " << tempDecimal << endl;
}
tempOctal /= 10;
}
octalValue += (tempDecimal * pow(10.0, h));
cout << "Octal Value " << octalValue << endl;
c /= 1000;
}
cout << "Final Octal Value: " << octalValue << endl;
}
system("pause");
return 0;
}
This looks overly complex. There's no need to involve floating-point math, and it can very probably introduce problems.
Of course, the obvious solution is to use a pre-existing function to do this (like { char buf[32]; snprintf(buf, sizeof buf, "%o", binaryValue); } and be done, but if you really want to do it "by hand", you should look into using bit-operations:
Use binaryValue & 3 to mask out the three lowest bits. These will be your next octal digit (three bits is 0..7, which is one octal digit).
use binaryValue >>= 3 to shift the number to get three new bits into the lowest position
Reverse the number afterwards, or (if possible) start from the end of the string buffer and emit digits backwards
It don't understand your code; it seems far too complicated. But one
thing is sure, if you are converting an internal representation into
octal, you're going to have to divide by 8 somewhere, and do a % 8
somewhere. And I don't see them. On the other hand, I see a both
operations with both 10 and 1000, neither of which should be present.
For starters, you might want to write a simple function which converts
a value (preferably an unsigned of some type—get unsigned
right before worrying about the sign) to a string using any base, e.g.:
//! \pre
//! base >= 2 && base < 36
//!
//! Digits are 0-9, then A-Z.
std::string convert(unsigned value, unsigned base);
This shouldn't take more than about 5 or 6 lines of code. But attention,
the normal algorithm generates the digits in reverse order: if you're
using std::string, the simplest solution is to push_back each digit,
then call std::reverse at the end, before returning it. Otherwise: a
C style char[] works well, provided that you make it large enough.
(sizeof(unsigned) * CHAR_BITS + 2 is more than enough, even for
signed, and even with a '\0' at the end, which you won't need if you
return a string.) Just initialize the pointer to buffer +
sizeof(buffer), and pre-decrement each time you insert a digit. To
construct the string you return:
std::string( pointer, buffer + sizeof(buffer) ) should do the trick.
As for the loop, the end condition could simply be value == 0.
(You'll be dividing value by base each time through, so you're
guaranteed to reach this condition.) If you use a do ... while,
rather than just a while, you're also guaranteed at least one digit in
the output.
(It would have been a lot easier for me to just post the code, but since
this is obviously homework, I think it better to just give indications
concerning what needs to be done.)
Edit: I've added my implementation, and some comments on your new
code:
First for the comments: there's a very misleading prompt: "Enter a
binary number" sounds like the user should enter binary; if you're
reading into an int, the value input should be decimal. And there are
still the % 1000 and / 1000 and % 10 and / 10 that I don't
understand. Whatever you're doing, it can't be right if there's no %
8 and / 8. Try it: input "128", for example, and see what you get.
If you're trying to input binary, then you really have to input a
string, and parse it yourself.
My code for the conversion itself would be:
//! \pre
//! base >= 2 && base <= 36
//!
//! Digits are 0-9, then A-Z.
std::string toString( unsigned value, unsigned base )
{
assert( base >= 2 && base <= 36 );
static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[sizeof(unsigned) * CHAR_BIT];
char* dst = buffer + sizeof(buffer);
do
{
*--dst = digits[value % base];
value /= base;
} while (value != 0);
return std::string(dst, buffer + sizeof(buffer));
}
If you want to parse input (e.g. for binary), then something like the
following should do the trick:
unsigned fromString( std::string const& value, unsigned base )
{
assert( base >= 2 && base <= 36 );
static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned results = 0;
for (std::string::const_iterator iter = value.begin();
iter != value.end();
++ iter)
{
unsigned digit = std::find
( digits, digits + sizeof(digits) - 1,
toupper(static_cast<unsigned char>( *iter ) ) ) - digits;
if ( digit >= base )
throw std::runtime_error( "Illegal character" );
if ( results >= UINT_MAX / base
&& (results > UINT_MAX / base || digit > UINT_MAX % base) )
throw std::runtime_error( "Overflow" );
results = base * results + digit;
}
return results;
}
It's more complicated than toString because it has to handle all sorts
of possible error conditions. It's also still probably simpler than you
need; you probably want to trim blanks, etc., as well (or even ignore
them: entering 01000000 is more error prone than 0100 0000).
(Also, the end iterator for find has a - 1 because of the trailing
'\0' the compiler inserts into digits.)
Actually I don't understand why do you need so complex code to accomplish what you need.
First of all there is no such a thing as conversion from binary to octal (same is true for converting to/from decimal and etc.). The machine always works in binary, there's nothing you can (or should) do about this.
This is actually a question of formatting. That is, how do you print a number as octal, and how do you parse the textual representation of the octal number.
Edit:
You may use the following code for printing a number in any base:
const int PRINT_NUM_TXT_MAX = 33; // worst-case for binary
void PrintNumberInBase(unsigned int val, int base, PSTR szBuf)
{
// calculate the number of digits
int digits = 0;
for (unsigned int x = val; x; digits++)
x /= base;
if (digits < 1)
digits = 1; // will emit zero
// Print the value from right to left
szBuf[digits] = 0; // zero-term
while (digits--)
{
int dig = val % base;
val /= base;
char ch = (dig <= 9) ?
('0' + dig) :
('a' + dig - 0xa);
szBuf[digits] = ch;
}
}
Example:
char sz[PRINT_NUM_TXT_MAX];
PrintNumberInBase(19, 8, sz);
The code the OP is asking to produce is what your scientific calculator would do when you want a number in a different base.
I think your algorithm is wrong. Just looking over it, I see a function that is squared towards the end. why? There is a simple mathematical way to do what you are talking about. Once you get the math part, then you can convert it to code.
If you had pencil and paper, and no calculator (similar to not using pre built functions), the method is to take the base you are in, change it to base 10, then change to the base you require. In your case that would be base 8, to base 10, to base 2.
This should get you started. All you really need are if/else statements with modulus to get the remainders.
http://www.purplemath.com/modules/numbbase3.htm
Then you have to figure out how to get your desired output. Maybe store the remainders in an array or output to a txt file.
(For problems like this is the reason why I want to double major with applied math)
Since you want conversion from decimal 0-256, it would be easiest to make functions, say call them int binary(), char hex(), and int octal(). Do the binary and octal first as that would be the easiest since they can represented by only integers.
#include <cmath>
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
char* toBinary(char* doubleDigit)
{
int digit = atoi(doubleDigit);
char* binary = new char();
int x = 0 ;
binary[x]='(';
//int tempDigit = digit;
int k=1;
for(int i = 9 ; digit != 0; i--)
{
k=1;//cout << digit << endl;
//cout << "i"<< i<<endl;
if(digit-k *pow(8,i)>=0)
{
k =1;
cout << "i" << i << endl;
cout << k*pow(8,i)<< endl;
while((k*pow(8,i)<=digit))
{
//cout << k <<endl;
k++;
}
k= k-1;
digit = digit -k*pow(8,i);
binary[x+1]= k+'0';
binary[x+2]= '*';
binary[x+3]= '8';
binary[x+4]='^';
binary[x+5]=i+'0';
binary[x+6]='+';
x+=6;
}
}
binary[x]=')';
return binary;
}
int main()
{
char value[6]={'4','0','9','8','7','9'};
cout<< toBinary(value);
return 0 ;
}