C++ Language Coding Style

CS Home Page: Web Course Materials: C++ Coding Style

 

Department Computer Science
San Jose State University

Delimiter Pairs

Braces { } and the comment delimiters /* */ must be lined up so that they are either on the same line or in the same column.

Example:

while (!done)
{
   ...
}
Example: /* read the next three lines for this record */

 

Example:

 

/* In this part of the program we will:
   (1) Read each part number;
   (2) Check if it is already in the data base;
   (3) Add it to the database if it isn't there.
*/
The following commonly used forms are NOT allowed within our guidelines:

Incorrect example:

while (!done){

   ...

}

Incorrect example: if (i < j){
   b[i] = a[i];
   a[i] = a[j];
}
Indenting.

You must indent your code inside braces.

Three spaces are required per indentation level. (This can be set by selecting Properties from the View menu.) The body of a for loop or while loop or the statement following an if or an else must be indented one level (3 spaces).

Example:

for (i = 0; i < n; i++)

   for (j = 0; j < i; j++)

   {   a[i][j] = 1.0 / (i + j + 1);

      a[j][i] = 0.0;

   }

Incorrect example:    for (i = 0; i < n; i++)

      for (j = 0; j < i; j++)

{ a[i][j] = 1.0 / (i + j + 1);

    a[j][i] = 0.0;

    }

Blank lines and spaces.

Use blank lines to separate logically separate parts of a function.

Example (notice the blank line between the two for loops):

   /* --build a max heap */
   for (i = n/2; i > 0; i--)
      perc_down(a, i, n);

   /* --do n delete_max operations */
   for (i = n; i >= 2; i--)
   {
      swap(&a[1], &a[i]);
      perc_down(a, 1, i-1);
   }

Leave one blank space after all keywords (if, while, for, ... ).

Leave no blank before and one blank after a comma or semicolon.

Example:

for (i = 0; i < n; i++)   /* blanks near keywords

                         blanks near semicolons

                        */

search_down(i, n); /* blanks near commas */

Leave no blanks before or after [ ].

Leave one blank before and one after each binary arithmetic, logical, and assignment operator.

Examples:

e[i] = 1.0 / (i + j + 1);

if ((a == b) || (a < c))

 

Documentation.

Separate each function from the next with a single line of the following format:

/*-----------------------------------------------*/ Each function MUST be documented with a header comment which comes between the definition and the body of the function. Use the following format for every function except main. /* PURPOSE:      What does this function do? (must be present)
   RECEIVES:   List every argument name and explain each argument.
               (omit if the function has no arguments)
   RETURNS:      Explain the value returned by the function.
               (omit if the function returns no value)
   REMARKS:      Explain any special preconditions or postconditions.
               See example below. (omit if function is unremarkable)
*/
Example: /*-----------------------------------------------*/
string digit_name(int n)
/* PURPOSE:      turn a digit into its English name
RECEIVES:   n - an integer between 1 and 9
RETURNS:      the name of n ("one" . . . "nine")
REMARKS:      Precondition: n must be between 1 and 9
               If this precondition is not satisfied,
               the empty string is returned.
*/
Note that each argument is listed and explained in the RECEIVES: section. Note also that assumptions that are made in the function about the input parameters (preconditions) are explained in the REMARKS: section as well as conditions that will be true after the function is executed (postconditions).

Comments are designed for the human reader. That person may be you six months from the time you first wrote a program when your boss asks you to add some feature to your program or it may be someone who will have to take over your program when you advance to another job. Write comments so that someone unfamiliar with your program can understand what you did.

Some of the best comments are good names for variables. If you name a variable cost_per_item instead of c, it will help the human reader to understand what you are doing.

Some general rules:

Comment as you code. If you comment after your program has been written, the comments will never be as clear and precise. Moreover, good comments will help you crystalize your thinking and help you to get a program debugged sooner.

When you declare a new variable, comment its use. Never again will you know so well why you needed it.

When you first are thinking of writing a function, write the function statement and the function header comment before you begin to write the function. If you don't understand precisely what a function is supposed to do then you need to think about it some more BEFORE writing it.

Do NOT comment the obvious:

/* if k equals j, increment k */
if (k == j)
   k++;

 

Naming Conventions

The following rules are to be used to decide when to use uppercase and lowercase letters in identifier names.

All variable and function names and all class members are in lowercase with perhaps an occasional uppercase letter as in a name like oldString or an underscore character as in a name like new_value.

All constants are in uppercase with perhaps anoccasional underscore as in MAX_SIZE.

All typedef and class names start with an uppercase letter and are followed by lowercase letters (again with the possible use of an uppercase letter or underscore as in PartsRecord).

Use names that tell you what the variable or function does. For example use string_length instead of sl or next_iterate instead of something like xn. Use previous_x, current_x, and next_x instead of something like x1, x2, and x3.

Putting Together a Source Code File.

A C++ source code file contains the following items must appear in the following order:

(a) Header comment
(b) #include statements
(c) Constant definitions
(d) Class definitions
(e) Global variables
(f) Functions
The header comment has the format shown in the following example. It is the first thing at the beginning of a source code file: /******************************************************
* Copyright (c):   1994, All Rights Reserved.
* Project:         CS 46A Homework #4
* File:            sortcomp.cpp
* Purpose:         compare timings for sort routines
* Start date:      4/2/97
* Programmer:      John Chen
*
******************************************************
*/
The #include section shows the header files (for example, "ccc.h"). #include "ccc.h"
#include "stack.h"
#include "clock.h"
All #include statements should have the file name only inside the quotes. Absolute directory paths such as #include "j:\cs46alab\cccfiles\ccc.h"

 

are strictly illegal. If MSDS cannot find a file, it is because you do not have your directory options set correctly.

The constant definition section contains all constants used in the program. For example,

const int MAX_SIZE = 9 /* maximum characters in a name */
const string EOL = "\n" /* newline character */
const float RATE_INCR = 0.5;
A standard older convention in C++ and C is to use a preprocessor #define to define constants: #define MAX_SIZE 9 This is not permitted in this course.

The class definition section contains all class definitions (if any are present):

class EmployeeTree
{
public:
   EmployeeTree();
   void insert(Employee e);
   void print() const;
private:
   EmployeeNode* root;
};

 

class Class_name
{
public:
   constructors
   mutators
   accessors
private:
   data
};

All data fields of classes must be private. Supply a default constructor for every class.

The global variable definition section contains all global variables. All global variables must be commented and initialized. You can have AT MOST THREE global variables per module. You should be very reluctant to use global variables. Because they are at risk of being modified by ANY function in your program, they can be a serious source of bugs.

The function definition section contains all functions. Some rules about functions:

Functions can be at most 30 lines long. Comments, blank lines, and lines containing only braces are not included in this count. Functions that consist of one long if/else statement may be longer, provided that each branch is ten lines or less.

Sort functions in such a way that each function is defined before the location in which it is first used. This means that main should be the last function in your program.

If Statements.

In if statements, the branches of the if statment can follow on the same line as the if or else if they are one statement or one statement and a return. Otherwise, put them on a new line.

Example;

if (a != 0) b = 1.0 / a; It may be easier to read the same example as follows:

Example:

if (a != 0)
   b = 1.0 / a;
Beware of the "if...if...else" trap: if (a < b)
   if (a < 0.1 * b)
      ...
else
   ...
The indentation suggests that the else belongs to the first if. However, the rule in C++ is that the else will be attached to nearest "else-less" if. That is, the compiler will associate the else with the second if.

Avoid the problem by always using { } as follows:

Example (if you want the else to belong to the first if):

if (a < b)
{
   if (a < 0.1 * b)
      ...
}
else
   ...
Example (if you want the else to belong to the second if): if (a < b)
{
   if (a < 0.1 * b)
      ...
   else
      ...
}
Loops and Nonlinear Control Flow.

Only use for loops when a variable runs from somewhere to somewhere with some constant increment/decrement.

Example:

for (i = 0; i < a.size(); i++)
   print(a[i]);
Do not use the for loop for weird constructs such as for (xnew = a / 2; count < ITERATIONS; cout << xnew)
/* Don't */
{   xold = xnew;
   xnew = xold + a / xold;
   count++;
}
Make such a loop into a while loop. That way, the sequence of instructions is much clearer: xnew = a / 2;
while (count < ITERATIONS) /* Ok */
{   xold = xnew;
   xnew = xold + a / xold;
   count++;
   cout << xnew;
}
Don't use the switch statement. Use if/else instead.

Do not use the break, continue and goto statements. Use a bool variable to control the execution flow.

Magic Numbers.

Use const definitions to define constants in your program. Don't forget that all such constant names must be all UPPERCASE.

Example:

const int BOILING_TEMP = 212; This way if you modify your program to use Celsius intead of Fahrenheit degrees, the change is trivial instead of scanning your program for all occurrences of 212 and modifying each value.

All buffers (vectors that are used to hold data temporarily while it is processed) must have their lengths defined as constants.

Example:

const int LINE_BUFFER_LEN = 80;
...
vector<char> line_buffer(LINE_BUFFER_LEN);
Different buffers should have different named constants for their lengths even if the value of the constants are the same. In this way you can change one later without the others.