Converting and Calculating char* expression - c

I have the following function, which receives a tree* and a mathematical expression char*:
double calc(char *expr, tree *variaveis){}
I'd like to know how to run through the expression verifying each character? I can't use strtok() because there will not always be a delimiter.
I was trying something like:
double calc(char *expr, tree *variaveis){
int i;
dado_t retorno = 0;
double aux;
char c;
for(i=0; i < strlen(expr); i++){
c = expr[i];
if(isdigit(c)){
//Here i need to convert the C value to a double.
}
}
}
Also, I'm having a problem converting the value represented by the character to a double variable. When I debug the code in codeblocks and I set c to the digit 2 as a value, it shows me:
Variable Value
c 50 '2'
Then, when I do something like:
double aux = c; or
double aux = (double)c;
All I get is the 50 not the 2.

You need to do c - '0' to transform the character '2' to the numeric value 2:
double aux = c - '0';
It works because the characters '0' to '9' have consequent ASCII values:
if c == '0' then '0' - '0' == 0
if c == '1' then '1' - '0' == 1
if c == '2' then '2' - '0' == 2
etc.

The 50 here is the ASCII value of character '2'. As, all the character representation of the digits are having successive values,NOTE you can do something like
double aux = c - '0';
to get the digit as the int value.
FWIW, i'm not much convinced about the aux type being a double.
NOTE:
From C11, chapter §5.2.1
..... the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous. ....

Related

Trying to write a program to sum the value of an int and a char

I am trying to write a program in C to sum the value of an integer and a character. If the user enters an integer where the character should be, I am expecting my program to calculate the value of the 2 integers. My code below works with the user entering 2 integers but only calculates up to 9 (Ex: 4 5: "Character '4' represents a digit. Sum of '4' and '5' is 9"). If the user enters 5 6, the result is: "Character '5' represents a digit. Sum of '5' and '6' is ;". I have been searching for a while now and any potential solution always leads to the incorrect sum. I also expect my program to accept user input higher than '9' (Ex: 20 50), but if I change '9' to '99', I get the following warning: "warning: multi-character character constant [-Wmultichar]". Can someone please point me in the right direction to achieve these goals?
#include <stdio.h>
int sum (int m, char n){
return m+n;
}
int main(){
char ch;
int c;
printf("Enter an integer and a character separated by a blank> ");
scanf("%d %c",&c, &ch);
if((c >= '0' && c <= '9')||(ch >= '0' && ch <= '9')){
int cs = sum(c, ch - 0);
printf("Character '%d' represents a digit. Sum of '%d' and '%c' is %d" , c, c, ch - 0, cs);
}
return 0;
}
int cs = sum(c, ch - 0);
It looks like your trying to account for ASCII values by subtracting the ASCII value of 0 from whatever character the user enters. However, you used an integer literal of 0, when you'd want to use a character literal of '0'. See below:
int cs = sum(c, ch - '0');
Also, I would recommend renaming your int to i or something other than c. It's a little difficult to distinguish that the types of c and ch are different.
Also consider changing
if((c >= '0' && c <= '9')
to
if((c >= 0 && c <= 9)
c is an integer and you should compare it as such. By using ' ', you're basically doing a cast to a char variable which is unnecessary here.
Another problem is that I don't think you're going to be able to accomplish what you're trying to do using a char variable for a two-digit number. A char variable can hold a single character, where as a two-digit number is composed of, well, two characters.
Sorry I can't comment so I'm adding this answer for the problem abou t using only one digit.
You have a single char
char ch;
So it reads only one char, you need an array of chars like char ch[10]
Then you'd use int foo = atoi(ch) to converto your array to an integer

Turning a string character into an int

Basically, I have this really long string full of digits:
char *number = "insert really long number";
Now I want to perform math operations on individual digits contained in this string, let's say the following (summing two consecutive digits in this string aka array of chars):
sum = number[i] + number[i+1];
However, this does not produce the correct result, it returns a garbage value. I know how to extract a single value with printf for example:
printf("%c", number[i]);
But how can I get this %c to use in computations as above? I tried with atoi, but I get "error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with &".
1) atoi accept string rather than single character
2) If you want to convert just one ACSII char 0 - 9 just use following code:
if(rChar >= '0' && rChar <= '9')
val = rChar - '0';
You probably want this:
char *number = "123";
int n = 0;
char c;
for (int i = 0; c = number[i]; i++)
{
n += number[i] - '0';
}
printf("n = %d\n", n);
For any number which is represented as a datatype char, you can subtract that number from '0' to get that number in integer type.
For example:
char a = '5';
int num = a - '0';
//num will store 5
Why this works?
Because if you check the ASCII value for '5', it is 53 and for '0' it is 48. So the difference is 5. This will work for converting any number in character form to integer.
The ASCII value for '0' is 48, for '1' it is 49 and so on. So the subtraction from '0' results in giving us the difference of ASCII values.
Here is a link to ASCII values: http://www.asciitable.com/
atoi convert string (const char*) to int, if you give it a char it will not work. A solution to convert a char to an int is to use the ASCII table:
char c = '9'
int v = c - '0'; // v == 9

why we need "-'0'" to modify array?

This is code from C by Dennis Ritchie, chapter "Array":
#include <stdio.h>
/* count digits, white space, others */
main()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
ndigit[i] = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf("digits =");
for (i = 0; i < 10; ++i)
printf(" %d", ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
}
Why do we need -'0' in this line?
++ndigit[c-'0'];
If I change it to ++ndigit[c], the program doesn't work properly. Why can't we just write ++ndigit[c]?
I already read the explanation of the book, but I don't understand it.
This works only if '0', '1', ..., '9' have consecutive increasing values. Fortunately, this is true for all character sets. By definition, chars are just small integers, so char variables and constants are identical to ints in arithmetic expressions. This is natural and convenient; for example c-'0' is an integer expression with a value between 0 and 9 corresponding to the character '0' to '9' stored in c, and thus a valid subscript for the array ndigit
to understand why we need "-'0'" you first need to understand ASCII table - http://www.asciitable.com/
now you need to understand that every character in C is represented by a number between 0 and 127 ( 255 for extended ).
for example if you'll print the character '0' for his numeric value:
printf( "%d", '0' );
output: 48
now you've declared an array of size 10 - ndigit[ 10 ], where the n cell represent the number of times the number n was given as input.
so if you receive '0' as input you'd want to do ndigit[ 0 ]++ so you need to convert from char to integer. and you can do that by subtracting 48 ( = '0' )
thats why we use the line ++ndigit[c-'0'];
if c = '5', we will get
++ndigit['5' - '0']
++ndigit[ 53 - 48 ]
++ndigit[ 5 ]
exactly like we wanted it to be
c = getchar() will store the character code read to c, and it is differ from the integer that the character stands for.
Quote from N1256 5.2.1 Character sets
. In both the source and execution basic character sets, the
value of each character after 0 in the above list of decimal digits shall be one greater than
the value of the previous.
As this shows, the character codes for decimal digits are continuous, so you can convert the character code of decimal digits to the integer that the characters stand for by subtracting '0', which is 0's character code, from the character code.
In conclusion, c-'0' yields the integer that the character in c stands for.

C Array Count (Beginner) [duplicate]

This question already has answers here:
What's the real use of using n[c-'0']?
(13 answers)
Closed 9 years ago.
I'm currently reading 'The C Programming Language' by Kernighan & Richie and I'm struggling to work out what a line does. I think I'm just being a little stupid, and not quite understanding their explanation.
++ndigit[c-'0'];
I've had to change the program ever so slightly as ndigit was previously giving me garbage values, so I just instantiate the array to 0, instead of traversing it with a for loop, and changing the values that way.
#include <stdio.h>
main()
{
int c, i, nwhite, nother;
int ndigit[10]= {0};
nwhite = nother = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf("digits =");
for (i = 0; i < 10; i++)
printf (" %d", ndigit[i]);
printf (", white space = %d, other = %d\n", nwhite, nother);
}
Using the program as its input, we get this printed to the console -
digits = 7 2 0 0 0 0 0 0 0 1, white space = 104, other = 291
I understand that 7 2 0 0 0 0 0 0 0 1 is a count of how many times the single numbers appear in the input 0 appears 7 times, 1 appears twice etc.)
But, how does the ...[c-'0']; 'work'?
You asked how the below expression works
c-'0'
The ASCII code of the entered charecter is subtracted from the ASCII code of 0 and it defines the position in the array where the count has to be stored .
Suppose you enter 1 from the keyboard ASCII code for 1 is 49 and ASCII code for 0 is 48.
hence
49-48 =1
and the count will be stored in the array index location 1 .
In C, when you have a variable c of type char, it actually stores some integer encoding of the char (usually the ASCII code). So c-'0' means the difference of the code of the character contained in c and the character 0. Since the digits are in natural order it convert the digit in the associated number.
c-'0' is technique to give int value == to char number e.g. 1 for '1' , 5 for '5'.
char symbols '0', '1', '2' ..... '9' are assigned continue encoding values so difference of a numeric char constant with '0' gives decimal number. (in your compiler for example in ASCII char they are assigned continues acsii values).
So for example in variable c is '7', then c - '0' == 7;
In your code array declared as:
int ndigit[10]= {0};
// default initialized with `0`
So index can be from 0 to 9. So in you code:
++ndigit[c-'0']; // ndigit[c-'0'] = ndigit[c-'0'] + 1;
increments frequency of a number by 1 when at corresponding digit of a number char.
Ascii is an encoding which gives consecutive id's to consecutive digits. As Eric Postpischil pointed out, the standard demands that property, even though the underlying encoding need not be ascii. Ascii is quite common though.
char c1 = '0';
char c2 = '1';
So whatever number '0' is mapped to, '1' will be that number + 1. In essence:
c2 == c1 + 1
Subtracting '0' from a character which is a digit, will return its numeric value:
'1' - '0' == 1
The C standard requires that the characters '0' to '9' have consecutive values.
'0' represents the value zero as a character and c is the value you enter it calculates to be like this :
'1' - '0' == 1
'2' - '0' == 2
and so on ... i.e equal to the value of c if c is a digit
((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
c gives you the current character. With the range checking you confirm it is a number by using its ASCII value
Check chr column for 0, it says 48 and for 8 it says 56.So, '8'- '0' gives 56 - 48 = 8
ndigit is used to keep track of how many times a number occurs in with each element of the array representing the number of times its subscript has occured.
ndigit[0] will ggive you number of times 0 has occurred and so on.. ndigit[x] gives number of times x appeared
[c - '0']
suppose your c i.e current character is 8 then '8' - '0' will give you 8. so you get ndigit[8] and you ++ that value [you initialised it to 0 at start]
Loog at ASCII wikipedia.
The American Standard Code for Information Interchange (ASCII /ˈæski/ ass-kee)1 is a character-encoding scheme originally based on the English alphabet that encodes 128 specified characters - the numbers 0-9, the letters a-z and A-Z, some basic punctuation symbols, some control codes that originated with Teletype machines, and a blank space - into the 7-bit binary integers.
So In the ASCII Scheme the '0' char is the number 48, the char '1' is 41, and so on. So c - '0' is equivalent to c - 48. If c is '1' the expression became 49 - 48 = 1. So in few word 'c' - '0' convert a digit char ['0'-'9'] into an integer [0-9].
Edit 1
As suggested by #Eric Postpischil, ASCII is not part of ANSi C (nor c++). But is very common and all compiler I know use ASCII set.
'0' is a char and it has value 48. You can look up any ASCII table in the google.
It works this way because you read from the input char value not the int, so if you don't add "-'0'" part it will increment 48th cell of an array.
Instead of "-'0'" you can put "-48", in my opinion it's more readable this way.

How to convert a hexadecimal number into Ascii in C

I plan to make a program like this:
loop
read first character
read second character
make a two-digit hexadecimal number from the two characters
convert the hexadecimal number into decimal
display the ascii character corresponding to that number.
end loop
The problem I'm having is turning the two characters into a hexadecimal number and then turning that into a decimal number. Once I have a decimal number I can display the ascii character.
Unless you really want to write the conversion yourself, you can read the hex number with [f]scanf using the %x conversion, or you can read a string, and convert with (for one possibility) strtol.
If you do want to do the conversion yourself, you can convert individual digits something like this:
if (ixdigit(ch))
if (isdigit(ch))
value = (16 * value) + (ch - '0');
else
value = (16 * value) + (tolower(ch) - 'a' + 10);
else
fprintf(stderr, "%c is not a valid hex digit", ch);
char a, b;
...read them in however you like e.g. getch()
// validation
if (!isxdigit(a) || !isxdigit(b))
fatal_error();
a = tolower(a);
b = tolower(b);
int a_digit_value = a >= 'a' ? (a - 'a' + 10) : a - '0';
int b_digit_value = b >= 'a' ? (b - 'a' + 10) : b - '0';
int value = a_digit_value * 0x10 + b_digit_value;
put your two characters into a char array, null-terminate it, and use strtol() from '<stdlib.h>' (docs) to convert it to an integer.
char s[3];
s[0] = '2';
s[1] = 'a';
s[2] = '\0';
int i = strtol(s, null, 16);

Resources