Issue with turning a character into an integer in C - c

I am having issues with converting character variables into integer variables. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char string[] = "A2";
char letter = string[0];
char number = string[1];
char numbers[] = "12345678";
char letters[] = "ABCDEFGH";
int row;
int column;
for(int i = 0; i < 8; i++){
if(number == numbers[i]){
row = number;
}
}
}
When I try to convert the variable row into the integer value of the variable number, instead of 2 I get 50. The goal so far is to convert the variable row into the accurate value of the character variable number, which in this case is 2. I'm a little confused as to why the variable row is 50 and not 2. Can any one explain to me why it is not converting accurately?

'2' != 2. The '2' character, in ASCII, is 50 in decimal (0x32 in hex). See http://www.asciitable.com/
If you're sure they're really numbers you can just use (numbers[i] - '0') to get the value you're looking for.

2 in your case is a character, and that character's value is 50 because that's the decimal version of the byte value that represents the character 2 in ASCII. Remember, c is very low level and characters are essentially the same thing as any other value: a sequence of bytes. Just like letters are represented as bytes, so are the character representation of their value in our base 10 system. It might seem that 2 should have been represented with the value 2, but it wasn't.
If you use the atoi function, it will look at the string and compute the decimal value represented by the characters in your string.
However, if you're only converting one character to the decimal value it represents , you can take a short cut. subtract the digit from the value of '0'. Though the digits are not represented by the base 10 value they have for us humans, they are ordered sequentially in the ASCII code. And since in C the characters are simply byte values, the difference between a numeric character 0-9 and 0 is the value of the character.
char c = '2';
int i = c - '0';
If you understand why that would work, you get what I'm saying.

Related

K&R 1.6 Arrays // Digit representation in an array construct

I found this example code on using arrays in the C language.
#include <stdio.h>
main () {
int c, i;
int ndigit[10];
for (i = 0; i < 10; ++i)
ndigit[i]=0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c - '0'];
printf("digits =");
for (i = 0; i < 10; ++i)
printf(" %d", ndigit[i]);
}
I never saw arrays before, but I think I got it.
Still, I'm not sure on why the digit values have to be inserted in '..' nor why the assignement of i has to be expressed as c-'0'.
This is a passage of the book that should clarify my doubts:
This particolar program relies on the properties of the character representation of the digits. For example the text if (c >= '0' && c <= '9') determines whether the characters in c is a digit. If it is, the numeric value if that digit is c - '0'.
I don't understand how can these values be used in arithmetical expressions if they are characters, is it because they are mapped to numerical values?
Then why the whole program just doesn't work if they are written as numbers as in if (c >= 0 && c <= 9) nor it works if c isn't written in that way (which to my understanding is just "whatever number c is minus 0).
TL;DR: a "char" is just a one-byte-long integer.
I don't understand how can these values be used in arithmetical expressions if they are characters, is it because they are mapped to numerical values?
In C, a char is the "smallest addressable unit of the machine that can contain basic character set. It is an integer type." [1]. Normally, char is equivalent to "a one-byte-long integer", so they can hold values from 0 to (2^8)-1, or [0,255].
That being said, when you write
char c = '9';
You are saying "c is a one-byte-long integer whose value is the character-set representation of the character 9". By looking at the most common character set, the ASCII table [2], we see that the character 9 has an integer value of 57, so the above expression is equivalent to
char c = 57;
To convert a digit's character-set value to the digit itself (e.g. '9' to 9, or 57 to 9), you can rely on a property of character sets that digits are always stored sequentially and increasingly, and just subtract by the value of '0', which in ASCII is 48, so:
char c;
c = '9' - '0'; /* = 9 In any character set */
c = 57 - 48; /* = 9 */
c = '9' - 48; /* = 9 In ASCII */
c = 57 - '0'; /* = 9 In ASCII */
Keep in mind that while ASCII is the most common character set, this is actually machine-dependent.
[1] http://en.wikipedia.org/wiki/C_data_types#Basic_types
[2] http://www.asciitable.com/
if you see the man page of getchar() it says
....reads the next character from stdin and returns it as an unsigned char cast to an int....
So, an input of a digit [example, 9] is treated as a char input and the corresponding encoded [Usually ASCII] value is returned by getchar().
Now coming to your question(s),
why the digit values have to be inserted in '..'
A digit [or any other character, for that matter], written as '.', represents the corresponding ASCII value of the same. Check the ASCII table here.
For understanding, a 9 is a 9 whereas a '9' represents the correcsponding ASCII 57.
why the assignment of i has to be expressed as c-'0'.
If you notice the ASCII table closely, you can see, the corresponding values of 0 to 9 are in sequence. So, to get the particular digit as an int value, we can do c - '0' which is same as c - 48 which will give us the digit as an int.
I don't understand how can these values be used in arithmetical
expressions if they are characters, is it because they are mapped to
numerical values?
getchar() returns the character read.Prototype for it is
int getchar(void)
When a character is read getchar() returns the ASCII value of the char read.
The ASCII value for char's 0 to 9 are contiguous. So just making use of it if we have
char ch = '5';
int i = ch - '0'; /* 53 - 48 = 5 */
will give you the integer value 5. Converting character to integer. The arithmetic is performed by implicit conversion.
If you have a character '8' then this doesn't give you the integer value 8 but retuns ASCII value 56. So during arithmetic ch - '0' since both are char's the respective ASCII values are used and the arithmetic operation is performed

Get a integer from a string in c

char str[]="abcde1fgh";
int i;
i=str[5];
return;
After this process, the integer i must be 1. But it doesn't. Why not?
You code does not work because in your example 1 is a char.
Try the following instead:
int i = str[5] - '0';
Here is why it works: Based on Jamal's explanation from his comment below
The numerical value is obtained by subtracting some character e.g. str[5] with the character '0'. The numeric value for each character is found in the ASCII table. In this example, we are subtracting 49 (corresponding to '1') minus 48 (corresponding to '0') which equals 1.

How do I get an int from a string in C with no whitespace?

So I have a string like this: "MULTR12"
I want to get '1' and '2' as two seperate integers. How do I go about doing that? Before, I had it simply as:
char *string = "MULTR12";
val = string[5];
But I get a really weird value for val instead of 1, like I want. Can anyone help? Thanks!
This is how you convert a char to int ..
int x = string[5] - '0';
Here's some explanation.. Every character is represented as an ASCII character in memory, A will be 65 and simliar. This also applies to numbers, so 0 in ASCII is 48, 1 is 49 etc.
Now, when we subtract 0 from any number's ASCII representation. Let's say the number is 5, this is what we are actually doing..
int x = 53 - 48
which gives us 5 as an integer. In other words, we are calculating the displacement of that numbers ASCII representation from 0's ASCII representation.
A bit hackish but try
val = string[5] - '0';
Shamelessly stolen from here
What you are trying to do above, is basically take the ASCII representation of the char '1' and convert it to an int, yielding 49. (probably not what you expected)
You can do something like this:
int num = string[ 5 ] - '0';
Actually you are getting a weird value because you are trying to change the value of a string that is fixed.
First take a new array as char str[]="Multr12";
Now you can access str[5]...try this

How this code in C is working

I got a code in c which will do functionality of atoi function but i don't how its working
int main(int argc, char* argv[])
{
printf("\n%d\n", myatoi("1998"));
getch();
return(0);
}
int myatoi(const char *string)
{
int i;
i=0;
while(*string)
{
i=(i<<3) + (i<<1) + (*string - '0');
string++;
}
return(i);
}
In the above code is not getting incremented and always be zero then how (i<<3) + (i<<1) will effect the code?
(i<<3) + (i<<1) (for positive numbers at least) is equivalent to multiplying by 10, because i<<3 shifts the integer by 3 bits to the left (i.e. multiplying by 8) and i<<1 shifts the integer by 1 bit to the left (i.e. multiplying by 2).
Each time you encounter a new digit, it multiplies the current number by 10 and adds the new digit (i.e. if your current number is 199 and you encounter the digit 8, then your new number should be 1998 = 10 * 199 + 8.
The reason for subtracting '0' is that if your characters are encoded in ASCII, you need to convert the ASCII codes back to numbers.
For understanding this code, you need to understand:
(i<<3), I mean bit operators
and
*string, string++, I mean string manipulation and more generally operations on pointers.
You also need to know how strings are represented in C and how numbers are represented in ASCII.

ASCII and printf

I have a little (big, dumb?) question about int and chars in C. I rememeber from my studies that "chars are little integers and viceversa," and that's okay to me. If I need to use small numbers, the best way is to use a char type.
But in a code like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int i= atoi(argv[1]);
printf("%d -> %c\n",i,i);
return 0;
}
I can use as argument every number I want. So with 0-127 I obtain the expected results (the standard ASCII table) but even with bigger or negative numbers it seems to work...
Here is some example:
-181 -> K
-182 -> J
300 -> ,
301 -> -
Why? It seems to me that it's cycling around the ascii table, but I don't understand how.
When you pass an int corresponding to the "%c" conversion specifier, the int is converted to an unsigned char and then written.
The values you pass are being converted to different values when they are outside the range of an unsigned (0 to UCHAR_MAX). The system you are working on probably has UCHAR_MAX == 255.
When converting an int to an unsigned char:
If the value is larger than
UCHAR_MAX, (UCHAR_MAX+1) is
subtracted from the value as many
times as needed to bring it into the
range 0 to UCHAR_MAX.
Likewise, if the
value is less than zero, (UCHAR_MAX+1)
is added to the value as many times
as needed to bring it into the range
0 to UCHAR_MAX.
Therefore:
(unsigned char)-181 == (-181 + (255+1)) == 75 == 'K'
(unsigned char)-182 == (-182 + (255+1)) == 74 == 'J'
(unsigned char)300 == (300 - (255+1)) == 44 == ','
(unsigned char)301 == (301 - (255+1)) == 45 == '-'
The %c format parameter interprets the corresponding value as a character, not as an integer. However, when you lie to printf and pass an int in what you tell it is a char, its internal manipulation of the value (to get a char back, as a char is normally passed as an int anyway, with varargs) happens to yield the values you see.
My guess is that %c takes the first byte of the value provided and formats that as a character. On a little-endian system such as a PC running Windows, that byte would represent the least-significant byte of any value passed in, so consecutive numbers would always be shown as different characters.
You told it the number is a char, so it's going to try every way it can to treat it as one, despite being far too big.
Looking at what you got, since J and K are in that order, I'd say it's using the integer % 128 to make sure it fits in the legal range.
Edit: Please disregard this "answer".
Because you are on a little-endian machine :)
Serously, this is an undefined behavior. Try changing the code to printf("%d -> %c, %c\n",i,i,'4'); and see what happens then...
When we use the %c in printf statement, it can access only the first byte of the integer.
Hence anything greater than 256 is treated as n % 256.
For example
i/p = 321 yields op=A
What atoi does is converting the string to numerical values, so that "1234" gets 1234 and not just a sequence of the ordinal numbers of the string.
Example:
char *x = "1234"; // x[0] = 49, x[1] = 50, x[2] = 51, x[3] = 52 (see the ASCII table)
int y = atoi(x); // y = 1234
int z = (int)x[0]; // z = 49 which is not what one would want

Resources