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
orint_list
to make this an easier task. - Implementing an
int_vector_contains(vec, data)
orint_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.