0% found this document useful (0 votes)
48 views9 pages

2020 Test 1

1. The document describes a module test for a computer science course involving questions on recursion, generics, operator overloading, delegates and events. 2. For question 1, students are asked to create a generic class to handle permutations and use recursion to print all permutations of an array. 3. For question 2, students must create a new real class to overload the power operator for double values. 4. For question 3, students must implement a messaging service with classes for clients, servers and a program using delegates and events to handle client registration and messaging between clients and servers.

Uploaded by

Nomhle
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views9 pages

2020 Test 1

1. The document describes a module test for a computer science course involving questions on recursion, generics, operator overloading, delegates and events. 2. For question 1, students are asked to create a generic class to handle permutations and use recursion to print all permutations of an array. 3. For question 2, students must create a new real class to overload the power operator for double values. 4. For question 3, students must implement a messaging service with classes for clients, servers and a program using delegates and events to handle client registration and messaging between clients and servers.

Uploaded by

Nomhle
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

UNIVERSITY OF THE FREE STATE

DEPARTMENT OF COMPUTER SCIENCE AND INFORMATICS

CSIS 2614 & CSIQ 2614

MODULE TEST 1

DATE: 20 March 2020 MARKS: 124


ASSESSORS: Prof. P.J. Blignaut & Mr. G.J. Dollman
MODERATOR: Prof. T.R. Stott TIME: 3½ hours

• This is a limited open-book test. You may use ONLY the text book by Nakov. No
other sources are allowed. Internet access will not be available for the duration of
the assessment.
• You may use the tools available in Visual Studio such as IntelliSense.
• No mobile computing devices may be active for the duration of the assessment
(Mobile phones, tablets, etc).

Question 1 (Recursion, Generics) [38]

Permutations are the possible combinations of a series of values. For example, for the
characters "abc", the permutations are "abc", "acb", "bac", "bca", "cab" and "cba".

Start with a new console application, named Question1.

1.1 Add a generic class called CPermutations to the solution. (2)

Use the following interface:

interface IPermutations<T>
{
void Swap(ref T First, ref T Second);
void PrintPermutations(T[] list, int j, int k);
}

1.2 Within the class CPermutations, implement the method Swap to swap two values.
Note that the method should be generic and be able to swap values of any type. (5)

1.3 Within theclass CPermutations, implement a recursive method


PrintPermutations to print all the possible permutations of an array to the console. (16)

1.4 In the Program class, add a private generic method called SelectionSort, to sort
the elements in a generic array in ascending order. (15)
Hint: You cannot use > or < for generic types. Limit T to inherit from IComparable
and then use the CompareTo method.

1
Use the following code to test your application. You may not change this code but you may
comment out lines that you cannot get to work.

static void Main(string[] args)


{
//Initialise array of numbers
int[] nums = new int[] { 4, 3, 5 };

//Sort elements in the array


nums = SelectionSort<int>(nums);

//Write elements
Console.WriteLine("\tNumbers");
Console.Write("\t");
foreach (int v in nums)
Console.Write(v + ", ");

//Get permutations
Console.Write("\n\n\tThe permutations of the numbers are: \n\t");
CPermutations<int> permNums = new CPermutations<int>();
permNums.PrintPermutations(nums, 0, nums.Length - 1);

//Initialise array of characters


char[] chars = new char[] { 'b', 'c', 'a' };

//Sort elements in the array


chars = SelectionSort<char>(chars);

//Write elements
Console.WriteLine("\n\n\tCharacters");
Console.Write("\t");
foreach (char v in chars)
Console.Write(v + ", ");

//Get permutations
Console.Write("\n\n\tThe permutations of the characters are: \n\t");
CPermutations<char> permChars = new CPermutations<char>();
permChars.PrintPermutations(chars, 0, chars.Length - 1);

//Wait for user response


Console.Write("\n\n\tPress any key to exit ...");
Console.ReadLine();
} //Main

2
Question 2 (Operator overloading) [22]

Start with a new console application.

The built-in class double does not have a binary operator to raise a number to a specific
power. Create a new class real that will behave similar to double but also include a
binary operator ^ that can be used in, for example 23 = 8, written as 2 ^ 3. (1)

Your class must contain the following:

2.1 A private date member, value (type double), to contain the value of the number. (1)
2.2 A constructor (2)
2.2 An implicit operator to cast double to real. (5)
2.3 An explicit operator to cast real to double. (5)
2.4 An overloaded operator ^. The signature must contain a real parameter, num, and a
double exponent, e. You can use the following code to calculate the power:

return new real(Math.Pow(num.value, e)); (5)

2.5 Override the default ToString method to return the value displayed as a string. (3)

You may test your class with the following Main method:

static void Main(string[] args)


{
real x = 2,
y = 3;
real z = 2 + 3;
Console.WriteLine(x + " + " + y + " = " + z.ToString());

z = x ^ (double)y;
Console.WriteLine(x + " ^ " + y + " = " + z.ToString());

Console.Write("\nPress any key to exit ...");


Console.ReadLine();
} //Main

3
Question 3 (Delegates and events) [64]

Consider the scenario of a messaging service with three classes, namely a client, server
and a program that manages the first two. The server class serves as a container for
clients and may connect to many clients. Every client connects to a single server.

Use the following delegate declaration and interfaces. You may not change this code but
you may comment out lines if you do not get the code to work.

public delegate void delMessage(string message);

public interface IClient : IDisposable


{
string ClientID { get; }
string ClientName { get; }
Server server { get; }
string ToString();
} //interface IClient

public interface IServer


{
event delMessage OnMessage;
IEnumerator<Client> GetEnumerator();
Client this[string clientID] { get; }
void RegisterClient(Client client);
void UnregisterClient(Client client);
void BroadcastMessage(string message);
} //interface IServer

The Server class acts as a container class for clients and contains a private list
List<Client> lstClients. Events must be triggered in the RegisterClient,
UnregisterClient and BroadcastMessage methods. See the output below for what is
expected. In the RegisterClient method, add the client to a private list and invoke an
event that a client with the specific name is registered. Invoke an alternative event if the
client is already registered. When unregistering a client, remove the client from the list
and dispose it. Again, invoke applicable messages if the client was successfully removed
or not. The Server class may not contain a reference to the System namespace. The
server class must also contain a GetEnumerator method and an indexer. (41)

In the Client class, register a client with the server (call server.RegisterClient) and
subscribe to the server event when a new client is instantiated. All events must be
handled in the Client class (display the server message). Unsubscribe when a client is
disposed. (23)

Test your program with the following main method. You may not change this code but
you may comment out lines.

4
class Program
{
static void Main()
{
//Black text on white background
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
Console.Clear();
Console.WriteLine();

//Register server
Server server = new Server();

//Register clients with server


Console.WriteLine("\tRegister clients");
Client client1 = new Client("123", "ABC", server); //ClientID, ClientName, server
server.RegisterClient(client1);
Client client2 = new Client("456", "DEF", server);
Client client3 = new Client("789", "GHI", server);

//Unregister clients
Console.WriteLine("\n\tUnregister clients");
server.UnregisterClient(client2);
server.UnregisterClient(client2);

//List clients
Console.WriteLine("\n\tList of clients");
foreach (Client client in server)
Console.WriteLine("\t" + client);
Console.WriteLine();

//Find client
Console.WriteLine("\tFind client");
Console.WriteLine("\t" + server["123"]);

//Message to all clients


Console.WriteLine("\n\tMesssage to all clients");
server.BroadcastMessage("Message to all clients.");

//Wait for user


Console.Write("\n\tPress any key to exit ... ");
Console.ReadLine();

} //Main
} //class

Marks allocation
class Server 1 class Client 1
Members 4 Members 3
Constructor 2 Constructor 9
GetEnumerator 5 Dispose 3
Indexer 6 ToString 3
RegisterClient 9 OnMessage 4
UnregisterClient 10
BroadcastMessage 4

5
POSSIBLE SOLUTIONS

Question 1 (38)

interface IPermutations<T>
{
void Swap(ref T First, ref T Second);
void PrintPermutations(T[] list, int j, int k);
} //interface IPermutations

class CPermutations<T> : IPermutations<T> 


{
public void Swap(ref T First, ref T Second) 
{
T temp = First; 
First = Second; 
Second = temp; 
} //Swap

public void PrintPermutations(T[] array, int j, int k) 


{
if (j == k) 
{
for (int i = 0; i <= k; i++) 
Console.Write("{0}", array [i]); 
Console.Write(", ");
}
else 
{
for (int i = j; i <= k; i++) 
{
Swap(ref array [j], ref array [i]); 
PrintPermutations(array, j + 1, k); 
Swap(ref array [j], ref array [i]); 
}
}
} //PrintPermutations

} //class CPermutations

private static T[] SelectionSort<T>(T[] arr)  where T: IComparable


{
for (int i = 0; i < arr.Length; i++)
{
int min = i; 
for (int j = i + 1; j < arr.Length; j++)
if (arr[j].CompareTo(arr[min]) == -1) 
min = j; 

//Swap
T temp = arr[i]; 
arr[i] = arr[min]; 
arr[min] = temp; 
} //for i

return arr; 
} //SelectionSort

6
Question 2 (22)

class real 
{
private double value; 

//Constructor
public real(double number_) 
{
value = number_; 
}

//Implicit conversion from double to real


public static implicit operator real (double num) 
{
return new real(num); 
}

//Explicit conversion from real to double


public static explicit operator double(real num) 
{
return num.value; 
}

//Operator overloading. Normally ^ means bitwise exclusive OR


public static real operator ^(real num, double e) 
{
return new real(Math.Pow(num.value, e)); 
}

//Override ToString
public override string ToString()
{
return value.ToString();
}
} //real

7
Question 3 (64)

public delegate void delMessage(string message);

public interface IServer


{
event delMessage OnMessage;
IEnumerator<Client> GetEnumerator();
Client this[string clientID] { get; }
void RegisterClient(Client client);
void UnregisterClient(Client client);
void BroadcastMessage(string message);
} //interface IServer

public class Server : IServer


{
//Members
private List<Client> lstClients; 
public event delMessage OnMessage; 

public Server()
{
lstClients = new List<Client>(); 
} //Constructor

public IEnumerator<Client> GetEnumerator()


{
foreach (Client client in lstClients) 
yield return client; 
} //GetEnumerator

public Client this[string clientId] 


{
get
{
return lstClients.FirstOrDefault(cl => cl.ClientID == clientId); 
}
} //this

public void RegisterClient(Client client) 


{
if (!lstClients.Contains(client)) 
{
lstClients.Add(client); 
OnMessage?.Invoke(client + " registered");
}
else
OnMessage?.Invoke("Client " + client + " already registered");
} //RegisterClient

public void UnregisterClient(Client client) 


{
if (lstClients.Contains(client)) 
{
lstClients.Remove(client); 
client.Dispose();
OnMessage?.Invoke(client + " unregistered");
}
else
OnMessage?.Invoke(client + " not registered");
} //RegisterClient

public void BroadcastMessage(string message) 


8
{
OnMessage?.Invoke(message); 
} //BroadcastMessage

} //class Server

public interface IClient : IDisposable


{
string ClientID { get; }
string ClientName { get; }
Server server { get; }
string ToString();
} //interface IClient

public class Client : IClient 


{
public string ClientID { get; private set; }
public string ClientName { get; private set; }
public Server server { get; private set; }

public Client(string clientId, string clientName, Server server) 


{
ClientID = clientId; 
ClientName = clientName; 
this.server = server; 
server.OnMessage += Server_OnMessage; 
server.RegisterClient(this); 
} //Constructor

public void Dispose()


{
server.OnMessage -= Server_OnMessage; 
} //Dispose

public override string ToString()


{
return "(" + ClientID + ") " + ClientName; 
} //ToString()

private void Server_OnMessage(string message) 


{
Console.WriteLine("\t" + this + ": Server message: {0}", message); 
} //Server_OnMessage

} //class

You might also like