3. # Tutorial references that should be used together with this worksheet are: arrays 1, array 2, pointers 1, pointer 2, pointer 3, functions 1 , function 2, function 3, function 4 and structs.

1. Show the output and answer the questions for the following exercise.

#include <stdio.h>

// struct declaration...

struct Branch

{

int value;

struct Branch *left;

struct Branch *right;

};

void main(void)

{

struct Branch x, y, z, *p = &y;

printf("&x = %p, &y = %p, &z = %p, p = %p\n", &x, &y, &z, p);

x.value = 100;

y.value = 200;

z.value = 300;

x.left = (struct Branch *) 0;

x.right = &z;

z.left = NULL;

z.right = &y;

y.left = &x;

y.right = &z;

printf("\n&x = %p: x.value = %d, x.left = %p, x.right = %p\n", &x, x.value, x.left, x.right);

printf("&y = %p: y.value = %d, y.left = %p, y.right = %p\n", &y, y.value, y.left, y.right);

printf("&z = %p: z.value = %d, z.left = %p, z.right = %p\n", &z, z.value, z.left, z.right);

}

1. How many items each do x, y and z hold?

2. For each item that they hold, how many are pointers? And pointers to what data type?

3. How many items does p hold? It can store addresses to what data type? What is its value?

4. Where are the variables x, y and z stored? Give their addresses.

5. Fill in all the addresses and boxes in the following Figures.

1. Based on the struct member variables, each x, y and z hold three items that is value, *left and *right.

2. Two are pointers (*left and *right) of struct Branch data type.

3. p also hold three items and it can store addresses of struct Branch. From the output sample shown below, its value is 0012FF44, same as the address of y.

4. From the output sample shown below &x = 0012FF58, &y = 0012FF44 and &z = 0012FF30.

5. See the following Figure.

1. For the following and the next exercises, add the some code at the end of the code given in exercise 10. Show the output and answer the questions based on the added code.

#include <stdio.h>

// struct declaration...

struct Branch

{

int value;

struct Branch *left;

struct Branch *right;

};

void main(void)

{

struct Branch x, y, z, *p = &y;

printf("&x = %p, &y = %p, &z = %p, p = %p\n", &x, &y, &z, p);

x.value = 100;

y.value = 200;

z.value = 300;

x.left = (struct Branch *) 0;

x.right = &z;

z.left = NULL;

z.right = &y;

y.left = &x;

y.right = &z;

printf("\n&x = %p: x.value = %d,\nx.left = %p, x.right = %p\n", &x, x.value, x.left, x.right);

printf("&y = %p: y.value = %d,\ny.left = %p, y.right = %p\n", &y, y.value, y.left, y.right);

printf("&z = %p: z.value = %d,\nz.left = %p, z.right = %p\n\n", &z, z.value, z.left, z.right);

printf("&y = %p, y.value = %d \n", &y, y.value);

printf("y.left = %p, y.right = %p \n", y.left, y.right);

printf("p = %p, (*p).value = %d \n", p, (*p).value);

printf("(*p).left = %p, (*p).right = %p\n", (*p).left, (*p).right);

}

1. When printing y.value, why was a %d used for the format string?

2. When printing y.left, why was a %p used for the format string?

3. What is the address in p? This is the address of which variable?

4. Can you print p.value?

5. Why do you need an asterisk in front of the p when printing (*p).value?

6. In the three places that this appears, "(*p).", change it to: "p " (a combination of hyphen and a greater than operator). Use no period or spaces. Is there any difference in the expressions? For instance, try the following code.

printf("p = %p, pvalue = %d \n", p, pvalue);

1. (*p).left gives the address stored in the left member of which variable?

2. Why does (*p).left give the address stored in the left member of y?

3. The address stored in (*p).left is the address of which variable?

1. The %d format string used because value variable is an integer data type.

2. The %p format string used because left variable is a pointer variable of struct Branch data type.

3. Based on the sample output, &p = 0012FF44 and this is the address of y variable.

4. No, p.value cannot be printed because p is a pointer variable.

5. This is because p is a pointer that hold an address instead of the value. By using the asterisk, we mean to print the value.

6. There is no difference.

7. y variable.

8. This is because of the *p = &y.

9. x variable.

1. Now add the following code to the end of your program. Rebuild and show the output for the added code.

p = (*p).left;

printf("\np = %p, (*p).value = %d \n", p, (*p).value);

printf("(*p).left = %p, (*p).right = %p\n", (*p).left, (*p).right);

1. Now p has the address of which variable?

1. p has the address of x variable.

1. Convert these lines to the notation that uses the arrow (). Is the result the same?

p = p->left;

printf("\np = %p, p->value = %d \n", p, p->value);

printf("p->left = %p, p->right = %p\n", p->left, p->right);

Yes, the result is same.

1. Now add the following code at the end of your previous program. Rebuild and show the output for the added code.

p = (*p).right;

printf("\np = %p, (*p).value = %d \n", p, (*p).value);

printf("(*p).left = %p, (*p).right = %p\n", (*p).left, (*p).right);

1. Convert these three lines to the arrow notation (->) as done previously and test your code.

p = p->right;

printf("\np = %p, p->value = %d\n", p, p->value);

printf("p->left = %p, p->right = %p\n", p->left, p->right);

1. Now the address stored in p is the address of which variable?

1. See the following Figure.

1. The address stored in p is the address of z variable.

1. Now add the following code to the end of your program that you have so far.

p = (*p).right;

printf("\np = %p, (*p).value = %d \n", p, (*p).value);

printf("(*p).left = %p, (*p).right = %p\n", (*p).left, (*p).right);

1. Convert these lines to the arrow notation as done previously and test your code. Is there an address or a member name on the left side of the arrow? What about on the right side?

p = p->right;

printf("\np = %p, p->value = %d \n", p, p->value);

printf("p->left = %p, p->right = %p\n", p->left, p->right);

1. Now the address that is stored in p is the address of which variable?

1. On the left-side is an address and on the right-side is a member name.

2. The address that stored in p is the address of y variable.

1. Can you do any of these assignments? Why or why not?

p = (*p).value;

p = &p;

y.left = &y;

p = (*p).value; - Cannot. value variable holds an integer instead of an address.

p = &p; - Cannot. p already a pointer that holds an address.

y.left = &y; - Can. Both side have similar data type, a pointer to an address.

For all questions and their parts, start with the following code definitions.

#include <stdio.h>

// struct declaration...

struct Ball

{

struct Ball *last;

struct Ball *next;

};

void main(void)

{

struct Ball x, y, *p5 = &x, *p6 = &y;

int i = 0, m[5] = {3, 6, 9, 12, 15}, *p1, *p3, *q[5];

double j, a[5] = {20.0, 30.5, 40.3, 50.3, 60.4}, *p2 = a;

// ...

// ...

// ...

}

1. Show the contents of the variables that have changed after executing each of the following codes.

1. p1 = &i;

*p1 = 8;

1. p1 = &m[0];

p1 = p1 + 2;

*p1 = *p1 + 8;

1. p1 = &i;

p3 = m;

*(p3 + 1) = *p3 + *p1;

1. p1 = m + 2;

p3 = p1 + 1;

i = *p1 + *p3;

1. for(i = 0; i <= 4; ++i)

q[i] = m + i;

for(i = 0; i <= 4; ++i)

*(a + i) = *q[i] + a[i];

1. for(i = 4; i >= 0; --i)

{

q[i] = &m[4 – i];

*p2 = *q[i] + *(a + i);

}

We add some code so that the output and the changed variables can be seen.

p1 = &i;

printf("p1 = %p, *p1 = %d\n",p1, *p1);

*p1 = 8;

printf("p1 = %p, *p1 = %d\n",p1, *p1);

p1 = &m[0];

printf("p1 = %p\n",p1);

p1 = p1 + 2;

printf("p1 = %p\n",p1);

*p1 = *p1 + 8;

printf("*p1 = %d\n",*p1);

p1 = &i;

printf("p1 = %p\n",p1);

p3 = m;

printf("p3 = %p\n",p3);

*(p3 + 1) = *p3 + *p1;

printf("*p1 = %d, p3 = %p, *p3 = %d\n",*p1,p3, *p3);

p1 = m + 2;

printf("p1 = %p, m = %p\n",p1, m);

p3 = p1 + 1;

printf("p3 = %p, p1 = %p\n",p3, p1);

i = *p1 + *p3;

printf("i = %d, *p1 = %d, *p3 = %d\n",i,*p1, *p3);

for(i = 0; i <= 4; ++i)

{

q[i] = m + i;

printf("m = %p, i = %d, q[%d] = %p\n", m, i, i, q[i]);

}

printf("\n");

for(i = 0; i <= 4; ++i)

{

*(a + i) = *q[i] + a[i];

printf("*q[%d] = %d, a[%d] = %.2f, a = %p, i = %d\n", i, *q[i],i,a[i],a, i);

}

for(i = 4; i >= 0; --i)

{

q[i]=&m[4-i];

printf("i = %d, &m = %p, &m[4-%d] = %p\n", i, &m, i, &m[4-i]);

*p2 = *q[i] + *(a + i);

printf("a = %p, i = %d, *(a+%d) = %.2f, *q[%d] = %d, *p2=%.2f\n", a, i, i, *(a+i), i, *q[i], *p2);

}

1. Which of the following are valid?

1. last = next;

2. x = y;

3. p5 = p6;

4. x = 10;

5. x.last = 10;

8. p5  -> Radius = 10;

11. *(x.last) = &y;

12. (*x).last = &y;

13. (*p5).last = &y;

14. *(p5.last) = &y;

15. p5 -> last = &y;

16. *p5 = y;

17. p5 -> last = NULL;

18. p5 -> next = 10;

1. last = next; - Invalid, we cannot directly access the member variable.

2. x = y;

3. p5 = p6;

4. x = 10; - Invalid, x is a variable of type struct Ball and should be written such as x.Radius = 10 or on the right-side must be struct Ball type such as x = y

5. x.last = 10; - Invalid, last is a pointer variable. On the right-side must be a struct Ball type instead of an integer.

7. p5.Radius = 10; - Invalid, p5 is a pointer variable of struct Ball type so must be written as (*p5).Radius = 10 or p5->Radius = 10.

8. p5  -> Radius = 10;

9. (*x).Radius = 10; - Invalid, Radius is an integer so must be something like x.Radius = 10

10. *(x.Radius) = 10; - Invalid, Radius is an integer so must be something like x.Radius = 10

11. *(x.last) = &y; - Invalid, supposed to be written as x.last = &y;

12. (*x).last = &y; - Invalid, supposed to be written as x.last = &y;

13. (*p5).last = &y;

14. *(p5.last) = &y; - Invalid, supposed to be written as (*p5).last = &y; or p5->last = &y;

15. p5 -> last = &y;

16. *p5 = y;

17. p5 -> last = NULL;

18. p5 -> next = 10; - Invalid, p5 is a pointer variable of struct Ball type and last is a pointer variable so on the right-side it must be an address

# Do A Programming

1. Write a function called AddTwo(). It will receive three pointers to floats. It will add the numbers pointed to by the first two floats and store their sum in the location pointed to by the third pointer. In main(), define j, k and m. Scan in j and k, send their addresses to AddTwo() and have main() print the address of m and its value that is in it from AddTwo().

#include <stdio.h>

float * AddTwo(float *, float *, float *);

void main()

{

// we need to initialize pointer variables,

// giving some dummy values

float p =1.2f, q=2.2f, r=3.3f, *j=&p, *k=&q, *m=&r, *n;

printf("Enter two floats: \n");

scanf_s("%f%f", j,k,sizeof(float*),sizeof(float*));

printf("The sum of %.2f and %.2f is %.2f\nwhich stored at %p.\n", *j, *k, *n, n);

}

float * AddTwo(float * pointTo_j, float * pointTo_k, float * pointTo_m)
{

*pointTo_m = *pointTo_j + *pointTo_k;

printf("The sum is %.2f\n", *pointTo_m);

return pointTo_m;

}

1. Define an integer array called a[10]. Initialize it to some values. Then assign the address of the slot whose index is 4 to an integer pointer called p. Print the contents of the array and the address of each slot using the name a but no brackets. Now do the same using the name p.

#include <stdio.h>

void main()

{

int i, a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9 , 10}, *p;

p = &a[3];

for(i=0;i<=9;i++)

{

printf("a[%d] = %d at %p\n", i, a[i], a + i);

}

printf("\n");

for(i=0;i<=9;i++)

{

printf("a[%d] = %d at %p\n", i, a[i], p - 3 + i);

}

}

# More Drills

1. The following diagram shows four variables and the addresses where they are stored. After the execution of these statements, show the values of the locations that are assigned.

int i = 43, j;

int *p1, *p2;

p1 = &i;

p2 = p1;

p2 = p2 + 1;

p1 gets the address of i, p2 gets p1 and p2 then gets incremented by one storage unit. p1 and p2 are pointers to integers.

1. The asterisk (*) is the indirection operator. *p1 refers to the location in memory that has its address in p1. Or, in other words, the location whose address is given in p1. What will the following code print? Notice that p1 uses a %p and *p1 uses a %d. Differentiate between the memory address and the actual value stored at the address.

printf("p1 = %p, *p1 = %d\n", p1, *p1);

p1 simply prints the address in it. However *p1 prints the value stored at a location pointed by p1. *p1 prints 43 because the address in p1, namely FF00, has 43 stored in it.

1. Show the new contents of the locations in the diagram after the following code is executed.

*p2 = *p1;

j = j + 1;

The contents that p1 points to are stored in the location that p2 points to. Then 1 is added to j.

1. After the following code execution, show the contents of the locations that will be changed.

*p2 = *(p1 + 1) - 2;

*p1 = *p1 - 2;

1 is added to p1, which is the address of FF02. From the contents of the location pointed to by FF02, 2 is subtracted, making j equal to 42. p1 remains the same. Then the contents pointed to by p1, which is actually i, has a 2 subtracted from it. now the current value of i is 41.

1. Continue from the previous drill, for the following code, show the values for x and y in the diagram. From main(), ShakeIt() is called. Show its effects in memory. Lastly, what is printed?

ShakeIt(p1, p2);

printf("*p1 = %d, *p2 = %d\n", *p1, *p2);

void ShakeIt(int *x, int *y)

{

*x = 0;

*y = 0;

}

The values for x and y are FF00 and FF02 respectively. *x is actually i and *y is actually j. These are set to zero in ShakeIt(). The two zeroes, the values of i and j are printed.

1. For the following code, show the printout. You may try to complete the code by adding the main() etc.

char x[10] = "Inside", y[10] = "and out";

ShakeIt(x, y);

printf("%s %s\n", x, y);

void ShakeIt(char *a, char *b)

{

*(a + 1) = 'M';

*b = 'u';

}

#include <stdio.h>

void ShakeIt(char *, char *);

void main()

{

char x[10] = "Inside", y[10] = "and out";

ShakeIt(x, y);

printf("%s %s\n", x, y);

}

void ShakeIt(char *a, char *b)

{

*(a + 1) = 'M';

*b = 'u';

}

Array names are actually array addresses. hence, the pointer a actually has its address at the beginning of x[ ] . This is also the case with y[ ]. When ShakeIt() changes the contents of the location pointed to by a and b, that changes the array x[ ] and y[ ].

1. Are there any errors in the following code? If not, show the printout.

void ShakeIt(char *, char *);

void main(void)

{

char x[10] = "Inside",

y[10] = "and out";

ShakeIt(&x[0], &y[0]);

printf("%s %s\n", x, y);

}

void ShakeIt(char a[ ], char b[ ])

{

a[1] = 'M';

b[0] = 'u';

}

No errors exist. Address can be passed to an array and the pointers can be used as arrays. The output is the same.

1. For the following questions, take a[ ] to be an array and specify which are true.

1. a == &a[0]

2. a + 1 == &a[1]

3. *a == a[0]

4. *(a + 1) == a[1]

1. a == &a[0]               - True

2. a + 1 == &a[1]        - True

3. *a == a[0]                - True

4. *(a + 1) == a[1]       - True

All are true. a is the address of &a[0]. *a accesses what is stored in a[0], as does a[0].

1. Here we have an array of pointers. Show the values of the memory locations in the provided diagram.

char x[ ] = "Lawdy", y[ ] = "Mamma", *t[3];

t[0] = x;

t[1] = y;

1. For the following scanf_s()/scanf(), "Hey" is read in. Show the contents of the memory locations after the execution of the given code.

t[2] = t[1];

strcpy_s(t[2], 10, t[0]);

scanf_s("%s", t[0], 10);

1. In the following structure, Rev and Fwd are pointers to type struct Node. Draw a diagram of each of the four variables. Which have three members and which have only one?

struct Node

{

int Qty;

struct Node *Rev;

struct Node *Fwd;

};

struct Node x, y, *Head, *Tail;

x and y have three members but Head and Tail have one only (an address).

1. Which of the following statements are valid? (True or false).

5. x = &y;

6. x.Rev = 30;

8. x.Rev = &y;

9. x.Rev = &x;

10. x.Qty = 30;

11. x.Qty = &y;

12. x = y;

1. Head = &x; - Valid

2. x = &Head; - Not Valid

3. Head = Tail; - Valid

4. Head = &Tail; - Not Valid

5. x = &y; - Not Valid

6. x.Rev = 30; - Not Valid

7. x.Rev = &Head; - Not Valid

8. x.Rev = &y; - Valid

9. x.Rev = &x; - Valid

10. x.Qty = 30; - Valid

11. x.Qty = &y; - Not Valid

12. x = y; - Valid

Head can store only an address of a struct Node, so (a) and (c) are valid and (d) is not valid. x.Rev also can store only an address of a struct Node, so (h) and (i) are valid but (f) and (g) are not valid. In (l), we assign one entire structure to another with similar data type (struct Node) and it is valid.

1. In the diagram for solution 11 (shown below), fill in the values that the following code will assign.

x.Fwd = &y;

// a NULL means that the address doesn't point to any object

// or pointing to address 0.

y.Fwd = NULL;

x.Qty = 500;

y.Qty = 800;

The address of x, which is A100, is stored in Head. The address of y, which is A200, is stored in x, Fwd and so on.

1. Write the statements to set up the following pointers: Have Tail point to y, have the Rev member of y point to x, and have the Rev member of x point to nothing.

Tail = &y;

y.Rev = &x;

x.Rev = NULL;

1. One way to access the Qty member of x is to state "x.Qty". Another way of doing that now is to state "(*Head).Qty". *Head will bring us to the location of A100 or x. And (*Head).Qty will bring us to the Qty member. A more common way of coding this is to state: "Head -> Qty". Give three ways to access the Fwd member of x.

1. x.Fwd

3. Head->Fwd. Could also be written as y.Rev->Fwd

1. Try writing the loop that starts with a pointer p, which is initialized to Head and then traverses the chain by following the Fwd pointers until it becomes NULL. Have the loop simply write out the values of p and the Qty members of each node as it traverses the chain. To advance the pointer p to the next link, p would have to be set equal to (*p).Fwd. Here is how your printout may look.

A100    500

A200    800

for(p = Head; p!=NULL; p = p->Fwd)

printf("%p %d\n", p, p->Qty);

1. Now try reversing the traversal, starting p with Tail and following the Rev pointers.

for(p = Tail; p != NULL; p = p->Rev)

printf("%p %d\n", p, p->Qty);

1. Using malloc(), we have created a new node that has no name, like x and y, but it has an address and it is stored in p. Let us pretend that the address stored in p is B100. How would you write the code so that this new node is placed between x and y. That is, x and y should point to the new node. Firstly, show the values in the diagram shown below that need to be changed.

1. There should be four addresses assigned or changed in the previous diagram. Give the four statements that will do that. Does the order of these statements matter? Do not use the pointers Head or Tail.

1. p->Rev = x.Fwd;

2. p-> Fwd = y.Rev;

3. x.Fwd = p;

4. y.Rev = p;

The first of the last two statements can be switched. However, the first two statements should come first. The Fwd and Rev members should be used first before new pointers are copied in them.

1. Now, do the same as above except do not use x or y. Instead, use Head and Tail. Let us also place a quantity, Qty of 600 in the new node.

p->Fwd = Tail->Rev;

Tail->Rev = p;

p->Qty = 600;

1. We will add a new node whose address is in pNew. Its quantity is 700 and we are to add it in the list. To start, first write the for loop that will start p at Head and make it follow the Fwd pointers until it finds a NULL. That is, p should follow A100, B100 and A200 where the NULL is found. Also fill in the diagram.

for( ; p != NULL; p = p->Fwd)

1. Now add an if statement to this loop that will break out of it when the quantity pointed to by p is greater than the quantity pointed to by pNew. In this example, the loop will break out when p becomes A200. That is, when p is A200 the 800 pointed to by p is greater than the 700 pointed to by pNew.

for( ; p != NULL; p = p->Fwd)

if(p->Qty > pNew->Qty)

break;

1. Since we know the Rev pointer from p, assign the address of the previous node from p into a pointer called pLast. That is, pLast should now be set to B100 after the loop. Then using pLast and p, change and assign the needed pointers so that the new node is linked between B100 and A200 in both directions. Also fill in the diagram for the changed and new address or/and data.

for( ; p != NULL; p = p->Fwd)

if(p->Qty > pNew->Qty)

break;

pLast = p->Rev;

pNew->Fwd = p;

pNew->Rev = pLast;

p->Rev = pNew;

pLast->Fwd = pNew;

1. Now assume that our node didn’t have the Rev pointers. Rewrite the code so that the pointer pLast follows one node behind p inside the loop. When we need to link up the pointers, we will know where the previous node is. Your new code should make no reference to Rev pointers because now they are not needed.

for( ; p != NULL; p = p->Fwd)

if(p->Qty > pNew->Qty)

break;

else

pLast = p;

pNew->Fwd = p;

pLast->Fwd = pNew;

1. What changes are needed in the provided code of the drill 24 solution to accommodate each of the following special conditions?

for( ; p != NULL; p = p->Fwd)

if(p->Qty > pNew->Qty)

break;

else

pLast = p;

pNew -> Fwd = p;

pLast -> Fwd = pNew;

...

1. The new quantity is greater than the quantity in the last node of the list.

2. The new quantity is greater than the quantity in the first node of the list.

3. The linked list is empty; that is, to begin with, Head is NULL.

No changes are needed for part (a). Answers for (b) and (c) are as follows:

for( ; p != NULL; p = p->Fwd)

if(p->Qty > pNew->Qty)

break;

else

pLast = p;

pNew -> Fwd = p;

else

pLast->Fwd = pNew;

1. In C++ what standard library that will be used for linked list and other related data manipulation of the C++ constructs?

Standard Template Library (STL).

1. Take less memory space.

2. Easier to use if you are dumped in the middle of the linked list and need to go back one node.

3. Easier to traverse in both directions.

4. Less pointer maintenance.

1. Single.

2. Double.

3. Double.

4. Single.