Most of a programmer's efforts are aimed at the development of correct and efficient programs. But the readability of programs is also important. There are many ``standards'' in use. Since following them will not guarantee good code, these ``standards'' are actually guidelines of style. Each one has its proponents and detractors. The textbook advocates one particular style for C++ programs. This document collects the style comments in the textbook into one place and adds some documentation requirements for this course. The essential point is that a program is a medium of communication between humans; a clear, consistent style will make it that much easier for you to communicate.
Since this course does not require a separate analysis and design document, much of what would have been in such a document is required to appear in the comments of your program files.
Makefiles should begin with a comment section of the following form and with the following information filled in:
# File: <name of file> # Class: CS 215 Instructor: Dr. Deborah Hwang # Assignment: Date assigned: # Programmer: Date completed:
The main program file should begin with a comment section of the following form and with the following information filled in:
// File: <name of file> // < Description of what the program does > // // Input: < Description of data that the program asks the user for // or reads from a file > // Output: < Description of what the program outputs as a result // either to the screen or to a file > // ------------------------------------------------------------------ // Class: CS 215 Instructor: Dr. Deborah Hwang // Assignment: Date assigned: // Programmer: Date completed:
Class definitions and implementations should be divided into multiple files so that we can reuse them easily. By convention, the class definition and related free functions prototypes are stored in a header file which has the extension ``.h''. The implementations of the class member, friend, and overloaded operator functions are stored in a source file with the extension ``.cpp''. The main program is usually stored in a separate source file that includes the header files for each class used.
Every class header file should use compiler directives #ifndef, #define, and #endif to ensure a header file is only included once. The symbol should be the name of the header file in all capital letters with an underscore (_) replacing the dot and a trailing underscore. For example, for the header file counter.h, the directives would be:
#ifndef COUNTER_H_
#define COUNTER_H_
class Counter
{
...
}; // end Counter
#endif // COUNTER_H_
Every class header file should start with a comment block with the following information filled in:
// File: <name of file> // Header file for <class> // < Description of what the class represents > // // Class: CS 215 Instructor: Dr. Deborah Hwang // Assignment: Date assigned: // Programmer: Date completed:
Every class source file should start with a comment block with the following information filled in:
// File: <name of file> // Implementation file for <class> // // Class: CS 215 Instructor: Dr. Deborah Hwang // Assignment: Date assigned: // Programmer: Date completed:
In the preprocessor section, include statements for header files should have comments indicating the types, constants, variables, or functions used from the header. For example,
#include <iostream> // cin, cout, <<, >>, endl #include <cmath> // sin, cos #include "list.h" // List class
The qualifiers public and private should be indented and the member and friend function prototypes and data member declarations indented in from the qualifiers. Free function prototypes should appear after the class definition. For example,
class Counter
{
public:
// Constructors
Counter (); // Creates counter with value of 0
// Accessors
int Value () const; // Returns the current value of the counter
// Friend functions
friend operator++(); // Increments counter by 1
...
private:
int value; // Current value of the counter
}; // end Counter
// Free overloaded I/O operators
istream& operator>> (istream& in, Counter& theCounter);
ostream& operator<< (ostream& out, const Counter& theCounter);
Member and friend function prototypes should appear in the same order as presented in the class specification. If there are many member functions, comments indicating grouping are helpful. E.g., constructors, accessors, mutators, I/O, etc.
Short comments describing what member functions do and what member data represent should be included as shown above.
Member functions that do not change the state of the object should be declared as const as shown above for the Value member function.
Class member, friend, and overloaded function implementations should appear in the same order as presented in the class definition.
Include documentation, as needed, of the following form for each function:
// Function: <name of function>
// Returns: <returned object, if any>
//
// < Short description of what function does in terms of the received
// parameters >
// < Assumptions about the state or values of the received parameters >
void Sample (type1 arg1, // RECEIVED: <short description of object>
type2& arg2,...) // PASSED BACK: <short description of object>
{
...
} // end Sample
There should be one formal parameter per line, lined up under each
other as shown above with comments about the movement and description
of the parameter. The movement of a parameter is in relation to the
function and refers to whether the data is received from the
caller or passed back to the caller.
Function comment headers should be included with member function definitions also. If there are many function definitions, comments indicating grouping are helpful. (E.g., accessors, mutators, I/O, etc.)
Identifiers should be chosen to be self-documenting. Abbreviations, except where standard, should be avoided. In addition, comment variables when usage is restricted. (E.g., an integer used to represent a calendar month, so its valid values are 1-12.)
Each word in a function identifier, class identifier, or structure type identifier should start with an uppercase letter. E.g., FindMinIndex or Point. Each word except the first one in an variable identifier should start with an uppercase letter. E.g., firstName. Constant identifiers should be written in all uppercase with words separated by an underscore (_). E.g., MAX_STRING_SIZE.
Comment the ending curly brace of each compound statement. Such
comments should start with // end along with a brief, mnemonic,
and unique (within the function or main program) comment. For
example,
// Function: Try
// Attempts to do some things...
void Try (...)
{
...
while (!done)
{
...
} // end while there are things left to do
...
} // end Try
Comment the ends of struct, class, and function
definitions with the name of the type or function being defined
as shown above.
Comment code to improve clarity. Comments should tell WHAT is being done or why it is being done, not how it is being done. For example,
// Adjust i to point to the end of the previous word:
i = i - 1
is better than
// Subtract 1 from i:
i = i - 1
Often these comments will be phrases that would be found in the
analysis and design.
Comments should be in good English. Grammar and spelling should be correct.
Abbreviations in comments should rarely be used, and then only those that would be found in a standard dictionary.
Constants should be declared globally if there is a possibility of using them in more than one function, otherwise they should be declared locally to the function that uses it.
Constants in your algorithm should be replaced by constant
identifiers in your program. Exceptions should be made only when the
constant conveys its own meaning, such as 0 as an initial value for a
sum or to start a count, or is part of a constant mathematical
formula, such as 2 in
.
Each (non-class attribute) variable identifier that occurs in a function should be local to that function - that is, declared in the function's header or in the function's body.
int Function1 (const vector<int> & v); // RECEIVED:...
For example, in the main function, we might declare
int main (int argc, char *argv[])
{
const int MAX_SIZE = 100;
const float PI = 3.14159;
int i, // Outer loop index
j, // Inner loop index
tests[MAX_SIZE]; // Array of test scores
Point p1;
...
} // end main
Comments should explain the purpose of each variable where
appropriate, and should line up.
while ((('a' <= line [i]) && (line[i] <= 'z'))
|| (('A' <= line[i]) && (line[i] <= 'Z')))
i++;
An I/O statement should be broken up so that the « or » operators line up. For example, we might write
cout << setw(15) << name
<< setw(30) << address
<< setw(15) << phone << endl;
A long function call statement should be broken up so that the function arguments lined up. For example, we might write
Sample (argument1, argument2, argument3,
argument4, argument5, argument6);
if (first <= last)
found = true;
Each line of the body of a compound statement should be indented. For example,
if (a [middle] = item)
{
item = a [middle];
found = true;
position = middle;
} // end if match found
if (x > 90)
grade = 'A';
else if (x > 80)
grade = 'B';
else if (x > 70)
grade = 'C';
else if (x > 60)
grade = 'C';
else
grade = 'F';
j = i;
while ((j > 1) && (a [j - 1] > a [j]))
{
// a [1..j-1] is unsorted and a [j..i] sorted:
Swap (a [j], a [j - 1]);
j = j - 1
} // end while
void FindMinIndex (...)
{
...
} // end FindMinIndex
;;;;; ;;;;; CC mode customizations ;;;;; (defun my-c-mode-common-hook () ;; use Ellemtel style for all C-like languages (c-set-style "ellemtel") ;; other customizations would go here ) (add-hook 'c-mode-common-hook 'my-c-mode-common-hook)In Emacs LISP, the `;' character starts a comment. This piece of code causes emacs to use the ``ellemtel'' indenting style instead of the default indenting style. The ellemtel style is much closer to the CS 215 guidelines.
Once you have added this code, you must exit out of emacs and
start it up again to see the effect.
Vi does not have smart indenting using the TAB key like emacs.
However, you can configure vi to display tabs as 3 spaces instead of
the default 8 spaces. Tim DeBaillie provides a configuration file
(.vimrc>) at
http://csserver.evansville.edu/~td41/vihelp.html (link
available on the course webpage) that you can download to do this.
However, these .vimrc commands only effect how the
tabs are displayed in vi. When the tabs are printed by a2ps, the
default 8 spaces is still used. However, a2ps has a command line
option (-T#) to print tabs as some number of spaces other than the
default. It is used as follows to get 3 space tabs: a2ps -T3
file1 file2 ... All source code for CS 215 developed under vi should
be printed in this manner. (However, do not print makefiles using
this option.)