Skip to main content

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.

  1. i = 5; j = 3;
    printf("%d %d", i / j, i % j);
  2. i = 2; j = 3;
    printf("%d",(i + 10) % j);
  3. i = 7; j = 8; k = 9;
    printf("%d",(i + 10) % k / j);
  4. i = 1; j = 2; k = 3;
    printf("%d", (i + 5) % (j + 2) / k);

1 2 0 1 0


Question 4.2

If i and j are positive integers, does (-i)/j always have the same value as -(i/j)? Justify your 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.)

  1. 8 / 5
  2. -8 / 5
  3. 8 / -5
  4. -8 / -5
  1. 8 / 5 // Expected: 1 // Actual: 1
  2. -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
  3. 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
  4. -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

Question 4.4

Repeat Exercise 3 for C99.

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.)

  1. 8 % 5
  2. -8 % 5
  3. 8 % -5
  4. -8 % -5

The explanation for the expected values is provided in the answer to Exercise 4.

ExpressionExpectedActual
(a)8 % 533
(b)-8 % 5-3 or +2-3
(c)8 % -5+3 or -23
(d)-8 % -53-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

Question 4.6

Repeat Exercise 5 for C99.

The explanation for the expected values is provided in the answer to Exercise 3.

ExpressionExpectedActual
(a)8 % 533
(b)-8 % 5-3 or +2-3
(c)8 % -5+3 or -23
(d)-8 % -53-3

Explanation for (d) provided in answer to Exercise 5.


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?

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?

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.9

Show the output produced by each of the following program fragments. Assume that i, j, and k are int variables.

  1. i = 7; j = 8;
    i *= j + 1;
    printf("%d %d", i, j);
  2. i = j = k = 1;
    i += j += k;
    printf("%d %d %d", i, j, k);
  3. i = 1; j = 2; k = 3;
    i -= j -= k;
    printf("%d %d %d", i, j, k);
  4. i = 2; j = 1; k = 0;
    i *= j *= k;
    printf("%d %d %d", i, j, k);
  1. Expectation: i *= (j + 1) -> i = i * (j + 1) -> i = 7 * (8 + 1) -> i = 63, j = 8
    Actual: i = 63, j = 8
  2. 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
  3. 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
  4. 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

Question 4.10

Show the output produced by each of the following program fragments. Assume that i and j are int variables.

  1. i = 6;
    j = i += i;
    printf("%d %d", i, j);
  2. i = 5;
    j = (i -= 2) + 1;
    printf("%d %d", i, j);
  3. i = 7;
    j = 6 + (i = 2.5);
    printf("%d %d", i, j);
  4. i = 2; j = 8;
    j = (i = 6) + (j = 3);
    printf("%d %d", i, j);
  1. Expectation: j = (i += i) -> j = (i = i + i) -> (j = (i = 12)) -> j = 12 -> i = 12, j = 12
    Actual: i = 12, j = 12
  2. 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
  3. 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])
  4. 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])

Question 4.11

Show the output produced by each of the following program fragments. Assume that i, j, and k are int variables.

  1. i = 1;
    printf("%d ", i++ - 1);
    printf("%d", i);
  2. i = 10; j = 5;
    printf("%d", i++ - ++j);
    printf("%d %d", i, j);
  3. i = 7; j = 8;
    printf("%d ", i++ - -—j);
    printf("%d %d", i, j);
  4. i = 3; j = 4; k = 5;
    printf("%d", i++ - j++ + --k);
    printf("%d %d %d", i, j, k);
  1. Here, the first printf should display 0 as i++ first fetches the value of i to the printf then subtracts -1 from it making the result 0. The second printf will have the updated value of i, so it displays 2. -> 0 2
  2. Here, the first printf will display 4 as i is first fetched and only in the later statements its value is incremented by 1 while the value of j is first incremented and then only fetched, so we 4 as the result and the second printf displays 11 and 6 for i and j respectively. -> 4 11 6
  3. Similar to #2, the first printf will display 0 as the value of i++ fetched will be 7 and 8 only in later statements while the value of --j will be 7 on the first printf itself. The second printf will display the value of i and j as 8 and 7 respectively. -> 0 8 7
  4. The first printf should display ((3 - 4) + 4) -> 3 as the value of i and j are incremented in later statements but the value of k is decremented in the same statement. The second printf will display the value of i, j, and k as 4 5 4 respectively. -> 3 4 5 4

Question 4.12

Show the output produced by each of the following program fragments. Assume that i and j are int variables.

  1. i = 5;
    j = ++i * 3 - 2;
    printf("%d %d", i, j);
  2. i = 5;
    j = 3 - 2 * i++;
    printf("%d %d", i, j);
  3. i = 7;
    j = 3 * i—- + 2;
    printf("%d %d", i, j);
  4. i = 7;
    j = 3 + -—i * 2;
    printf("%d %d", i, j);
  1. j = (++i) * 3 - 2
    j = ((++i) * 3) - 2
    j = (((++i) * 3) - 2)
    j = ((6 * 3) - 2)
    j = 16
    i = 6, j = 16
  2. 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
  3. 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;
  4. 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

Question 4.13

Only one of the expressions ++i and i++ is exactly the same as (i += 1); which is it? Justify your 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.

  1. a * b - c * d + e
  2. a / b % c / d
  3. - a - b + c - + d
  4. a * - b / c - d
  1. 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
  2. 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
  3. - 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
  4. 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

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.)

  1. i += j;
  2. i--;
  3. i * j / i;
  4. i % ++j;

The following are the result that is expected to obtain after the statements:

  1. i += j
    i = i + j
    i = 1 + 2
    i = 3
  2. 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.)
  3. ((i * j) / i)
    = ((1 * 2) / 1)
    = 2 / 1
    = 2
  4. 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.

#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.

#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.

#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.)

#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

#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

#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: ");