Instructor: David Goldschmidt, Ph.D.
Office Hours: after class
Email: click here to email me

Example 1: Hello World

// helloworld.cpp  <== click here for file

// First program in C++

#include <iostream>
using namespace std;

int main()
{
//  std::cout << "Hello folks!" << std::endl;
  cout << "Hello folks!" << endl;

//  (cout << "Hello folks!") << endl;
//  cout << endl;

  return 0;
}

Basic Syntax:

  • Comments are indicated using // for single line comments and /* and */ for multi-line comments.
  • The #include compiler directive asks the compiler for parts of the standard library that we wish to use (e.g. the input/output stream function std::cout).
  • The int main() part is a necessary component of all C++ programs; it returns a value (integer in this case) and it could have parameters (within parentheses).
  • The curly braces (i.e. { and }) indicates that everything between them should be treated as a single logical unit or block.

The Standard Library:

  • The standard library is not a part of the core C++ language. Instead it contains types and functions that are important extensions to the language or platform. We use the standard library to such a great extent that it will feel like part of the C++ core language.
  • Streams are the first component of the standard library that we see.
  • The abbreviation std is a namespace that contains the standard library.
  • Functions std::cout and std::endl are defined in the standard library (in particular, in the standard library header file iostream).

Expressions:

  • Each expression has a value and zero or more side effects.
  • An expression followed by a semi-colon is a statement. The semi-colon indicates the value of the expression should be ignored.
  • The following line is actually two expressions and one statement:
  • std::cout << "Hello folks!" << std::endl;
    
  • The first expression is:
  • std::cout << "Hello folks!"
    
  • The value of this expression is std::cout and the side effect is that "Hello folks!" is displayed.
  • Using the value of the first expresssion, the second expression is as follows:
  • std::cout << std::endl;
    

C++ vs. Java:

  • In Java, everything is an object and everything inherits from java.lang.Object. In C++, functions can exist outside of classes. In particular, the main() function is never part of a class.
  • Source code file organization in C++ does not need to be related to class organization as it does in Java. On the other hand, creating one C++ class (when we get to classes) per file is the preferred organization, with the main() function in a separate file on its own or with a few helper functions.
  • Compare the helloworld.cpp example above with the same example in Java:
  • public class HelloWorld
    {
      public static void main( String[] args )
      {
        System.out.println( "Hello folks!" );
      }
    }
    

Example 2: Temperature Conversion

Our second introductory example converts a Fahrenheit temperature to a Celsius temperature and decides if the temperature is above the boiling point or below the freezing point.

// tempconversion.cpp  <== click here for file

#include <iostream>
using namespace std; // Eliminates the need for std::

int main()
{
  // Request and input a temperature.
  cout << "Please enter a Fahrenheit temperature: ";
  float fahrenheit_temp;
  cin >> fahrenheit_temp;

  // Convert it to Celsius and output it.
  float celsius_temp = (fahrenheit_temp - 32) * 5.0 / 9.0;
  cout << "The equivalent Celsuis temperature is " << celsius_temp
       << " degrees.\n";

  // Output a message if the temperature is above boiling or below freezing.
  const int BoilingPointC = 100;
  const int FreezingPointC = 0;
  if ( celsius_temp > BoilingPointC ) {
    cout << "That is above the boiling point of water.\n";
  } else if ( celsius_temp < FreezingPointC ) {
    cout << "That is below the freezing point of water.\n";
  }

  return 0;
}

Variables and Constants:

  • A variable is an object with a name (a C++ identifier such as fahrenheit_temp or celsius_temp).
  • An object is assigned memory and has a type.
  • A type defines structure and a set of valid operations.
  • A constant such as BoilingPointC and FreezingPointC (defined using const) is an object with a name, but a constant object may not be changed once it is defined and initialized. Any operations on integer types may be applied to a constant int, except operations that attempt to change its value.

Expressions, Assignments, and Statements:

  • Consider the following statement:
  • float celsius_temp = (fahrenheit_temp - 32) * 5.0 / 9.0;
    
  • If we used 5/9 instead of 5.0/9.0, we'd always get 0, because 5 and 9 are both integers and dividing two integers always yields an integer (by truncating any digits after the decimal point).
  • The calculation on the right-hand side of the = operator is an expression, which is evaluated based on the definitions of C++ arithmetic expressions and operator precedence. The rules in C++ are almost identical to that of Java.
  • The resulting value of this expression is assigned to (i.e. stored in the memory location of) the newly created float variable named celsius_temp.

Conditional statements:

  • The general form of an if-else statement is:
  • if ( conditional-expression ) {
      statement;
    } else {
      statement;
    }
    
  • Each statement may be a single statement, such as the cout statement in the example code, or a compound statement delimited by { and }.
  • Though { and } are not required for a single statement, it is strongly encouraged to include them anyways to improve readability and avoid error later when additional lines are added (and { and } are not!).

Example 3: Julian Day

A Julian Day simply tells us the number of days that have passed since the beginning of the given year. For example, the Julian Day corresponding to May 18, 2009 is 138 (or 31+28+31+30+18).

// julianday.cpp  <== click here for file

#include <iostream>
using namespace std;

const int DaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

// The following function returns true if the given year is a leap year
// and returns false otherwise.
bool
is_leap_year( int year )    // Pass by value
{
  return year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 );
  // A leap year occurs every four years, but not when a year is
  //  divisible by 100; however, if a year is divisible by 400, it
  //  actually is a leap year.  See Wikipedia!
}

// Calculate and return the Julian day associated with the given
// month and day of the year.
int
julian_day( int month, int day, int year )    // Pass by value
{
  int jday = 0;

        // initialize      ; condition ; update
  for ( unsigned int m = 1 ; m < month ; ++m )
  {
    jday += DaysInMonth[ m - 1 ];
    if ( m == 2 && is_leap_year( year ) ) ++jday; // February 29th
    // <== the "update" part happens here (i.e. ++m or m++)
  }
  jday += day;
  return jday;
}

int main()
{
//  DaysInMonth[15] = 30;  <== will compile and run, but behavior is unpredictable

  cout << "Please enter three integers (a month, a day and a year): ";
  int month, day, year;
  cin >> month >> day >> year;

  cout << "That is Julian day " << julian_day( month, day, year ) << endl;
  return 0;
}

Arrays and Constant Arrays:

  • An array is a fixed consecutive sequence of objects, all of the same type.
  • The following statement declares an array of 15 double values:
  • double a[15];
    
  • The values are accessed through subscripting operations, as follows:
  • int i = 5;
    a[i] = 3.14159;  // assign 3.14159 to index 5 (6th position) of the array
    a[7] = 2.78183;  // assign 2.78183 to index 7 (8th position) of the array
    
  • C++ array indexing starts at zero. So does Java (and many other languages).
  • Arrays are fixed size, and each array knows nothing about its own size. The programmer must write code that keeps track of the size of each array.
  • In the given statement:
  • const int DaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    
  • The global array DaysInMonth is an array of 12 constant integers, indexed from [0] to [11].
  • The list of values within the curly braces initializes the 12 values of the array, as in:
  • DaysInMonth[0] = 31;
    DaysInMonth[1] = 28;
    DaysInMonth[2] = 31;
    // ...
    DaysInMonth[10] = 30;
    DaysInMonth[11] = 31;
    

Functions and Arguments:

  • Functions break code up into modules that ease programming and testing, and improve the readability of the code by others.
  • Functions are blocks of code that are reusable in one or more programs.
  • Each function has a sequence of parameters and a return type, as designated by the function prototype Given the example function prototype below, the julian_day() function has a return type of int and three parameters, each of type int:
  • int julian_day( int month, int day, int year )
    
  • The order of the parameters in the calling function must match the order of the parameters in the function prototype.

Loops:

  • The basic form of a for loop is:
  • for ( expr1 ; expr2 ; expr3 ) {
      statement;
    }
    
  • expr1 is the initial expression executed before the loop iterations begin.
  • expr2 is the test applied at the beginning of each loop iteration. The loop ends when this expression evaluates to false or 0.
  • expr3 is evaluated at the very end of each iteration.
  • A purely mechanical process translates a for loop to a while loop (and vice versa), as shown in the example code below:
  • for ( unsigned int m = 1 ; m < month ; ++m )
    {
      jday += DaysInMonth[ m - 1 ];
      if ( m == 2 && is_leap_year( year ) ) ++jday; // February 29th
    }
    
    // rewrite above for loop as a while loop:
    
    unsigned int m = 1;
    while ( m < month )
    {
      // same code from above
      jday += DaysInMonth[ m - 1 ];
      if ( m == 2 && is_leap_year( year ) ) ++jday; // February 29th
      ++m;
    }
    
  • The only difference between the two loops shown above is the scope of variable m.

When is a Leap Year a Leap Year?

  • Consider the single statement in the is_leap_year() function:
  • return year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 );
    
  • Conditional expressions are evaluated from left to right. So, if year is not divisible by 4, the function immediately returns false, without evaluating the right-hand side of &&.
  • For a year that is divisible by 4, if year is not divisible by 100 or is divisible by 400, the function returns true. Otherwise, the function returns false.
  • The function will not work properly if the parentheses are removed, in large part because && has higher precedence than ||.

Example 4: Scope

// scope.cpp  <== click here for file

#include <iostream>
using namespace std;

int main()
{
  int a = 5, b = 10;  // SCOPE "A"
  int x = 15;

  // New SCOPE "B"
  {
    double a = 1.5;
    b = -2;
    int x = 20;
    int y = 25;
    cout << "a = " << a << ", b = " << b << '\n'
         << "x = " << x << ", y = " << y << endl;
  }
  // SCOPE "B" ENDS!  So a, x, y are "gone"

  // ADD here within scope "A":  int y = 400;

  cout << "a = " << a << ", b = " << b << '\n'
       << "x = " << x << ", y = " << y << endl;

  return 0;
}

Scope:

  • The scope of a name (identifier) is the part of the program in which it is visible and has meaning.
  • Curly braces { and } establish a new scope, including functions, compound statements, loops, etc.
  • This means scopes may be nested.
  • Identifiers may be reused as long as they are in different scopes. This is usually a bad idea (since it causes confusion).
  • Identifiers (variables or constants) within a scope hide or overshadow identifiers within an outer scope having the same name. This does not change the values of hidden variables or constants; they are just not accessible.
  • When } is reached, a scope ends. All variables and constants (and other identifiers) declared in the scope are eliminated. Further, identifiers from an outer scope that were hidden become accessible again in any code that follows.

Example 5: Month/Day Function

// monthdayfunction.cpp  <== click here for file

// Compute the month and day corresponding to the Julian day within
// the given year.
void                                     // pass by reference
month_and_day( int julian_day, int year, int &month, int &day )
{
  bool month_found = false;
  month = 1;

  // Loop through the months, subtracting the days in this month
  // from the Julian day, until the month is found where the
  // number of remaining days is less than or equal to the total
  // days in the month.
  while ( !month_found )
  {
    // Calculate the days in this month by looking it up in the
    // array. Add one if it is a leap year.
    int days_this_month = DaysInMonth[ month - 1 ];

    if ( month == 2 && is_leap_year( year ) )
      ++days_this_month;
    if ( julian_day <= days_this_month )
      month_found = true; // Done!
    else
    {
      julian_day -= days_this_month;
      ++month;
    }
  }
  day = julian_day;
}

Value Parameters and Reference Parameters:

  • Consider the line of code in main() that calls the month_and_day() function:
  • month_and_day( julian, year, month, day_in_month );
    
  • Here's its function prototype:
  • void month_and_day( int julian_day, int year, int &month, int &day )
    
  • The first two parameters are value parameters. These are essentially local variables (in the function) whose initial values are copies of the values of the corresponding argument in the function call.
  • Thus, the value of julian from main() is used to initialize julian_day in the month_and_day() function.
  • Changes to value parameters do not change the corresponding argument in the calling function (i.e. main() in this example).
  • Note the & in front of the third and fourth parameters. These parameters are reference parameters, as indicated by the &.
  • Reference parameters are just aliases for their corresponding arguments. No new variable are created.
  • As a result, changes to reference parameters actually change the corresponding variables (arguments) in the calling function.
  • When a function needs to provide just one result (e.g. is_leap_year()), make that result the return value of the function and pass all parameters by value.
  • When a function needs to provide more than one result (e.g. month_and_day()), these results should be returned using multiple reference parameters.

Arrays as Function Arguments:

  • Consider the following function:
  • void
    do_it( double a[], int n )
    {
      for ( int i = 0 ; i < n ; i++ )
      {
        if ( a[i] < 0 )
          a[i] = 0;
      }
    }
    
  • What does this function do?
  • Changes made to array a are seen in the calling function (e.g. back in main()), even though a is passed by value!
  • Here's why: the memory location of the start of the array is passed by value (i.e. copied). The actual entries of the array are not copied; therefore, changes to these entries are seen in the calling function.
  • The number of locations in the array to work on (i.e. the value parameter n) must be passed in as well, because arrays have no idea about their own size.

Exercises and Questions

  1. What is the output of the following code?
  2. void swap( double x, double &y )
    {
      double temp = x;
      x = y;
      y = temp;
    }
    
    int main()
    {
      double a = 15.0, b = 20.0;
    
      cout << "a = " << a << ", b = " << b << endl;
      swap( a, b );
      cout << "a = " << a << ", b = " << b << endl;
    
      return 0;
    }
    
  3. Write a swap() function that correctly swaps two elements. Test your function using main() from above.
  4. Write a rotate() function that takes three elements and swaps values by rotating the values to the right. More specifically, for inputs x, y, and z, resulting values should be z, x, and y. Test using code in main().
  5. Write a rotate_right() function that takes an array as input and rotates all values to the right. Test using code in main().
  6. Write a rotate_left() function that takes an array as input and rotates all values to the left. Test using code in main().
  7. Using the monthdayfunction.cpp code from Example 5 above, write a main() function that asks the user for the Julian day and year. The program uses the month_and_day() function to determine the corresponding month and day. Display the resulting values to the user.
  8. Write a sum_it_up() function that calculates the sum of all values in an integer array passed in as an argument. Test using code in main().