C Programming Test Exercises - ANSWERS:

1. What does this print?

  #include <stdio.h>

  #include <string.h>

  #include <stdlib.h>

  int main(void){

    char* word = (char *) malloc(sizeof(char) * 30);

    strcpy(word,"good one 123 two 456");

    char wordarr[20] = "working memory";

    wordarr[4] = '\0';

    char suba[4];

    suba[3] = '\0';

    strncpy(suba,word+5,3);

    suba[1] = toupper(suba[1]);

    int x;

    int y;

    char string1[30];

    char * string2 = string1;

    char * string3 ;

    string3 = (char *) malloc(sizeof(char) * 30);

    sscanf(word,"%s%s%i%s%i",string1,string2,&x,string3,&y);

    char builtBySprintf[100];

    sprintf(builtBySprintf,"the first number was %i and the second number was %i\n",x,y);

 

    printf("the value of wordarr is: %s and the length is %lu\n", wordarr, strlen(wordarr));

    printf("the value of word is: %s\n",word);

    printf("the value of suba is: %s\n",suba);

    printf("the value of string1 is: %s \n",string1);

    printf("the value of string2 is: %s \n",string2);

    printf("the value of string3 is: %s \n",string3);

    printf("the value of x is %i and y is: %i \n",x,y);

    printf("the value of builtBySprintf is: %s \n",builtBySprintf);

    printf("tricky: the value of wordarr after the null at 4 is: %s\n",wordarr+5);

  }

·         the value of wordarr is: ___work___ and the length is __4___

·         the value of word is: __good one 123 two 456____________________________

·         the value of suba is: __oNe_______

·         the value of string1 is: __one_______

·         the value of string2 is: __one_______

·         the value of string3 is: __two_______

·         the value of x is ____123_____ and y is: __456_______

·         the value of builtBySprintf is: _the first number was 123 and the second number was 456

·         tricky: the value of wordarr after the null at ____4_____ is: ___ng memory________

 

2. What does this print?

#include <stdio.h>

struct record {

  int  v;

  int num[3];

};

int mystery(int * numbIn, int  vIn, struct record * struIn );

int main(void){

  int *p , *q ;

  struct record spreadsheet[2];

  p = &(spreadsheet[0].v);

  *p = 30;

  q = p;

  spreadsheet[0].num[0] = *q;

  p = spreadsheet[0].num;

  p[2] = 22;

  spreadsheet[1].num[2] = 6;

  *q = 10;

  spreadsheet[0].v = 11;

  p++;

  *(p+3) = 16;

// This was a mistake on my part. I am not sure we can count on spreadsheet[1]num[0] to be the next

//    cell though it seems to be. I should not have used the pointer to cross into another array.

//    C happily lets you walk though memory though

  p = &spreadsheet[0].num[1];

  *p = 10;

  printf("the size of a spreadsheet[0].num is %lu\n",sizeof(spreadsheet[0].num));

  mystery (spreadsheet[0].num, spreadsheet[1].v, &(spreadsheet[1]));

  spreadsheet[1].v = mystery (spreadsheet[0].num, spreadsheet[0].v, &(spreadsheet[1]));

  //What are the last spreadsheet.values of spreadsheet.v and spreadsheet.num ?

  printf("last spreadsheet.value of *p is %i \n",*p);

  printf("last spreadsheet.value of *q is %i \n",*q);

  printf("last spreadsheet.value of spreadsheet[0].v is %i \n",spreadsheet[0].v);

  printf("last spreadsheet.value of spreadsheet[1].v is %i \n",spreadsheet[1].v);

  int c,countRow;

  for (countRow = 0; countRow < 2; countRow++){

    for (c = 0; c < 3; c++){

      printf("last spreadsheet.value of spreadsheet[%i].num %i is %i\n",

      countRow,c,spreadsheet[countRow].num[c]);

    }

  }

}

int mystery(int * numbIn, int  vIn, struct record * struIn ) {

  printf("the size of a numbIn is %lu. Why?\n",sizeof(numbIn));

  static int z = 0; // notice it only initializes to 0 on the first call

  int * pIn = numbIn;

  int y = 0;

  y = y + 150;

  z = z + 10 + y;

  pIn[1] =   100;

  vIn = vIn + 60;

// vIn was never initialized but I am adding to it.

//   C usually defaults ints to 0, but I should not have counted on that.

  struIn->v = y;

  struIn->num[1] = 304;

  return (z);

}

·         the size of a spreadsheet[0].num is ___12______

·         the size of a numbIn is __8_______. Why? When the array is passed to the function, just the address is passed. The array variable, itself, in the main method has a larger size stamped on it. Inside the function, sizeof(array) only gives back the size of the pointer to the array. In main, sizeof(array) gives the size of all the contents of the array.

·         the size of a numbIn is __8_______. Why?

·         last spreadsheet.value of *p is __100_______

·         last spreadsheet.value of *q is ___11______

·         last spreadsheet.value of spreadsheet[0].v is __11_______

·         last spreadsheet.value of spreadsheet[1].v is ___320______

·         last spreadsheet.value of spreadsheet[0].num 0 is ___30______

·         last spreadsheet.value of spreadsheet[0].num 1 is __100_______

·         last spreadsheet.value of spreadsheet[0].num 2 is __22_______

·         last spreadsheet.value of spreadsheet[1].num 0 is ___16______(See my oops above)

·         last spreadsheet.value of spreadsheet[1].num 1 is ___304______

·         last spreadsheet.value of spreadsheet[1].num 2 is ____6_____

3. Functions pass by reference and local, both array and integer and random.

Write a small program with 2 functions:

main:  Create an array of 5 dice, each with a random number between 1 and 6. Also create one more integer to hold the magic number, which is also a random number between 1 and 6. Call the game function, passing it the magic number and the dice and receive back the total. Pass both  the magic number and the dice array by reference. Then print the magic number, and all the dice and the total.

game: input parameters: dice array, magic number

output : total score

process: Calculate the total score by adding all the dice, but if a die equals the magic number, change the die to die +1 before adding it to the score,  and add 1 to the magic number. If the magic number goes over 6, it is okay.

#include <stdio.h>

 

int game (int * dice, int * magic);

// note that the instructions did not say the magic number

//   had to be a pointer, but it did say

//"Pass both  the magic number and the dice array by reference

//    pass by reference means to pass the address.

 

int main(void){

                int dice[5];

                int magic;

                int count;

                for (count = 0; count < 5; count++){

                                dice[count] = rand() % 6 + 1; // I did not seed ; rand() % 6 gives 0-5.

                                               // add 1 to have a range of 1-6

                }

                magic = rand() % 6 + 1;

// not required to print values before, but nice to have:

    printf("prior to game function magic value is %d and dice are:\n",magic);

                for (count = 0; count < 5; count++){

                                 printf("Dice %i is %i\n",count,dice[count]);

                }             

                int tot = game(dice,&magic);

                printf("The magic number is now %d and the total is %d\n",magic,tot);

                for (count = 0; count < 5; count++){

                                 printf("Dice %i is %i\n",count,dice[count]);

                }                             

}

int game (int *diceIn, int * magicPtr){

                // you could also use int diceIn[] in place of int * diceIn

                printf("dice[5] is %i\n",diceIn[5]);

                                int count;

                                int total = 0;

                for (count = 0; count < 5; count++){

                  if (diceIn[count] == *magicPtr){

                                  printf("dice[%i] matched\n",count);

                                  diceIn[count] = diceIn[count] + 1; // I did not say it was okay for the die to

                                                   // exceed 6  but it is

                                                                                                   // the referenced dice array in main is updated

                                   *magicPtr = *magicPtr + 1; // the referenced variable in main is updated

                                  printf("the new magic is %i and the new dicein[%i] is %i\n",

                                         *magicPtr,count,diceIn[count]);

                                  }           

                                  total = total + diceIn[count];      

                }

                return total; // returning a total so the game function will evaluate to the total

}

4. Read and print formatting and String comparison and decisions:

Write a small program that reads in 2 integers, 1 decimal and 2 words and 1 date in the form YY-MM-DD. The integers should be read into 2 cells of an integer array. 1 word should be created as char word[30] and the other should be created as char * word2.  Print what the user entered to the screen. Then print the decimal as currency with 2 decimal places.  Then print whether the words matched.

#include <stdio.h>

#include <stdlib.h>

int main(void){

                int intarr[2];

                char word[50]  ;

                char * word2;

                word2 = (char *) malloc(sizeof(char) * 30);

                   // without the malloc, scanf will crash ; need stdlib for malloc

                float dec;

                // I could have used time-t for date

                //    this type is found in stdlib, but we did not cover

                //    that, so I am using 3 ints

                int month,day,year;

                puts("enter 2 integers, 1 decimal and 2 words and then 1 date s YY-MM-DD");

                scanf("%d%d%f%s%s%i:%i:%i",&intarr[0], &intarr[1], &dec,

                word, word2, &year,&month,&day);

                // note that while intarr is an array that hold an address

                //         and does not need &, the

                //     individual cell  is a value that needs &

                printf("you entered int #1 %d int #2 %d and dec %5.2f and word %s word2 %s year %02d month %02d day %02d\n",

                intarr[0], intarr[1], dec,

                word, word2, year,month,day);

}

5.  Arrays – sizes and copies and Dynamic Arrays – creating and using

Ask the user for the size of an array. Then create 2 integer arrays of the same size – one should be static and the other dynamic. (Dynamic means it is created in memory without an array name.) Fill them both with random numbers. Then look through them both to see whether they have the same contents. Print that the result of your test, stating whether the contents are the same.

#include <stdio.h>

#include <stdlib.h>

int main(void){

                int arrsize, count;

                int issame = 1;

                puts("enter array size");

                scanf("%d",&arrsize);

                int normalArray[arrsize];

                int * dynArray = (int *) malloc (sizeof(int)*arrsize);

                // note that dynamic array does not have an array name

                //   only a pointer to the array memory

                for (count = 0; count < arrsize; count++){

                                normalArray[count] = rand() % 4   ; // I did not seed ; rand() % 6 gives 0-5.

                                // used range of 0 to 4 

                                dynArray[count] = rand() % 4  ;

                                // uncomment for testing to make it the same:

                                // dynArray[count] = normalArray[count] ;

                }

                count = 0;

                while (issame == 1 && count < arrsize)

                    { //keep looking through the array as long

                                // as issame is not proven false

                                if (normalArray[count] != dynArray[count]){

                                                count = arrsize ; // done to end the loop

                                                issame = 0; // issame is false

                                }

                                count = count +1;

                }

                if (issame == 0){

                                puts("The contents are not the same");}

                else {

                                puts ("The contents are the same");}

                // not required but needed for testing

                for (count = 0; count < arrsize; count++){

                                printf("normalArray[%i] is %i and DynArray[%i] is %i\n",

                                count,normalArray[count], count,dynArray[count]);

                }

}

 

6. Questions about string functions:

a)      What is the difference between char * and char [ ].

char * allocates only the space for a pointer (the size of an address) while char x[] creates an array of characters that allocates space for the entire array.

b)      When do you need to use free?

After you have used malloc

c)       Given the variables zip_code_first_five, zip_code_last_four and city and state, write a sprintf command that will put these variable values into the variable address_line_2 in city, state xxxxx-xxxx (with the last part being zip_code_first_five - zip_code_last_four ) format.

sprintf(address_line_2,"%s, %s %05d-%04d",

 city,state,zip_code_first_five,zip_code_last_four);

 printf("%s",address_line_2);

d)      Given the string word containing "1 good 3", write a sscanf command that will extract the 1, good and 3 from the string word into two integer variables x and y and one character array myword.

      sscanf(word,"%d,good,%d",&x,&y);

e)      Write a typedef statement that creates a new variable type Stringy that is actually just a pointer to a character.

     typedef char * Stringy

7.  Structure – declare and use as a function parameter

Main:

·         Make a structure of pets that will hold a pet name, type and age. It should include the name of the pet, the type of pet (such as dog or cat) and the age of the pet. A pet type can only be 10 characters long but its name can be 20 characters long.

·         Ask the user how many pets they have, and then create an array of the number of pets they mentioned.

·         Ask the user for the name, type and age of each pet.

·         Create one more structure variable of a single pet.

·         Call the findBestPet function and then print the single pet variable values.

findBestPet 

·         takes in the array of pets and a pointer to the single pet. It should ONLY read through all the pets and find the oldest. Copy the values of the oldest pet into the single pet structure variable.

#include <stdio.h>

struct Pets {

                char name[21];

                char type[11]; // note 11 for the 10 char type + 1 char null

                int age;};

void findBestPet( struct Pets petArrayIn[], int size, struct Pets * bestPetPtr);

int main(void){

                int numPets;

                puts("How many pets do you have?");

                scanf("%i",&numPets);

                if (numPets > 0){ // not required to capture this, but why bother if no pets

                                struct Pets petArray[numPets];

                                int count;

                                for (count = 0; count < numPets; count++){

                                                puts("please enter the pet name, type and age");

                                                scanf("%s%s%i", petArray[count].name, petArray[count].type,

                                                &(petArray[count].age));

                                }

                                struct Pets bestPet;

                                findBestPet(petArray, numPets, &bestPet);

                                printf("The best pet is %s who is a %s and is %i years old\n",

                                bestPet.name, bestPet.type, bestPet.age);

                                // the printing of the array is not required but helpful for testing

                                for (count = 0; count < numPets; count++){        

                                                printf("Pet #%i is %s who is a %s and is %i years old\n",

                                                count, petArray[count].name, petArray[count].type,

                                                (petArray[count].age));

                                }

                }

}

// sadly, in class I used this as an example to insist you follow my

//   instructions in the design of the function header exactly, but

//   in this function header, you had to also include the arrayLength because

//   passed arrays do not know their length. This is something I would

//   have wanted you to question me about on the test so I could clarify

 

void findBestPet( struct Pets petArray[], int arrayLength, struct Pets * bestPet){

                int count;

                if (arrayLength == 0) { return; }

                *bestPet = petArray[0]; // seed with the first pet

                for (count = 1; count < arrayLength; count++){  

                                if (petArray[count].age >  bestPet->age) {

                                                *bestPet = petArray[count];

                                }

                }

}

 

8. Comparison:

·         Which paradigms do C, Java and Prolog each represent?

C - Imperative Procedural

Java - Imperative Object Oriented

Prolog - Declarative Logic

·         How does C handle memory differently than Java?

Java has its own garbage collection and does not expose the memory addresses as much as C

·         How is a class in Java different from a structure in C? 

A class in java has methods and properties, but a structure in c just has properties

Prolog Programming Exercises:

P1. Write 2 prolog facts:

·         One fact to represent mr jones lives in a green house with a cat

lives(jones, green, cat).    Or lives("mr jones" , green, cat).

·         Another fact to represent that mr bozo lives in a yellow house with a dog.

lives(bozo, yellow, dog).

 

P2. Given these facts, write the requested rules:

female(amy).

female(mary).

female(lucy).

female(sally).

male(tim).

male(jim).

male(frank).

parent(jim,mary).

parent(jim,amy).

parent(lucy,mary).

parent(sally,amy).

parent(sally,frank).

 

Note that the parent rule is meant to read the first parm is a parent of the second parm, so jim is a parent of mary.

Write a rule for sibling(Sib1,Sib2) to be true when a male or female has the same parent.

sibling(Sib1,Sib2):-parent(X,Sib1),parent(X,Sib2).

Write a rule for daughter(Parent,Child) to be true when the child is a female.

daughter(Parent,Child):- parent(X,Child),female(Child).

Write a rule for mother(X) to be true only when the mother is both a parent and female.

mother(X):- parent(X,Child), female(X).

P3. Write a prolog query given facts and rules.

Given this Knowledgebase

point(a,2,3).

point(b,1,3).

point(c,5,3).

point(d,4,2).

point(e,7,3).

point(f,2,9).

point(g,5,9).

point(h,4,8).

point(i,9,2).

point(j,9,8).

 

magicLetterPoints(A,B,C,D):-

point(A,Ax,Ay),

point(B,Bx,By),

point(C,Cx,Cy),

point(D,Dx,Dy),

Ay = By,

Ax = Cx,

Ay < Cy,

Ax < Bx,

Dy = Cy,

Bx = Dx.

 

Write a query that will print all the magicLetterPoints that are found in the knowledgebase.

magicLetterPoints(First, Second, Third, Fourth). (and then hit ; after each answer.)

What letter does it create?

                Z

How many answers are there to this query in the given knowledgebase?

2

 

First = a,

Second = c,

Third = f,

Fourth = g ;

First = d,

Second = i,

Third = h,

Fourth = j ;

false.