I have a question about a part of the getint program.
When we got this part:
for(*pn = 0; isdigit(c); c = getch())
*pn = 10 * *pn + (c - '0');
First it converts c to its real numeric value, then it multiply the data inside pn with 10.
Why does it multiply 10 with the data inside pn?
Regards,
Ken
any number in the decimal notation can be expressed as a polynomial in 10
234 = 2*10^2 + 3*10 + 4
reading from the left and multiplying by 10 assures each digit ends up multiplying the correct power of 10. It's just an application of Horners rule, really.
It is starting from the left, and multiplying by 10 for each successive digit it encounters as it moves to the right.
Take the string "234" for example:
On the first iteration, take the 2. Multiply the 0 (*pn) by 10, add 2, you get 2.
On the second iteration, take the 3. Multiply the 2 (*pn) by 10, add 3, you get 23.
On the third iteration, take the 4. Multiply the 23 (*pn) by 10, add 4, you get 234.
The function is reading one digit at a time, starting from the left. So if it's reading, say, 12, then first it gets c == '1' and *pn == 0, it adds 1 to *pn and now *pn is 1. For each successive digit, it multiplies the existing value by ten (*pn is now 10) and adds the digit (*pn is now 12). This way it reads one digit at a time and ends up with the correct integer.
Related
Given a number, I want to modify the Nth digit of the number.
For example, given 1237645, I want to change the 4th digit from the right, which is 7 in this case, to say 5.
The only way in which I can think of is to do this
N = 1237645
fourthDigit = (N / 1000) % 10
N -= fourthDigit * 1000 // make fourth digit 0
N += 5 * 1000 // make fourth digit 5
But this is quite inefficient. Is there a better way to this? I cannot use array to represent N due to memory constraints.
You can do it in one arithmetic operation:
N = 1237645
fourthDigit = (N / 1000) % 10
N -= (fourthDigit-5) * 1000
provided fourthDigit >= 5, otherwise the last line becomes
N += (newDigit-fourthDigit)*1000
Is this embedded system programming?
If it is, then try storing numbers as binary-coded decimal (BCD), then convert to binary if you need to. It is probably easier to convert from BCD to binary than the other way around.
Also see: http://homepage.divms.uiowa.edu/~jones/bcd/bcd.html
BTW, right here in the room with me is a clock which keeps time in BCD. This way, it doesn't have to divide by 10 for display.
I came across this C program:
int main() {
printf("Enter your address, (e.g. 51 Anzac Road) ");
gets(address);
number = 0;
i = 0;
while (address[i] != ' ') {
number = number * 10 + (address[i] - 48);
i++;
}
}
I understand number = number * 10 + (address[i] - 48); is to get the number from input, but can anybody explain to me how this works? How does that produce the number from the input?
C requires the digits 0 through 9 to be stored contiguously, in that order, in the execution character set. 48 is the ASCII value of '0', so, for instance:
'3' - 48 == 3
for any digit.
ASCII is not required for C, so better is:
'3' - '0'
because while 48 is right for ASCII, '0' is by definition right for any character set.
If address contains "456 ", then:
when i == 0 and number == 0, number * 10 + (address[0] - 48) equals 0 * 10 + 4, or 4.
when i == 1, number * 10 + (address[1] - 48) is 4 * 10 + 5, or 45.
when i == 2, number * 10 + (address[2] - 48) is 45 * 10 + 6, or 456
and you're done.
Never use gets(), it's dangerous, and isn't even part of C anymore.
In ASCII, the digit characters '0' through '9' occupy code points 48 through 57 (i hex, 0x30 through 0x39) so, to turn a digit character into a value, you just subtract 48.
As an aside, you should really subtract '0' since the standard doesn't guarantee ASCII, though it does guarantee that the digit characters are contiguous and ordered. C under z/OS, for example, uses EBCDIC which places the digits at code points 0xf0 through 0xf9.
The loop itself is a simple shift-and-add type, to create a number from multiple digit characters. Say you have the string "123", and number is initially zero.
You multiply number (zero) by ten to get zero then add digit character '1' (49) and subtract 48. This gives you one.
You then multiply number (one) by ten to get ten and add digit character '2' (50), again subtracting 48. This gives you twelve.
Finally, you multiply number (twelve) by ten to get a hundred and twenty then add digit character '3' (51) and subtract 48. This gives you a hundred and twenty three.
There are better ways to do this in the C standard library, atoi or the more robust strtol-type functions, all found in stdlib.h. The latter allow you to better detect if there was "rubbish" at the end of the number, for assistance with validation (atoi cannot tell the difference between 123 and 123xyzzy).
And, as yet another aside, you should avoid gets() like the plague. It, like the "naked" scanf("%s"), is not suitable for user input, and opens your code to buffer overflow problems. In fact, unlike scanf(), there is no safe way to use gets(), which is undoubtedly why it has been removed from C11, the latest standard. A more robust user input function can be found here.
There's also a large class of addresses for which that code will fail miserably, such as:
3/28 Tivoli Rd
57a Smith Street
Flat 2, 12 Xyzzy Lane
I have a program I am writing that converts Octal to Decimal numbers. Most of it works.
(more code above this, assume all variables are properly declared).
for(i; i > 0; i--)
{
decimalNumber = (decimalNumber + (number['i'] * pow(8,power)));
power++;
}
The code correctly shifts over to the right to do other digits but it doesn't change the number it is working with. For example, entering 54 in octal results in an output of 36, 4*(8^0) + 4*(8^1) when it should be outputting 4*(8^0) + 5*(8^1), or 44.
'i' is a constant. You probably meant just i. Also, << 3.
As Ignacio pointed out, 'i' is a constant and will cause you to access the same out of bounds array element on each iteration of the loop. Since I assume you start with i equal to the number of digits in the array (you didn't show that code), you want to subtract 1 from it when you use it as an array index.
You're traversing the string in the wrong direction.
Or, better, change your logic:
5 -> 5*8^0
54 -> (5*8^0)*8 + 4
543 -> ((5*8^0)*8 + 4)*8 + 3
number[0] is 5
number[1] is 4
decimalNumber is 0
power is 0
i = 1 downto 0 do
decimalNumber = (decimalNumber + (number[i:1,0] * pow(8,power:0,1)));
power++;
do end
Let's say I have a number like 21 and I want to split it up so that I get the numbers 2 and 1.
To get 1, I could do 1 mod 10. So basically, the last digit can be found out by using mod 10.
To get 2, I could do (21 - (1 mod 10))/10.
The above techniques will work with any 2-digit number.
However, let me add a further constraint, that mod can only be used with powers of 2. Then the above method can't be used.
What can be done then?
2 == 23 / 10
3 == 23 - (23 / 10) * 10
To get 2 you can just do
int x = 23 / 10;
remember that integer division drops the fractional portion (as it can't be represented in an integer).
Modulus division (and regular division) can be used for any power, not just powers of two. Also a power of two is not the same thing as a two digit number.
To split up a three digit number
int first = 234/100;
int second = (234/10)-first*10;
int third = (234/1)-first*100-second*10;
with a little work, it could also look like
int processed = 0;
int first = 234/100-processed;
processed = processed + first;
processed = processed * 10;
int second = 234/10-processed;
processed = processed + second;
processed = processed * 10;
... and so on ...
If you put a little more into it, you can write it up as a loop quite easily.
what about
x%10 for the second digit and
x/10 for the first?
For instance n = 8135267 => 16
Here is a solution but I don't understand it.
int sumOddDigits(int n) {
if(n == 0)
return 0;
if(n%2 == 1) //if n is odd
//returns last digit of n + sumOddDigits(n/10) => n/10 removes the last digit of n
return n % 10 + sumOddDigits(n/10)
else
return sumOddDigits(n/10);
}
Integer divison by ten "cuts off" the last digit: I.e. 1234/10 results in 123.
Modulo 10 returns the last digit: i.e. 1234%10 results in 4.
Thus, the above code considers always the last digit. If the last digit is odd (hence the %2==1 stuff) it will be counted, otherwise not. So, if it should count the digit, it takes the last digit (the % 10-stuff) and continues computing with the remaining digits (the recursion with the /10-stuff) and adding them to the digit. If the current digit shall not be counted, it continues just with the remaining digits (thus the recursion and the /10-stuff) without adding it to the current digit.
If the argument is 0, this means that the whole number is traversed, thus the function terminates with returning 0.
% is the modulo operator. It basically finds the remainder of dividing by a number.
n %2 n is only 1 if it's odd. % 10 gets the remainder of the dividing the number by 10, this gets you the currently last digit. Integer division by 10 gets you the next digit as the current last digit (1567/10 = 156)
Think about it this way: Starting with your known answer of 8135267 => 16, if I asked you for the sum of the odd digits in *3*8135267, what would you do? What if I asked for *4*8135267? How do your manual steps related to that function?
Think of it this way. If you get an even digit your function returns it + function value of the number without that digit. Otherwise it returns the function value of the number without the last digit. On your example:
813526(7) -> 0 + sumEvenDigits(813526)
6 + sumEvenDigits(81352)
2 + sumEvenDigits(8135)
....
8 + sumEvenDigits(0)
0 = 16
Hope this helps.
int sum_odd_digits(int n)
{
int s=0,r=0;
if(n==0)
return 0;
r = n%10;
if(r%2==1)
s = s+r;
n=n/10;
return s+ sum_odd_digits(n);
}