You want to build a program but where to start?
OK, I'll tell you. This should be done in the following steps:
1. Specifications
2. Design
3. Implementation
4. Test & Debug
5. Documentation
We go through this article by an example program. Imagine we are ordered to make a program for a school. They need a program to store student's name and average of marks. Then they should be able to find a student's average by knowing his/her name and vice versa. The program should also be able to show all the averages on the screen, alphabetically sorted.
OK. Now we know what they want, so we can enter step one, Specifications:
• Program should start with a menu with the following options: 1) Show list 2) Enter new name 3) Change a mark 4) Delete an entry 5) Search by name 6) Search by mark 7)Exit
• The program should be able to do all the tasks in menu
• The program should keep the records (names and marks) on hard disk in order to keep them safe on power off and retrieve them when program starts.
Now step two, Design:
It is the most important part of the development because a good design will make implementation easy and efficient while a bad one will make you cry (and program users may insult you!). How should we start? There are classic ways to design a program. For trivial programs like this, we use top down functional decomposition technique. We write pseudo codes to demonstrate the design. As we see in specifications, 6 functions are necessary. In addition there should be a function to read user choice and call appreciate function. We also need to save the records somewhere and read them again when the program starts. So we should have a main() like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
int main()
{
LoadDataFromFile();
while(userChoice != 7){
userChoice = GetUserChoice();
switch (userChoice) {
case 1: ShowList(); break;
case 2: AddEntry(); break;
case 3: ChangeMark(); break;
case 4: Delete(); break;
case 5: ShowMark(); break;
case 6: ShowName(); break;
case 7: break;
}
}
SaveDataToFile();
return 0;
}
| |
main() gets user choice, calls the appreciate function and will loop until it gets the choice 7, which means exit. In this case main() returns and program terminates. main() also loads the data from a file and saves them on exit (just before return).
This is the function which reads data from a file. For the first time the program runs there is no file to be opened. So this function creates an empty file to store data.
1 2 3 4 5 6 7 8 9 10
|
LoadDataFromFile()
{
if(fileExists){
OpenFile();
ReadFileToMemory();
}
else
CreateNewFile();
}
| |
We need to sorts the list then prints each item in the list until reaches the end of list. We sort list every time an item is added, so we will always have a sorted list in memory.
1 2 3 4
|
ShowList()
{
for(int i = 0; i < listCount; ++i ) cout << i << "\t" << listItem[i];
}
| |
To add an entry, program asks for name and mark of the student. There is an integer named listCount that keeps the number of records in the list.
1 2 3 4 5 6 7 8
|
AddEntry()
{
name = GetStudentName();
mark = GetStudentMark();
listCount++;
AddToList(name, mark);
SortList();
}
| |
Each entry (name and mark pair) in the list has an index number. Suppose the user wants to change the mark of or delete an entry. She/He should first select the Show List option or using search options to find the desired entry and see its index. Then he/she can use Delete or Change Mark options which will ask for the index of desired entry. Every time an item is added, the list will be sorted. So indices may change.
1 2 3 4 5 6
|
ChangeMark()
{
idx = GetStudentIdx();
mark = GetStudentMark();
SetNewMark(idx, mark);
}
| |
We will discuss SetNewMark() later.
Functions below seem straightforward:
1 2 3 4 5 6
|
Delete()
{
idx = GetStudentIdx();
DeleteFromTheList(idx);
listCount--;
}
| |
1 2 3 4 5
|
ShowName()
{
mark = GetStudentMark();
for(int i = 0; i < listCount; ++i ) if(listItem[i].mark == mark) cout << i << "\t" << listItem.name;
}
| |
1 2 3 4 5
|
ShowMark()
{
name = GetStudentName();
for(int i = 0; i < listCount; ++i ) if(listItem[i].name == name) cout << i << "\t" << listItem.mark;
}
| |
Sort function uses bubble sort algorithm to sort the list. Study its code in implementation step.
You can see some new functions have been revealed in pseudo code. Some of them are straightforward like GetStudentMark() and some have to get studied like AddToList(). To get into more detail of those functions, we should now think about how to keep the records in the memory.
It is a branch of IT that discusses the ways which should be used to store particular kinds of data. But as I don't want to enter that area, I choose a simple method. We will have a class that defines a pair of name and mark.
1 2 3 4 5 6
|
class StudentEntry
{
public:
string name;
int mark;
}
| |
One entry is defined. To have a list we use an array of pointers to that class which keeps a pointer to each entry.
|
StudentEntry *entryList[max_student];
| |
AddToList() is something like this:
1 2 3 4 5
|
AddToList(name, mark)
{
entryList[entryCount] = new StudentEntry(name, mark);
}
| |
You can read about "new" keyword in this web site, if you are not familiar with it.
And DeleteFromTheList() is like this:
1 2 3 4 5 6
|
if(entryCount != idx)
for(int i = idx; i < entryCount; i++) {
entryList[i]->name = entryList[i+1]->name;
entryList[i]->mark = entryList[i+1]->mark;
}
delete entryList[entryCount];
| |
To delete an entry we just replace it by its successor and repeat this action till the end of list. We also must delete the last entry that is duplicated when the list is shifted up. If not we will have a memory leak.
You can see some things like (listItem[i].name == name) in the design pseudo code. I wrote them before deciding how exactly entries are stored into memory. We can rewrite it as (entryList[i]->name == name) now that we know we are using an array of pointers to class.
We have finished the design step. Now we exactly know how program works. We have actually written some parts of it.
Step three, Implementation:
Its time to write the code in the C++ language. As you noticed our pseudo code is nearly in C++ syntax but it needs to be polished to be a functional C++ program. I feel good to explain a little about the process of translating a cpp source code into an executable. First we write a code in cpp syntax and save it on hard disk. This cpp file is readable by humen of course. Next we give this file to a special executable, named "compiler". Compiler is a program that translates human readable data into machine readable data and saves it on hard disk as an object file (these are files with .obj extension). These files are not yet ready to be executed by the system. The reason is that they call many routines that are written in other files. For example the cout << operator is defined in a .lib or .dll file. There is another program named "linker" that copies the code from .lib or other .obj files and puts them in the target file (That is the .obj file with main() entry point). After this operation, the file is ready to be executed and will have the .exe extension.