Converting a [char] variable to [int] then back to [char] - c++

I am using Visual C 6
I am trying to convert a character array (single-quotation) into an integer, then incrementing the value by 1, then storing the result back into a different character array..
But I keep getting an unexpected value when converting back to character..
Here is my code
char char_array[4];
char_array[0] = '1';
char_array[1] = '2';
char_array[2] = '3';
char_array[3] = '\0'; //Terminating character
int my_number = atoi(char_array);
printf("my_number = %d" , my_number); // output is 123
my_number++; // works and my_number is incremented =124
printf("now: my_number = %d" , my_number); // output is 124
char result[4]; //declared to store the result
result = itoa(my_number); // Output is unexpected.
printf("%c", result[0]); // Output is 2 instead of 1
printf("%c", result[1]); // Output is 2
printf("%c", result[2]); // Output as 3 instead of 4
It seems that the function itoa() somehow knows the original value 123 and in some weird way knows that I have incremented that value.. but the addition is done to the wrong digit. Instead of adding 1 to the least significant digit, the addition is done to the most significant digit.

I find it really difficult to believe that your compiler is letting this code through:
char result[4]; //declared to store the result
result = itoa(my_number); // Output is unexpected.
For one reason, you're attempting to reseat an array. Which shouldn't be allowed. For another, itoa() normally takes three arguments. It's prototype should look like:
char *itoa(int value, char * str, int base);
So you should be calling it as:
char result[4];
itoa(my_number, result, 10);
Or, if you'd like to use portable functions that don't have possible buffer overflows:
char result[4];
snprintf(result, 4, "%d", my_number);

itoa is not a standard C library function.
You can use
char result[sizeof(int) * CHAR_BIT / 10 * 3 + 4]; // '-1', '\0', max sizeof int on my 4 byte machine
// 10 bits are roughly equal to 3 digits at decimal base, extra 4 for '-', '\0', extra digit and safe character
sprintf(result, "%d", my_number);
If you still want to use itoa, consult the documentation of this function (in library/compiler documentation)

my_number is incremented and hence if you are using itoa() then it will know the new value of my_number which is 124.
Check the code below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char char_array[4];
char_array[0] = '1';
char_array[1] = '2';
char_array[2] = '3';
char_array[3] = '\0'; //Terminating character
int my_number = atoi(char_array);
printf("my_number = %d" , my_number); // output is 123
my_number++; // works and my_number is incremented =124
printf("now: my_number = %d" , my_number); // output is 124
char result[4]; //declared to store the result
snprintf(result,4,"%d",my_number);
printf("%c", result[0]);
printf("%c", result[1]);
printf("%c", result[2]);
return 0;
}

First the itoa(my_number) maybe wrong, I only know the followed function:
char * itoa ( int value, char * str, int base );
str should be an array long enough to contain any possible value:
(sizeof(int)*8+1) for radix=2 i.e. 17 bytes in 16-bits platforms and
33 in 32-bits platforms.

Related

How to subtract integers from characters in C?

Brian Kernighnan in his book Programming with C says
By definition, chars are just small integers, so char variables and
constants are identical to ints in arithmetic expressions.
Does this mean we can subtract char variable from int ??
I wrote a small piece of code:
#include <stdio.h>
main()
{
int a ;
int c;
a = 1;
c = 1 - '0' ;
printf("%d", c);
}
However it gives me output = -47...
What is that I'm doing wrong ?? Are the variables I assigned have the right type??
The output is to be expected. '0' is a char value that, since your compiler presumably uses the ASCII encoding, has value 48. This is converted to int and subtracted from 1. Which gives the value -47.
So the program does what it is expected to do, just not what you might hope it would do. As for what you are doing wrong, it is hard to say. I'm not sure what you expect the program to do, or what problem you are trying to solve.
The characters from '0'-'9'' have values 48-57 when converted to integer ('0' = 48, '1' = 49 etc). Read more about ASCII Values. When used in numerical calculation, first they are converted to int, so 1- '0' = 1-48 =-47.
You're mixing here the actual operation with the form of representation. printf outputs the data according to the specified format - integer in your case. If you want to print it as a character, switch %d with %c.
What you are doing is treating with the ASCII code of the chars, each char has an ASCII value assigned.
Now, playing a little with the ASCII of each char you can do things like:
int a;
a = 'a' - 'A' ;
printf("%d", a);
And get 32 as output, due to the ASCII value to 'a' = 97 and for 'A' = 65, then you have 97-65 = 32
I think this gives you more clear understanding...
#include <stdio.h>
main()
{
int a ;
a = 1;
printf("%d", char(a+48));
//or printf("%d", char(a+'0'));
}

How to convert a "char number" into an int WITHOUT use of magic numbers? (in C++)

In other words, based on the ASCII table, from the range of '0' to '9',
how may I convert them into integers 0 to 9?
A solution such as:
char a = '6';
int b = a-48;
has already been floating around these parts, but I was wondering if there are other ways to go about this without the use of magic numbers?
Since '0' is not guaranteed to be 48, but the numbers are guaranteed to be consecutive, you can use a-'0'.
If you really want to, you could use a stringstream like this:
#include <string>
#include <sstream>
int charToInt(char c) {
// initialize a buffered stream with a 1-character string
std::stringstream ss(std::string(1,c));
// read an int from the stream
int v;
ss >> v;
return v;
}
Not the simplest way to do the conversion, but this way you don't see any of the implementation details involving "magic" number or character. You also get error handling (an exception is thrown) if the caracter was not a number.
On the other hand, if you're absolutely certain that the character c is in the '0'..'9' range, I don't see why not use c - '0'.
Another solution is to replace c - 48 with c & 0xf, but that still involves magic numbers and is less readable than c - '0'
The ascii table is ordered in an hexadecimal way, so it's very easy to change numbers characters to real number value, or another things like to Uppercase to Lower...
As the numbers begin in the 0x30, then 0x30 =0 , 0x31 = 1, 0x32 =2, etc, you must just remove the 0x30 to get the real value.
char number='2';
int numberValue = (int)number - 0x30; /* you can rest the '0' value too */
As it, to convert an int to char is the same, just add it the 0x30.
int numberValue=5;
char number = (int)numberValue +0x30; /* or add '0' to your var */
Subtract ASCII zero from the number:
char a = '2';
int b = a-'0';
If you can't use '0', how about that kind of cheating?
(int)(a + 2) % 10;
If it's a char, not a char pointer, you can do this:
int convert (char x)
{
return (int(x) - int('0'));
}

how values are stored in char

I am adding values into the combo box as a string. Below is my code.
Platform Windows XP and I am using Microsoft Visual Studio 2003
language C++
error encountered -> "Run-Time Check Failure #2 - Stack around the variable 'buffer' was corrupted."
If I increase the size of the buffer to say 4 and above then I won't get this error.
My question is not related to how to fix that error, but I am wondering why I got this error if buffer size = 2.
According to my logic I have given buffer size = 2 as char[0] will store the valve of char[1] = null terminated character.
Now since char can store values from 0 to 255 , I thought this should be ok as my inserted values are from 1 to 63 and then from 183 to 200.
CComboBox m_select_combo;
const unsigned int max_num_of_values = 63;
m_select_combo.AddString( "ALL" );
for( unsigned int i = 1; i <= max_num_of_values ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
const unsigned int max_num_of_high_sats = 202 ;
for( unsigned int i = 183; i <= max_num_of_high_sats ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
Could you guys please give me an idea as to what I'm not understanding?
itoa() zero-terminates it's output, so when you call itoa(63, char[2], 10) it writes three characters 6, 3 and the terminating \0. But your buffer is only two characters long.
itoa() function is best avoided in favour of snprintf() or boost::lexical_cast<>().
You should read the documentation for itoa.
Consider the following loop:
for( unsigned int i = 183; i <= max_num_of_high_sats ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
The first iteration converts the integer 183 to the 3 character string "183", plus a terminating null character. That's 4 bytes, which you are trying to cram into a two byte array. The docs tell you specifically to make sure your buffer is large enough to hold any value; in this case it should be at least the number of digits in max_num_of_high_sats long, plus one for the terminating null.
You might as well make it large enough to hold the maximum value you can store in an unsigned int, which would be 11 (eg. 10 digits for 4294967295 plus a terminating null).
the ito function is used to convert a int to a C sytle string based on the 3rd parameter base.
As a example, it just likes to print out the int 63 in printf. you need two ASII byte, one is used to storage CHAR 6, the other is used to storage CHAR 3. the 3rd should be NULL. So in your case the max int is three digital. you need 4 bytes in the string
You are converting an integer to ASCII, that is what itoa does. If you have a number like 183 that is four chars as a string, '1', '8', '3', '\0'.
Each character takes one byte, for example character '1' is the value 0x31 in ASCII.

Converting array of type char into a int variable

Compiling this on Codepad:
#include <iostream>
using namespace std;
void main (void)
{
char ch[2];
int value;
cout<<"Enter two integers between 0-9"<<endl;
cin.getline(ch,2);
//testing with char array
//(...)
//how could I do operations like '*', '+', '-', or '/' to the char arrays
}
Gives:
Line 4: error: '::main' must return 'int'
compilation terminated due to -Wfatal-errors.
For example:
Lets say ch[0]='5' and ch[1]='3'
what do I need to do so I can do ch[0] - ch[1] = 2 and store into an int value
You wouldn't have to do anything at all in particular. int x = ch[0] - ch[1] works quite as you would expect it to.
I guess that the original exercise would ask you to get two different integer of probably more than 1 character each.
However, the solution to your problem: ch[0] - ch[1].
Why it works?
Ascii character '0' is character 48.
Ascii character '9' is character 48 + 9
now....
'4' - '3' = (48 + 4) - (48 + 3) = 4 - 3 = 1.
There are a few different problems with the code you've posted. main needs to have a return type of int.
int main() { /* .. */ }
Your call to cin.getline will only fill a single character in the array you've declared, because the function call will null terminate the array. You need
char array[3];
cin.getline( array, 3 );
After that, if array[0] contains '5' and array[1] contains '3', you can simply do
array[0] - array[1]
to get the integer result 2.
If you need to deal with numbers outside the range [0..9] you'll need to convert them to their numeric representation. This can be done using std::stringtream or atoi.

Assigning multiple integers to a character array in binary

I have three integers (4 bytes of memory for each integer) and I want to assign each of their binary values to a character array with 12 elements. So, if each integer had a value of let's say 2, then I want the character array to have these values:
2 0 0 0 2 0 0 0 2 0 0 0
I have tried:
memcpy(cTemp, &integer1 + &integer2 + &integer3, 12);
but I receive an "invalid operands" compiler error.
I have also found the function strcat referenced here: http://www.cplusplus.com/reference/clibrary/cstring/
However it is mentioned as: "The terminating null character in destination is overwritten by the first character of source" which I obviously don't want since most of the times integers will have a null character at the end unless the value is really large. Does anybody know of a better working method? Any help is appreciated.
It is probably simpler (if you are on a x86 at least :P) to just cast the pointer and assign directly. i.e.
int* p = (int*) cTemp;
p[0] = a;
p[1] = b;
p[2] = c;
You can also do a union hack:
union translate {
char c[sizeof(int) * 3];
int i[3];
};
translate t;
t.i[0] = 2;
t.i[1] = 2;
t.i[2] = 2;
// access t.c[x] to get the chars
... and read the chars...
If you want to see how a variable is represented as a sequence of bytes, you can do the following.
int i[3] = {2, 2, 2};
char cTemp[sizeof i];
memcpy(cTemp, &i, sizeof i);
Note however that the representation will be different on different platforms. What are you trying to solve?
Edit:
I'm just writing a program to edit [a file], and the file happens to store integers in binary.
Why didn't you say so in the first place? If you know the program will only run on platforms where int has the correct memory-layout, you can simply store the integer.
fout.write((char const *)&i, sizeof i);
However, if you want to be portable, you need to properly serialize it.
void store_uint32_le(char * dest, unsigned long value)
{
for (int i = 0; i < 4; ++i)
{
*dest++ = value & 0xff;
value >>= 8;
}
assert(value == 0);
}
int main()
{
char serialized[12];
store_uint32_le(serialized, 2);
store_uint32_le(serialized + 4, 2);
store_uint32_le(serialized + 8, 2);
std::ofstream fout("myfile.bin", std::ios::binary);
fout.write(serialized, sizeof serialized);
}
I think this should work:
int i,j,k;
char a[12];
*((int*)a) = i;
*(((int*)a)+1) = j;
*(((int*)a)+2) = k;