If you missed the class discussion on circular buffers, look it up on the internet (e.g., Wikipedia) or a data structures textbook.
The data structure you will implement will help a currency trader (let's call him Andreas) summarize the foreign currency exchange data he receives throughout the day. Andreas's data feed looks like this:
Each line is a quote and represents an offer by someone somewhere to exchange currency at a particular rate. Here, USD is U.S. Dollars, EUR is Euros and JPY is the Japanese Yen. The second column is a timestamp and the third column is the actual exchange rate. For example, the line:
The exchange rates can vary dramatically over the course of a trading day — depending on the news of the day and what other currency traders are doing. Andreas can make money trading currencies, for example, if he correctly predicts that the Euro will rise versus the US Dollar today. Then he can buy Euros with dollars in the morning and exchange them back to dollars in the afternoon and end up with more dollars than he started with.
Thus, Andreas needs to pay attention to these quotes but on a busy day there may be thousands of quotes in an hour. That's too much information. He wants you to store the quotes from the last 5 minutes (300 seconds) and report the average exchange rate for him. You will do so by storing the quotes from the last 5 minutes in a circular buffer.
Finally, Andreas cannot tell you how many quotes there will be in 5 minutes. Your data structure should adapt its memory usage accordingly. If your circular buffer is full, you should double the amount of storage allocated. On the other hand, if your circular buffer is using less than a quarter of the storage, you should free up half of the storage.
Note: As with Project 5, this project description deliberately avoids using C syntax. This is so you figure out how to look up the syntax of various elements of the C programming language.
You will implement an Abstract Data Type (ADT) to store currency quotes in a circular buffer. Your functions must be compatible with the main programs given below. Memory for the circular buffer must be dynamically allocated. Main programs that use your ADT may use several circular buffers at a time. (Thus, your functions should not rely on global variables.) Your ADT must support the following functions:
Initialize a circular buffer and return a pointer that can be used to specify that circular buffer in future function calls.
Deallocate all dynamically allocated memory associated with the circular buffer referenced by cb_ptr. The programmer using your ADT promises to never use the value in cb_ptr again.
Add a new currency exchange quote to the specified circular buffer. The time is in seconds since midnight. This function should remove any quotes in the circular buffer that are more than 5 minutes older than this quote. You should assume that the timestamps given to cbuf_update() are in non-decreasing order. During a cbuf_update(), the memory for the circular buffer may have to grow or shrink according to the rules described above.
To assist in grading, please print out a diagnostic message with the old and new maximum sizes of your circular buffer when you either grow or shrink the buffer.
Return the average exchange rate of the quotes currently stored in the buffer.
Return a pointer to the earliest quote currently stored in the buffer. (Earliest = smallest timestamp) The programmer using your ADT promises to just "look at" the quote and not alter it in any way.
Return a pointer to the latest quote currently stored in the buffer. (Latest = largest timestamp) The programmer using your ADT promises to just "look at" the quote and not alter it in any way.
Print the contents of the circular buffer to standard output. The output should be formatted nicely and also print out the current size, maximum size and the indices of the start and end of the buffer. (See sample runs linked below.)
Same as cbuf_dump() but does not print out the quotes.
You will likely implement additional functions used internally by your ADT. (Actually, this is highly recommended.) Programmers using your ADT may not use these additional functions.
You must provide a header file circular.h that contains all the typedefs and function prototypes needed to use your ADT. The header file must be guarded.
Your circular buffer needs to maintain an array of structs of type quote. Each quote struct must have an unsigned int field called time and a double field called rate. The array of quote structs must be dynamically allocated.
Your header file must have a type definition of cbuf. A pointer to cbuf is used to specify the circular buffer to the ADT's functions. The type cbuf itself is most likely a struct (you decide), but the programmer using your ADT is not allowed to assume that. In particular, the programmer is not allowed to manipulate the fields of cbuf.
You should make your declarations and definitions compatible with these sample main programs:
The three data files used in the third test, Ticks6am.txt, Ticks2pm.txt and TicksAll.txt are available on the GL filesystem:
Similarly, for shrinking, you should allocate a new, smaller, array when the number of quotes in the buffer is less than a quarter of the current maximum size. (Note: that's a quarter and not a half.) The new array should have half the current maximum size. (Note: that's half not a quarter.)
Use the UNIX submit command on the GL system to turn in your project. You must submit the header file circular.h, the implementation circular.c and any test programs you wish to submit (optional): test1.c, test2.c, ...
In addition, submit a typescript file showing that your ADT functions worked with main6a.c, main6b.c and main6c.c.
You may optionally submit a README file explaining anything the graders might need to know about compiling and/or running your programs.
Your submit commands will look like:
submit cs313 proj6 circular.h circular.c
submit cs313 proj6 test1.c test2.c
submit cs313 proj6 typescript README