Expressions
Exercises
Question 4.1
Show the output produced by each of the following program fragments. Assume that i, j, and k are int variables.
i = 5; j = 3;
printf("%d %d", i / j, i % j);i = 2; j = 3;
printf("%d",(i + 10) % j);i = 7; j = 8; k = 9;
printf("%d",(i + 10) % k / j);i = 1; j = 2; k = 3;
printf("%d", (i + 5) % (j + 2) / k);
- Output
- Program
1 2 0 1 0
#include <stdio.h>
int main (void) {
int i = 5, j = 3;
printf("%d %d\n", i / j, i % j);
i = 2; j = 3;
printf("%d\n", (i + 10) % j);
Question 4.2
If i and j are positive integers, does (-i)/j always have the same value as -(i/j)? Justify your answer.
- Answer
No, (-i)/j does not always have the same value as -(i/j). -(i/j) operation first divides i by j and then puts the minus sign, whereas (-i)/j is more difficult to explain. As described in the QnA section, the goal is to ensure that the value of (i / j) * j + i % j will always be equal to i (provided that the value of i and j are "representable"). If the value of i is 9 and j is 7, thereby making (-i)/j = -9/7, this operation can provide either one of two results; -1 or -2.
Question 4.3
What is the value of each of the following expressions in C89? (Give all possible values if an expression may have more than one value.)
8 / 5-8 / 58 / -5-8 / -5
- Answer
- Program
-
8 / 5 // Expected: 1 // Actual: 1 -
-8 / 5 // Expected: -1 or -2 // Actual: -1
(i / j) * j + i % j == i // The result of (i / j) can be either rounded up or down if either one of operand is negative.
(-8 / 5) * 5 + (-8 % 5) -> (-1 * 5) + (-3) = -8
(-8 / 5) * 5 + (-8 % 5) -> (-2 * 5) + (+2) = -8 -
8 / -5 // Expected: -1 or -2 // Actual: -1
(i / j) * j + i % j == i
(8 / -5) * -5 + (8 % -5) -> (-1 * -5) + (+3) = 8
(8 / -5) * -5 + (8 % -5) -> (-2 * -5) + (-2) = 8 -
-8 / -5 // Expected: 1 // Actual: 1
// This should work like a normal division as both the operands have a negative sign, thereby cancelling the minus sign.
(i / j) * j + i % j == i
(-8 / -5) * -5 + (-8 % -5) -> (-1 * -5) + (???) = -8 // this and the expression below simply does not work as the value for (i % j) should be such that it should be -13 to get the final result of -8
(-8 / -5) * -5 + (-8 % -5) -> (-2 * -5) + (???) = -8 // the value of (i % j) should be -18 to get the final result of -8
#include <stdio.h>
int main (void) {
int i = 8, j = 5;
printf("(%d / %d) = %d\n", i, j, (i / j));
i = -8, j = 5;
printf("(%d / %d) = %d\n", i, j, (i / j));
Question 4.4
Repeat Exercise 3 for C99.
- Answer
From book: In C99, the result of division is always truncated towards zero. So -9/7 is -1 as it is more near to 0 than -2.
Expectation: Since the value was in the range of either -1 or 1 using the C89 compiler, the values will be similar to C99 compiler as well(?)
Actual Result: As expected, the values that were obtained were similar to the ones obtained using the C89 compiler.
Question 4.5
What is the value of each of the following expressions in C89? (Give all possible values if an expression may have more than one value.)
8 % 5-8 % 58 % -5-8 % -5
- Answer
- Program
The explanation for the expected values is provided in the answer to Exercise 4.
| Expression | Expected | Actual | |
|---|---|---|---|
| (a) | 8 % 5 | 3 | 3 |
| (b) | -8 % 5 | -3 or +2 | -3 |
| (c) | 8 % -5 | +3 or -2 | 3 |
| (d) | -8 % -5 | 3 | -3 |
So, why does -8 (i) % -5 (j) yield -3? As C must satisfy the equality for negative integers in division or modulus operation
like (i / j) * j + i % j == i. So, i % j == i - ((i / j) * j)
(i / j) will yield 1, so
=> i % j == -8 - ((1) * -5)
=> i % j = -8 - (-5)
=> i % j = -3
#include <stdio.h>
int main (void) {
int i = 8, j = 5;
printf("(%d %% %d) = %d\n", i, j, (i % j));
i = -8, j = 5;
printf("(%d %% %d) = %d\n", i, j, (i % j));
Question 4.6
Repeat Exercise 5 for C99.
- Answer
- Program
The explanation for the expected values is provided in the answer to Exercise 3.
| Expression | Expected | Actual | |
|---|---|---|---|
| (a) | 8 % 5 | 3 | 3 |
| (b) | -8 % 5 | -3 or +2 | -3 |
| (c) | 8 % -5 | +3 or -2 | 3 |
| (d) | -8 % -5 | 3 | -3 |
Explanation for (d) provided in answer to Exercise 5.
#include <stdio.h>
int main (void) {
int i = 8, j = 5;
printf("(%d %% %d) = %d\n", i, j, (i % j));
i = -8, j = 5;
printf("(%d %% %d) = %d\n", i, j, (i % j));
Question 4.7
The algorithm for computing the UPC check digit ends with the following steps:
Subtract 1 from the total.
Compute the remainder when the adjusted total is divided by 10.
Subtract the remainder from 9.
It's tempting to try to simplify the algorithm by using these steps instead:
Compute the remainder when the total is divided by 10.
Subtract the remainder from 10.
Why doesn't this technique work?
- Answer
The actual opertions are: (9 - ((total - 1) % 10)). But the alternative descirbed is: (10 - (total % 10)). Let's take one example: 0-13800-15173-5, the total is 45 in this case. Now, when we subtract 1 from it, we get 44 and its modulus operation with 10 yields 4. When 4 is subtracted from 9, we get 5 as the result. When we use the latter technique, first we do modulus operation for 45 with 10 obtaining 5. Then we subtract 5 from 10 to get the result of 5. Consider another example: 0-51500-24128-?, here the total obtained is 52 and subtracting 1, we get 51. when divided by 10, the remainder is 1 and when the remainder is subtracted from 9, we get 8 as the final result. Using the alternative approach, we divide 52 by 10 to get the remainder of 2, then we subtract 2 from 10 to obtain the value of 8.
Both approach seems to provide the same result.
The program seems to run as expected for the following examples: 0-13800-15173-?(5), 0-51500-24128-?(8), 0-31200-01005-?(6).
Question 4.8
Would the upc.c program still work if the expression 9 - ((total - 1) % 10) were replaced by (10 - (total % 10)) % 10?
- Answer
- Program
The program seems to run as expected for the following examples: 0-13800-15173-?(5), 0-51500-24128-?(8), 0-31200-01005-?(6).
#include <stdio.h>
int main (void) {
int first_digit;
int i1, i2, i3, i4, i5;
int j1, j2, j3, j4, j5;
int first_sum, second_sum;
int total;
Question 4.9
Show the output produced by each of the following program fragments. Assume that i, j, and k are int variables.
i = 7; j = 8;
i *= j + 1;
printf("%d %d", i, j);i = j = k = 1;
i += j += k;
printf("%d %d %d", i, j, k);i = 1; j = 2; k = 3;
i -= j -= k;
printf("%d %d %d", i, j, k);i = 2; j = 1; k = 0;
i *= j *= k;
printf("%d %d %d", i, j, k);
- Answer
- Program
-
Expectation: i *= (j + 1) -> i = i * (j + 1) -> i = 7 * (8 + 1) -> i = 63, j = 8
Actual: i = 63, j = 8 -
Expectation: i += (j += k) -> (i += (j += k)) -> (i += (j = j + k)) -> (i += (j = 2)) -> (i = i + j = 2) -> i = 3, j = 2, k = 1
Actual: i = 3, j = 2, k = 1 -
Expectation: i -= (j -= k) -> (i -= (j -= k)) -> (i -= (j = j - k)) -> (i -= (j = -1)) -> (i = i - (j = -1)) -> i = 2, j = -1, k = 3
Actual: i = 2, j = -1, k = 3 -
Expectation: i *= (j *= k) -> (i *= (j *= k)) -> (i *= (j = j * k)) -> (i *= (j = 0)) -> (i = i * (j = 0)) -> i = 0, j = 0, k = 0
Actual: i = 0, j = 0, k = 0
#include <stdio.h>
int main (void) {
int i, j, k;
i = 7; j = 8;
i *= j + 1;
printf("%d %d\n", i, j);
Question 4.10
Show the output produced by each of the following program fragments. Assume that i and j are int variables.
i = 6;
j = i += i;
printf("%d %d", i, j);i = 5;
j = (i -= 2) + 1;
printf("%d %d", i, j);i = 7;
j = 6 + (i = 2.5);
printf("%d %d", i, j);i = 2; j = 8;
j = (i = 6) + (j = 3);
printf("%d %d", i, j);
- Answer
- Program
-
Expectation: j = (i += i) -> j = (i = i + i) -> (j = (i = 12)) -> j = 12 -> i = 12, j = 12
Actual: i = 12, j = 12 -
Expectation: j = ((i -= 2) + 1) -> j = ((i = i - 2) + 1) -> j = ((i = 3) + 1) -> j = 4 -> i = 3, j = 4
Actual: i = 3, j = 4 -
Expectation: j = (6 + (i = 2.5)) -> j = 8.5 but since j is int, j = 8 and same for i, i.e. i = 2 -> i = 2, j = 8
Actual: i = 2, j = 8 (Also got the warning: implicit conversion from 'double' to 'int' changes value from 2.5 to 2 [-Wliteral-conversion]) -
Expectation: j = ((i = 6) + (j = 3)) -> j = (6 + 3) = 9 -> i = 6, j = 9 or 3. The value of j is assigned twice in the same statement, so it mostly depends on the compiler to assign the actual value for j.
Actual: i = 6, j = 9 (Also got the warning: multiple unsequenced modifications to 'j' [-Wunsequenced])
#include <stdio.h>
int main (void) {
int i, j;
i = 6;
j = i += i;
printf("%d %d\n", i, j);
Question 4.11
Show the output produced by each of the following program fragments. Assume that i, j, and k are int variables.
i = 1;
printf("%d ", i++ - 1);
printf("%d", i);i = 10; j = 5;
printf("%d", i++ - ++j);
printf("%d %d", i, j);i = 7; j = 8;
printf("%d ", i++ - -—j);
printf("%d %d", i, j);i = 3; j = 4; k = 5;
printf("%d", i++ - j++ + --k);
printf("%d %d %d", i, j, k);
- Answer
- Program
- Here, the first
printfshould display0asi++first fetches the value ofito the printf then subtracts-1from it making the result0. The secondprintfwill have the updated value ofi, so it displays2. ->0 2 - Here, the first
printfwill display4asiis first fetched and only in the later statements its value is incremented by1while the value ofjis first incremented and then only fetched, so we4as the result and the secondprintfdisplays11and6foriandjrespectively. ->4 11 6 - Similar to #2, the first
printfwill display0as the value ofi++fetched will be7and8only in later statements while the value of--jwill be7on the firstprintfitself. The secondprintfwill display the value ofiandjas8and7respectively. ->0 8 7 - The first
printfshould display((3 - 4) + 4) -> 3as the value ofiandjare incremented in later statements but the value ofkis decremented in the same statement. The secondprintfwill display the value ofi,j, andkas4 5 4respectively. ->3 4 5 4
#include <stdio.h>
int main (void) {
int i, j, k;
i = 1;
printf("%d ", i++ - 1);
printf("%d\n", i);
Question 4.12
Show the output produced by each of the following program fragments. Assume that i and j are int variables.
i = 5;
j = ++i * 3 - 2;
printf("%d %d", i, j);i = 5;
j = 3 - 2 * i++;
printf("%d %d", i, j);i = 7;
j = 3 * i—- + 2;
printf("%d %d", i, j);i = 7;
j = 3 + -—i * 2;
printf("%d %d", i, j);
- Answer
- Program
-
j = (++i) * 3 - 2
j = ((++i) * 3) - 2
j = (((++i) * 3) - 2)
j = ((6 * 3) - 2)
j = 16
i = 6, j = 16 -
j = 3 - 2 * (i++)
j = 3 - (2 * (i++))
j = (3 - (2 * (i++)))
j = (3 - (2 * 5))
j = (3 - 10)
j = -7
i = 6, j = -7 -
j = 3 * (i--) + 2
j = (3 * (i--)) + 2
j = ((3 * (i--)) + 2)
j = ((3 * 7) + 2)
j = (21 + 2)
j = 23
i = 6, j = 23; -
j = 3 + (--i) * 2
j = 3 + ((--i) * 2)
j = (3 + ((--i) * 2))
j = (3 + (6 * 2))
j = (3 + 12)
j = 15
i = 6, j = 15
#include <stdio.h>
int main (void) {
int i, j;
i = 5;
j = ++i * 3 - 2;
printf("%d %d\n", i, j);
Question 4.13
Only one of the expressions ++i and i++ is exactly the same as (i += 1); which is it? Justify your answer.
- Answer
i += 1 increments the value of i by 1 and then assigns it to the variable i. ++i first increments the value of i by 1 and then fetches the value of i whereas i++ first fetches the value of i and then increments it by 1 for later statements to use the value of i.
Question 4.14
Supply parentheses to show how a C compiler would interpret each of the following expressions.
a * b - c * d + ea / b % c / d- a - b + c - + da * - b / c - d
- Answer
- Program
-
a * b - c * d + e
= (a * b) - (c * d) + e
= ((a * b) - (c * d)) + e
= (((a * b) - (c * d)) + e)
= (((12 * 20) - (25 * 31)) + 88)
= ((240 - 775) + 88)
= -535 + 88
= -447 -
a / b % c / d
= (a / b) % c / d
= ((a / b) % c) / d
= (((a / b) % c) / d)
= (((12 / 20) % 25) / 31)
= ((0 % 25) / 31)
= (0 / 31)
= 0 -
- a - b + c - + d
= (- a) - b + c - (+ d)
= ((- a) - b) + c - (+ d)
= (((- a) - b) + c) - (+ d)
= ((((- a) - b) + c) - (+ d))
= ((((- 12) - 20) + 25) - (+ 31))
= (((-32) + 25) - (+ 31))
= (-7) - (+ 31)
= -38 -
a * - b / c - d
= a * (- b) / c - d
= (a * (- b)) / c - d
= ((a * (- b)) / c) - d
= (((a * (- b)) / c) - d)
= (((12 * (- 20)) / 25) - 31)
= (((-240) / 25) - 31)
= ((-9) - 31)
= -40
#include <stdio.h>
int main (void) {
int a, b, c, d, e;
a = 12; b = 20; c = 25; d = 31; e = 88;
printf("a * b - c * d + e = %d\n", a * b - c * d + e);
printf("a / b %% c / d = %d\n", a / b % c / d);
Question 4.15
Give the values of i and j after each of the following expression statements has been executed. (Assume that i has the value 1 initially and j has the value 2.)
i += j;i--;i * j / i;i % ++j;
- Answer
The following are the result that is expected to obtain after the statements:
-
i += j
i = i + j
i = 1 + 2
i = 3 -
i--
i = 1
i = i - 1
i = 0 (the new value of i, i.e. i = 0 is not stored as the statment is executed but rather in later statements where i is called.) -
((i * j) / i)
= ((1 * 2) / 1)
= 2 / 1
= 2 -
i % ++j
= i % (++j)
= i % (3)
= 1 % 3
= 1
Programming Projects
Project 4.1
Write a program that asks the user to enter a two-digit number, then prints the number with its digits reversed. A session with the program should have the following appearance:
Enter a two-digit number: 28
The reversal is: 82
Read the number using %d. then break it into two digits. Hint: If n is an integer, then n % 10 is the last digit in n and n / 10 is n with the last digit removed.
- Program
#include <stdio.h>
int main (void) {
int num;
int reverse_num = 0;
printf("Enter a two-digit number: ");
scanf("%2d", &num);
Project 4.2
Extend the program in Programming Project 1 to handle three-digit numbers.
- Program
#include <stdio.h>
int main (void) {
int num;
int reverse_num = 0;
printf("Enter a three-digit number: ");
scanf("%3d", &num);
Project 4.3
Rewrite the program in Programming Project 2 so that it prints the reversal of a three-digit number without using arithmetic to split the number into digits. Hint: See the upc.c program of Section4.1.
- Program
#include <stdio.h>
int main (void) {
int first_digit, second_digit, third_digit;
printf("Enter a three-digit number: ");
scanf("%1d%1d%1d", &first_digit, &second_digit, &third_digit);
printf("The reversal is: %d%d%d", third_digit, second_digit, first_digit);
Project 4.4
Write a program that reads an integer entered by the user and displays it in octal (base 8):
Enter a number between 0 and 32767: 1953
In octal, your number is: 03641
The output should be displayed using five digits, even if fewer digits are sufficient. Hint: To convert the number to octal, first divide it by 8; the remainder is the last digit of the octal number (1, in this case). Then divide the original number by 8 and repeat the process to arrive at the next-to-last digit,(printf is capable of displaying numbers in base8, as we'll see in Chapter 7, so there's actually an easier way to write this program.)
- Program
#include <stdio.h>
int main (void) {
int num;
int first_digit, second_digit, third_digit, fourth_digit, fifth_digit;
printf("Enter a number between 0 and 32767: ");
scanf("%d", &num);
Project 4.5
Rewrite the upc.c program of Section 4.1 so that the user enters 11 digits at one time, instead of entering one digit, then five digits, and then another five digits.
Enter the first 11 digits of a UPC: 01380015173
Check digit: 5
- Program
#include <stdio.h>
int main (void) {
int first_digit, second_digit, third_digit, fourth_digit, fifth_digit;
int sixth_digit, seventh_digit, eighth_digit, ninth_digit, tenth_digit;
int eleventh_digit;
int first_sum, second_sum, total;
printf("Enter the first 11 digits of a UPC: ");
Project 4.6
European countries use a 13-digit code, known as a European Article Number (EAN) instead of the 12-digit Universal Product Code (UPC) found in North America. Each EAN ends with a check digit, just as a UPC does. The technique for calculating the check digit is also similar:
- Add the second, fourth, sixth, eighth, tenth, and twelfth digits.
- Add the first, third, fifth, seventh, ninth, and eleventh digits.
- Multiply the first sum by 3 and add it to the second sum.
- Subtract 1 from the total.
- Compute the remainder when the adjusted total is divided by 10.
- Subtract the remainder from 9.
For example, consider Güllüoglu Turkish Delight Pistachio & Coconut, which has an EAN of 86914260008.The first sum is 6 + 1 + 8 + 2 + 0 + 0 = 17, and the second sum is 8 + 9 + 4 + 4 + 6 + 0 = 31. Multiplying the first sum by 3 and adding the second yields 82. Subtracting 1 gives 81. The remainder upon dividing by 10 is 1. When the remainder is subtracted from 9, the result is 8, which matches the last digit of the original code. Your job is to modify the upc.c program of Section 4.1 so that it calculates the check digit for an EAN. The user will enter the first 12 digits of the EAN as a single number:
Enter the first 12 digits of an EAN: 869148426000
Check digit: 8
- Program
#include <stdio.h>
int main (void) {
int i1, i2, i3, i4, i5, i6;
int i7, i8, i9, i10, i11, i12;
int first_sum, second_sum, total;
printf("Enter the first 12 digits of an EAN: ");