Last Updated: 2015-07-22 Wed 10:06

Final Exam Practice Problems

This document contains some practice problems designed to prepare students for the second exam. Some questions have answers are partial answers available while others do not. Students may visit office hours to discuss full answers to all problems.

Table of Contents

1 Get, Set, Clear Bits

Write three functions which make it easier to work with the bits of an integer.

  • Get a bit
  • Set a bit to 1
  • Clear a bit to make it 0

Bits number 0 to 31 from right to left as in

        3         2         1         0
index: 10987654321098765432109876543210
bits:  10000000000000000000000010100001

has bits 0, 5, 7, and 31 all set to 1 while the remaining bits are clear.

Get a Bit

int get_bit(int x, int bit_i)

Return 1 if bit at index bit_i is 1 and 0 if it is 0.

//         3         2         1         0
// index: 10987654321098765432109876543210
int x = 0b10000000000000000000000010100001;
int result;
result = get_bit(x, 0);  // returns 1
result = get_bit(x, 1);  // returns 0
result = get_bit(x, 2);  // returns 0
result = get_bit(x, 7);  // returns 1
result = get_bit(x, 30); // returns 0
result = get_bit(x, 31); // returns 1

Set A bit

void set_bit(int *x, int bit_i)

Set the bit at index bit_i in the integer pointed at by x to be 1. So that the bits of the integer can actually change, x is a pointer to the integer that should be changed.

//         3         2         1         0
// index: 10987654321098765432109876543210
int x = 0b10000000000000000000000010100001;

set_bit(&x, 0);  // bit 0 already set

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 10000000000000000000000010100001;


set_bit(&x, 1);  // change bit 1 to 1

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 10000000000000000000000010100011;

set_bit(&x,10);  // change bit 10 to 1

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 10000000000000000000010010100011;

set_bit(&x, 30);  // change bit 30 to 1

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 11000000000000000000000010100111;

Clear A bit

void clear_bit(int *x, int bit_i);

Set the bit at index bit_i in the integer pointed at by x to be 0, also known as clearing the bit. So that the bits of the integer can actually change, x is a pointer to the integer that should be changed.

//         3         2         1         0
// index: 10987654321098765432109876543210
int x = 0b11000000000000000000000010100111;

clear_bit(&x, 3); // bit 3 is already 0

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 11000000000000000000000010100111;

clear_bit(&x, 1); // change bit 1 to 0

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 11000000000000000000000010100101;

clear_bit(&x, 31); // change bit 31 to 0

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 01000000000000000000000010100101;


clear_bit(&x, 31); // change bit 31 to 0

//         3         2         1         0
// index: 10987654321098765432109876543210
// x is : 01000000000000000000000010100101;

Interactive Main

Below is an interactive main() function that allows testing of the bit functions above. The code is in bit_ops_main.c at the bottom of this section.

lila [final-exam-practice-code]% gcc bit_ops_main.c bit_ops.c
lila [final-exam-practice-code]% a.out
        3         2         1         0
index: 10987654321098765432109876543210
bits:  00000000000000000000000000000000
command> get 0
bit 0 is 0
        3         2         1         0
index: 10987654321098765432109876543210
bits:  00000000000000000000000000000000
command> set 0
setting bit 0 to 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  00000000000000000000000000000001
command> get 0
bit 0 is 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  00000000000000000000000000000001
command> set 31
setting bit 31 to 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  10000000000000000000000000000001
command> set 31
setting bit 31 to 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  10000000000000000000000000000001
command> set 30
setting bit 30 to 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  11000000000000000000000000000001
command> get 31
bit 31 is 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  11000000000000000000000000000001
command> set 22
setting bit 22 to 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  11000000010000000000000000000001
command> set 21
setting bit 21 to 1
        3         2         1         0
index: 10987654321098765432109876543210
bits:  11000000011000000000000000000001
command> clear 22
clearing bit 22 to 0
        3         2         1         0
index: 10987654321098765432109876543210
bits:  11000000001000000000000000000001
command> quit

Source code for bit_ops_main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void showbits(int x);
int get_bit(int x, int bit_i);
void set_bit(int *x, int bit_i);
void clear_bit(int *x, int bit_i);

int main(int argc, char **argv){
  int x = 0;
  if(argc > 1){
    x = atoi(argv[1]);
  }
  char command[128] = "";
  int biti;

  while(1){
    printf("        3         2         1         0\n");
    printf("index: 10987654321098765432109876543210\n");
    printf("bits:  "); showbits(x); printf("\n");

    printf("command> ");
    scanf("%s",command);
    if( strcmp(command,"get")==0 ){
      scanf("%d", &biti);
      printf("bit %d is %d\n", biti, get_bit(x,biti));
    }
    else if( strcmp(command,"set")==0 ){
      scanf("%d", &biti);
      printf("setting bit %d to 1\n", biti);
      set_bit(&x, biti);
    }
    else if( strcmp(command,"clear")==0 ){
      scanf("%d", &biti);
      printf("clearing bit %d to 0\n", biti);
      clear_bit(&x, biti);
    }      
    else if( strcmp(command,"quit")==0 ){
      break;
    }
    else{
      printf("Unknown command %s\n",command);
    }
  }
}

/* Print the most signficant (right-most) to least signficant bit in
   the integer passed in */
#define INT_BITS 32
void showbits(int x){
  int i;
  int mask = 0x1;
  for(i=INT_BITS-1; i>=0; i--){
    int shifted_mask = mask << i;
    if(shifted_mask & x){
      putchar('1');
    } else {
      putchar('0');
    }
  }
  /* Equivalent short version */
  //    (x&(1<<i)) ? putchar('1'): putchar('0');
}

2 Skip Line

Define the skipline() function which advances a file pointer past the end of a line so that subsequent reads occur on the next line. The end of a file must not cause an infinite loop. For full credit, use a single character buffer with fgetc(FILE *f) which returns the next character in the file or EOF. (My Solution is 4 lines long.)

The demo below shows a main() function in skipline_main.c and a data file some.txt. It reads data from the input file and calls skipline() (from file skipline.c) several times to show what data is passed over.

lila [final]% cat skipline_main.c
#include <stdio.h>
void skipline(FILE *f);
int main(){
  FILE *f = fopen("some.txt","r");
  char buf[128];
  skipline(f);
  fscanf(f,"%s",buf); printf("%s\n",buf);
  fscanf(f,"%s",buf); printf("%s\n",buf);
  skipline(f);
  fscanf(f,"%s",buf); printf("%s\n",buf);
  skipline(f);
  fclose(f);
  return 0;
}

lila [final]% gcc skipline_main.c skipline.c
lila [final]% cat some.txt
a line of garbage
Woot Cool Skip the rest
last
Last line all skipped
lila [final]% a.out
Woot
Cool
last

3 Unique Numbers in a File

Write a main function that

  • Opens up a file
  • Repeatedly reads integers from it (assume only integers will appear in the file)
  • Keeps track of all the unique integers that appear in the file
  • When the end of file is reached, close it
  • Print out all unique integers that appeared

Implementation Notes

  • Use a int_vector or int_list to make this an easier task.
  • Implementing an int_vector_contains(vec, data) or int_list_contain(lst,data) function to determine if a particular number is in a data structure is very helpful.

Sample runs

lila [final-exam-practice-code]% gcc unique_numbers.c

lila [final-exam-practice-code]% cat numbers1.dat 
1 1 1
0 0 0 0
2 2
3 3 3
1 1
3 3 3 3
5
7 7
1

lila [final-exam-practice-code]% a.out numbers1.dat
Unique numbers: 1 0 2 3 5 7

lila [final-exam-practice-code]% cat numbers2.dat
1 2 3 4 5 1 2 3 1 2 5 9 1 2

lila [final-exam-practice-code]% a.out numbers1.dat
Unique numbers: 1 2 3 4 5 9

4 Minimum Element of a Linked List

Write a function which finds the minimum integer in a linked list and returns it. As a side effect, it also sets the a pointer to an integer to the index at which the minimum element occurred.

int int_list_minimum(int_list *list, int *min_index_ptr)

If the list is empty, return 0 and set the integer pointed to by min_index to be -1.

The following main program demonstrates how the function should work.

#include "int_list.h"
#include <stdio.h>
#include <stdlib.h>

int int_list_minimum(int_list *list, int *min_index);

int main(){
  int_list *l = int_list_create();

  int_list_prepend(l, 8);
  int_list_prepend(l, 3);
  int_list_prepend(l, 9);
  int_list_prepend(l, 5);
  // l is [5, 9, 3, 8]

  int min, min_index=-1;

  min = int_list_minimum(l, &min_index);

  printf("Min: %d, At index: %d\n",min,min_index);
  // Min: 3, At index: 2

  int_list_prepend(l, 7);
  int_list_prepend(l, 4);
  // l is [4, 7, 5, 9, 3, 8]

  min = int_list_minimum(l, &min_index);

  printf("Min: %d, At index: %d\n",min,min_index);
  // Min: 3, At index: 4

  int_list_prepend(l, 2);
  // l is [2, 4, 7, 5, 9, 3, 8]

  min = int_list_minimum(l, &min_index);

  printf("Min: %d, At index: %d\n",min,min_index);
  // Min: 2, At index: 0

  int_list_destroy(l);

  l = int_list_create();        
  // l is empty

  min = int_list_minimum(l, &min_index);

  printf("Min: %d, At index: %d\n",min,min_index);
  // Min: 0, At index: -1

  int_list_destroy(l);

  return 0;
}

5 Secret Message Decoding

A file has a secret message in it. The last character of the first word on each line is part of the message. For example following text file contains the secret word "program."

Lip balm is waxy.
prayer books for kids.
Bono is a singer.
pig went to the market.
briar rabbit? That's now how you spell it.
panacea has lots of vowels.
exam imminent; prepare or perish.

This can be seen by limiting your attention to the last letter of the first word on each line as follows.

    Lip
 prayer
   Bono 
    pig 
  briar
panacea
   exam
p
r
o 
g 
r
a
m

Write a program that will read through a file printing the last letter in the first word on each line. This will reveal secret messages which are encoded with the scheme described.


Author: Chris Kauffman (kauffman@cs.gmu.edu)
Date: 2015-07-22 Wed 10:06