CMSC 202 - General C++ Coding Standards
Every programming department has some set of standards or conventions
that programmers are expected to follow. The purpose of these standards
is make programs readable and maintainable. After all, you may be the programmer who
maintains your own code more than six months after having written the original.
While no two programming departments'
standards/conventions may be the same, it is important that all members
of the department follow the same standards. Neatness counts!!!
The following standards are to be followed in CMSC 202. A separate
summary page is also available.
Part of every project grade
is based upon how well these standards are followed.
It is your responsiblity to understand these standards.
If you have any questions, ask your instructor,
any of the TAs, or the Computer Science Help Center.
C++ File Extensions
There are numerous file extensions used to designate C++
source code files and header files. For this course, the file
extensions .cpp
for source code files and .h
for header files will be used. No other extensions are permitted.
File Naming
For every project, a file containing only the main( )
function is
required. This file should be named after the project and have a .cpp file
extension. For example, the main( )
function for project 3 would be in a file named Proj3.cpp
.
Auxiliary files (e.g Proj3Aux.cpp) and/or header files
(e.g. Proj3Aux.h) are permitted, but must be named appropriately.
For most projects, you will be creating your own classes. In these
projects, the following standards also apply.
- All C++ classes are defined in a separate header file.
Name each file after the class it contains and give it a
.h
file
extension.
- All C++ classes are implemented in a separate source code file.
Name each file after the class and give it a
.cpp
file extension.
- No member function is to be implemented in a class header file
(i.e., no inline methods are permitted. All implementations belong in the
matching implementation file.)
File Organization
- Every header file must be guarded using the
#ifndef FOO_H
#define FOO_H
.
.
#endif
style. This style is used to avoid multiple inclusions of the header file.
- A header file is to be included in a given file if and only if the header
defines an entity referred to in the given file. For example, suppose the header
file
Foo.h
refers to an
ifstream
entity and a string
entity. Then,
definitely do include fstream
and string
in the Foo.h
. Foo.h
should NOT rely on
Foo.cpp
to include ifstream
and string
prior to including Foo.h
.
Since Foo.cpp
and Foo.h
are part of the same code, Foo.cpp
need not include header files
already included in Foo.h
.
Neither Foo.h
nor Foo.cpp
should include header files
which are unnecessary.
The point is that each .h file is "independent" and therefore the order in which
.h files are listed in a .cpp file doesn't matter.
- The executable for a project must be named after the project.
For example, the executable for project 3 must be named
Proj3
(notice the capital "P"). This is very important because the graders will
look for that file to run your program. The graders will not run
a.out
or any other executable. The executable name is
controlled by your makefile - get it right.
Grading scripts used by the graders assume that you follow this convention.
Class Definition Standards
The following standards must be followed when a class is defined
within it's header (.h) file
- All class names begin with uppercase. Multi-word class names
follow the variable/function naming convention below.
- Only one
private
, protected
and
public
section in a class definition. public
comes first, followed by protected
and then private
.
- Every data member of a class must be
private
.
- You may use global symbolic constants (
const
), but not global
variables.
- Class methods follow function naming conventions below.
- Class methods must have complete function header comments in the
header file. Fewer comments are required in the .cpp file.
- Class methods must be
const
whenever possible.
- Except for explict class input/output methods, class methods
should not perfrom input or output.
- Class data members begin with m_ and follow the variable naming
conventions below.
Example:
int m_length;
int m_nrStudents;
Variable, Constant and Function Declarations
These standards detail how variables and constants should
be declared, proper function prototype declarations as well
as naming conventions.
- Use meaningful descriptive variable names!!
For example, if your program needs a variable to represent
the radius of a circle, call it 'radius', NOT 'r' and NOT 'rad'.
- Begin variable names with lowercase letters
- The use of single letter variables is forbidden, except as simple
'for' loop indices, temporary pointer variables and in special
cases such as x- and y-coordinates.
- The use of obvious, common, meaningful abbreviations is permitted.
For example, 'number' can be abbreviated as 'num' as in 'numStudents'
or as 'nr' in 'nrStudents'.
- If commented, variables must be declared one per line. Comments
should appear on the same line without wrapping (use two lines if necessary).
- Do not use global variables
- Separate "words" within variable names with mixed upper and lowercase.
(e.g. grandTotal)
- Begin function names with uppercase letters.
- Use active function names, generally beginning with a verb
and including a noun -- GetName( ).
- Function prototypes must include parameter names as well as types.
- Default values for parameters must be specified in the prototype.
- Parameters must be passed by reference whenever appropriate.
- Reference parameters must be const whenever appropriate.
- Separate "words" within function names with mixed upper and lowercase.
(e.g. ProcessError)
- Constants should be commented on the same line on
which they occur. Such comments should not wrap; use two lines if necessary.
const int NUM_STUDENTS = 35; // number of students in the class
const int NUM_SECTIONS = 4; // number of sections of CMSC 104
const float CUTOFF = 88.5; // cutoff for an "A" for the 2001
// spring semester
- Constants should be used for magic numbers and strings whenever
possible. Points will be deducted from projects with code written like
that on the left. A "magic number" is a constant that has some meaning
within your program and is often used in multiple places. Use a const int/float/double to give it a name.
Likewise, well known mathematical constants (like PI) should also be
given a name (
const double PI = 3.14159;
.
When used in the usual way, zero and one are NOT magic numbers. Likewise, some constants
found in formulas (Celsius = (5/9)*(Fahrenheit-32) have no meaningful names and are not
considered "magic".
The point is to give names to numbers and strings which already have well known names
(ie PI), are used in the logic of your code and/or are likely to change in some future
version of your code. Giving names to these important values makes your code more
readable and changeable.
Wrong
| Right
|
int array[30]; // a magic number
for (int i = 0; i < 30; i++) // here it is again
array[i] = -3; // what does -3 mean?
if (command == "ADD") // magic string may change someday
// do something
else if (command == "MULTIPLY") // another magic string
// do something else
|
const int ARRAYSIZE = 30;
const int INITIALVALUE = -3;
const string ADD = "ADD";
const string MULTIPLY = "MULTIPLY";
int array[ARRAYSIZE];
for (int i = 0; i < ARRAYSIZE; i++)
array[i] = INITIALVALUE;
if (command == ADD)
// do something
else if (command == MULTIPLY)
// do something else
|
Documentation
The following sections detail the required program documentation.
Failure to adhere to these standards will result in point deductions
from your project submittal.
Use of Whitespace
The prudent use of whitespace (blank lines as well as spaces)
goes a long way to making your program readable.
- Use blank lines to separate pieces of code for readability
to separate unrelated sections of code and thereby group logically related
lines of code together.
This code fragment is unreadable and results in deductions
// count total number of students
for (int i = 0; i < size; i++)
totalStudents += class[i];
cout << "total students = " << total students << endl;
while (moreStudents == true) {
// read student last name
ReadStudentName();
// print full name
PrintStudentName();
// now verify student info
goodInfo = VerifyStudentInfo(student);
if (goodInfo == true)
cout << "good info" << endl;
}
cout << " this is the end" << endl;
and should be formatted like this
// count total number of students
for (int i = 0; i < size; i++)
totalStudents += class[i];
cout << "total students = " << total students << endl;
while (moreStudents == true)
{
// read student last name
ReadStudentName();
// print full name
PrintStudentName();
// now verify student info
goodInfo = VerifyStudentInfo(student);
if (goodInfo == true)
cout << "good info" << endl;
}
cout << " this is the end" << endl;
- DO NOT use tabs (unless your text editor changes tabs to 3 or 4
spaces). Tabs may be interpreted differently by different editors.
- Use 3 or 4 spaces (not 6 or 8) for each level of indentation.
and be consistent. Too much indenting makes the code unreadable and
hastens line wrapping.
// This is an example of good formatting
if ( x > 90 )
{
statement 1;
statement 2;
}
else
{
statement 3;
}
// This is an example of too much indenting
if ( x > 90 )
{
statement 1;
statement 2;
}
else
{
statement 3;
}
// This is an example of inconsistent indenting
if ( x > 90 )
{
statement 1;
statement 2;
}
else
{
statement 3;
}
- Use spaces around all operators. For example, write
x = y + 5;
NOT
x=y+5;
- Using the emacs or xemacs editor along with the .emacs file
provided for you will automatically indent your code appropriately.
The pico editor will not do so.
Use of Braces
- Use a consistent style for braces. See the
indentation styles for
appropriate placement of braces.
- Braces are not required for single statement if/else/while/for structures,
assuming suitable indentation is used to show the structure.
For example, the following structures are permitted
if (grade > 90)
cout << "You got an A" << endl;
else
cout << "No A for you" << endl;
for (i = 0; i < 30; i++)
array[i] = -3;
Comments
Comments are the programmer's main source of documentation.
From "The Practice of Programming" by Brian Kernighan and Rob Pike, page 23
Comments are meant to help the reader of a program. They do not
help by saying things that the code already plainly says, or by
contradicting the code, or by distracting from the code with
elaborate typographical displays. The best comments aid the understanding
of a program by briefly pointing out salient details or by providing
a larger-scale view of the proceedings".
Commenting standards for files, functions, and code are described below.
File Header Comments
EVERY .cpp and .h file should contain an opening comment
describing the contents of the file and other pertinent information.
This "file header comment" MUST include the following information.
- The file name
- The project number
- Your name
- The date the file was created
- Your section number
- Your UMBC e-mail address
- A description of what the code in the file does
For example,
/*****************************************
** File: Proj1.cpp
** Project: CMSC 202 Project 1, Spring 2003
** Author: Bob Smith
** Date: 6/22/99
** Section: 0304
** E-mail: bsmith32@gl.umbc.edu
**
** This file contains the main driver program for Project 1.
** This program reads the file specified as the first command line
** argument, counts the number of words, spaces, and characters, and
** displays the results in the format specified in the project description.
**
**
***********************************************/
Function Header Comments
Function header comments are the primary form of documentation for the user
of our functions and classes. It is important that this documentation be
both complete and accurate as it forms a "contract" between the function/class
user and and the function/class implementer.
EACH FUNCTION and CLASS METHOD must have a header comment that
includes the following information. The full function header comment described below
must appear in the appropriate .h file. Less formal function header comments
are required in the appropriate .cpp file.
- The function's name
- The function's pre-condition(s) (if there are no
pre-conditions, say so).
- The function's post-condition(s).
A pre-condition is a statement giving the condition(s)
that is (are) required to be true when the function is called. The function
is not guaranteed to perform correctly unless the pre-condition
is true (see text page 113). It is NOT just a restatement of the parameter
names and types.
All functions must test for pre-conditions to the extent possible
Until we learn about exceptions, if a false pre-condition
can be handled in code, do so (see CircleArea function below).
A post-condition is a statement describing what will be
true when the function call is completed (assuming the pre-condition is
met and the function completes -- see text page 113).
For example, in Circle.h we would expect to find
prototypes and full function header comments like this
intended for the user of the function
//-------------------------------------------------------
// Name: CircleArea
// PreCondition: the radius is greater than zero
// PostCondition: Returns the calculated area of the circle
//---------------------------------------------------------
double CircleArea (double radius ):
whereas in the .cpp file we expect to find the function
implementation and comments meant for the programmer
// CircleArea
// Given the radius, returns the area
double CircleArea ( double radius )
{
const double PI = 3.14159;
// handle unmet precondition
if (radius < 0.0)
return 0.0;
else
return PI * radius * radius;
}
Pre- and Post-conditions will be discussed in more detail in class.
In-Line Comments
- In-line comments are used to clarify what your code does,
NOT how it does it.
- An in-line comment MUST appear above the code to which it applies
and is indented to the same level as the code.
The following example is acceptable.
// check every element of the array
for (i = 0; i < ARRAYSIZE; i++)
{
// add one to odd values
if (array[i] % 2 == 1)
{
array[i]++;
}
}
The following example is not acceptable
for (i = 0; i < ARRAYSIZE; i++) // check every element of the array
{
if (array[i] % 2 == 1) // add one to odd values
{
array[i]++;
}
}
- Be sure your comments don't contradict the code.
- Don't comment bad code -- rewrite it.
- Don't comment the obvious. Comments like these are worthless.
// return true
return true;
// increment counter
++counter;