C++ Functions and Arrays

Download Report

Transcript C++ Functions and Arrays

Introduction to C++
Functions, Arrays, and Vectors
Topics
C++ Functions
-- passing by reference in C++
C++ Arrays
-- char arrays
-- vectors
C++ Functions
What we called methods in C# are usually referred to
as functions in C++.
Function Prototypes
The C# compiler is a multipass compiler, and so
it is not necessary to “declare” a method before
it is used in C#. This is not true in C++.
In C++, we must declare a function by writing a
function prototype in the code someplace before
the function is ever called. For stand-alone functions
we normally write the function prototypes before main( ).
If the function is completely defined before it is used,
then a separate function prototype is not required.
#include <iostream>
using namespace std;
void printMe(int);
int main( )
{
int a = 5;
printMe(a);
system("PAUSE");
return 0;
}
The function prototype
Calling the function
The function implementation
void printMe(int num)
{
cout << "\nNumber = " << num << endl;
}
Alternatively you could write the code this way:
#include <iostream>
using namespace std;
The complete function definition
void printMe(int num)
{
cout << "\nNumber = " << num << endl;
}
int main( )
{
int a = 5;
printMe(a);
system("PAUSE");
return 0;
}
Calling the function
We usually include the function prologue
with the function prototype.
#include <iostream>
using namespace std;
// The printMe function
// Purpose: outputs the parameter
// Parameter: The value to be output as an integer
// Returns: nothing
void printMe(int);
int main( )
{
int a = 5;
printMe(a);
system("PAUSE");
return 0;
}
void printMe(int num)
{
cout << "\nNumber = " << num << endl;
}
Passing Parameters by Reference
Passing parameters by reference is slightly
different in C++ and C#
C#
void swap( ref int num1, ref int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
C++
void swap(int& num1, int& num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
Passing Parameters by Reference
Passing parameters by reference is slightly
different in C++ and C#
C#
void swap( ref int num1, ref int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
int n = 5; int m = 3;
swap (ref n, ref m);
C++
void swap(int& num1, int& num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
int n = 5; int m = 3;
swap (n, m);
In C++, parameters are passed by value unless you
explicitly tell the compiler to pass by reference.
Passing by const Refernce
C++ has a notion of constantness that does not exist
in C#. When passing a parameter by reference, it is
possible to have a side effect that changes the data in
the calling function. Generally side effects are not
wanted. To avoid side effects, we pass by
constant reference.
void printMe( const Employee& joe);
This is a common idiom in C++. It allows us to
pass an object without having to make a copy of the
object (which is expensive), but avoids any changes
to the object by the function.
If a member function does not change anything
(for example, a “getter”), then you should
make the function a constant function.
string Employee::getAddress( ) const;
Arrays in C++
Arrays in C++
There is a major difference in how arrays are
defined in C# and C++. In C#, arrays are true
objects. In C++ they are not objects.
An array is a list of values … not an object
All values must be of the same type
examScores
89
0
Values are stored in consecutive
memory locations
94
1
78
2
The position where a value is stored
in an array is given by its index.
We sometimes refer to this as the
subscript.
93
3
75
4
99
5
82
6
Indexing always begins with zero
77
7
To access an element of an array, we
use the array name, followed by the index
inside of square brackets
53
8
87
9
Declaring an Array
examScores
data type of array elements
array size
int examScores[10];
the declaration
0
1
2
3
4
5
Good programming style uses a constant for the
array size. For example
const int SIZE = 10;
int examScores[SIZE];
6
7
8
9
Accessing array elements in C++ is identical to C#
examScores
value of examScores[4]
index
89
0
94
1
78
2
93
3
75
4
99
5
82
6
77
7
53
8
87
9
Out of Bounds Errors
When a C++ program is executing, it does not notice
when a calculation results in an array index that is
out of bounds. The address of the element is calculated
and that place in memory is accessed, even if it does
not belong to the array! This is much different than
what happens in C#.
index
someInts
0
0
someInts +4
1
1
int someInts[5], badNum;
someInts +8
2
2
badnum = 100;
for ( int indx = 0; indx <=5; indx++)
{
someInts[indx] = indx;
}
someInts +12
3
3
someInts +16
4
4
badNum
Notice that we over-wrote the variable
badNum with the value of 5! This destroys
the original value in badNum.
100
5
Initializer lists
int examScores [ ] = { 87, 83, 94, 99, 74, 66, 88 };
the array size is automatically determined by the
number of items in the initializer list
Since an array is not an object, there is no
member data nor any methods that return
the size of the array. When passing an array
as a parameter, it is common to pass the size
of the array as an additional parameter.
Two Dimensional Arrays
columns
rows
How we think of a two dimensional array
examScores
78
89
student 2
76
79
82
85
student 3
83
89
91
90
exam 1
exam 2
exam 3
exam 4
student 1
65
97
An Array of Arrays
78
89
student 2
76
79
82
85
student 3
83
89
91
90
exam 1
exam 2
exam 3
exam 4
student 1
65
97
int main( )
{
// declare an array 3 x 4
int examScores[ ][4]= { {78, 89, 65, 97},
{76, 79, 82, 85},
{83, 89, 91, 90} };
const int STUDENT = 3;
const int EXAMS = 4;
for ( int i = 0; i < STUDENT; i++ )
{
double sum = 0.0;
for ( int j = 0; j < EXAMS; j++ )
sum = sum + examScores [ i ][ j ];
}
}
double avg = sum/EXAMS;
cout << “Student # “ << (i+1) << “: “ << avg << “\n”;
Multi-dimensional array as a parameter…
We do not give the size of the first dimension of an
array when passing it, but we do give the sizes of
the remaining dimensions. The size of the first dimension
is passed as a separate argument.
void getPage (char p[][100], int sizeOne);
Char Arrays
We have been using the C++ String
class to represent strings of characters.
Although this is the most convenient way
to represent character strings, the C++
language also represents character strings
as arrays of type char.
The terminal character in the array is the
null terminating character, \0.
someText
h
0
This is called a null terminated string, or
a C-string (this is the only way that a
character string could be represented
in the C language).
e
1
l
2
l
3
Functions that operate on C-strings look for
the null terminating character to know where
the end of the string is.
o
4
\0
5
When creating an array to store a character string,
always be sure that there is room for the null
terminating character.
firstName
Note that is possible to have an array
of characters that is not a C-String.
lastName
S
0
m
1
i
2
t
3
h
4
?
5
?
?
...
char firstName[20] = “John”;
when initialized this way, the
null terminating character is
automatically added at the end.
char lastName[20] = {‘S’,’m’,’i’,’t’,’h’};
when initialized this way, no null
terminating character is added.
This is just a simple array of
characters. It is not a C-String!
J
0
o
1
h
2
n
3
\0
4
?
5
?
?
...
Char Arrays and Loops
You can treat a char array exactly like any other array.
You can use index notation to access individual array
elements
lastName[n] = ‘ t ’;
You can use loops to manipulate arrays elements.
for (int n = 0; n < SIZE; n++)
{
lastName[n] = ‘ - ’;
}
But … be careful not to accidentally replace the null
terminating character with some other character.
Assignment
Although you can use the assignment operator
when initializing an array, you cannot use the
assignment operator anywhere else with a
character array. For example, the following is
illegal:
char aString[10];
aString = “Hello”;
The reason that this does not work is because the
variable aString is a constant pointer to the first
first element of the array, not the array data.
You cannot overwrite this pointer.
Consider two char arrays
char array1[4] and
char array2[4]
array1
array2
Because the array names are constant pointers
you cannot write an assignment statement like this:
array1 = array2;
To copy the characters from one char array to another,
you have to use the strcpy function.
strcpy Function
The easiest way to assign a value to a C-String
is to use the strcpy function.
To use strcpy you must use the include directive
#include <cstring>
No using statement is required, the definitions
in <cstring> are in the global namespace.
Security Issues
Incorrect use of string functions has caused many security
problems because of buffer over-runs. To prevent these problems
use:
“n” versions of functions, like strncpy – you must ensure that
string is null-terminated. If it is not, do it manually after the copy.
“l” versions of functions, like strlcpy – these are not part of the
standard library, but source code is available from BSD
“_s” versions of functions, like strcpy_s – available with Microsoft
development tools, might be included in standard libraries later.
Examples
strcpy (aString, “Hello”);
copies the char string Hello into aString.
includes a null terminating character.
strcpy (aString, bString);
copies the contents of bString into aString.
strncpy (aString, bString, 9);
copies at most 9 characters from
bString into aString.
by making the last parameter one
less than the size of aString, you
can make the copy safe … i.e. it
will not over-run the array.
When you use strcpy, be sure that the last slot
in the array contains the null terminating
character or it will not be a proper c-string.
Equality
Comparing two C-Strings using the equality
operator will compile without errors and will
execute, but will not give you the results you
expect.
char aString[ ] = “abc”;
char bString[ ] = “abc”;
if ( aString == bString )
{
…
strcmp Function
To compare two C-Strings, use the strcmp
function.
You must #include <cstring> to use this
function.
strcmp(strng1, strng2);
returns a value of zero if the strings are equal
returns a negative value if strng1 < strng2
returns a positive value if strng1 > strng2
comparison is done in lexicographic order.
Other <cstring> functions
strcat (strng1, strng2);
concatenates strng2 to the end of strng1.
strlen (aString);
returns the length of aString
does not include the null terminating character
C-String Input and Output
You can use >> and << operators to
input and output C-Strings.
To input a string containing blanks, you
must use
cin.getline (a, n);
where a is a char array and
n is an integer that indicates the max
number of characters to read. Note that
the null terminating character fills one
of these character positions.
These techniques work on files as well
as standard input and output.
Character I/O
Sometimes it is useful to input and output
one character at a time.
cin.get(aChar);
reads one character into aChar.
cout.put (aChar);
writes the character in aChar to
cout.
These work on any character, including
spaces and new-line characters.
Example
The following code will read one character
at a time from standard in and write it to
standard out, until a new-line character is
encountered.
char symbol;
do
{
cin.get (symbol);
cout.put (symbol);
} while (symbol != ‘\n’);
Character Manipulation Functions
The following functions operate on characters. To use
any of these you must
#include <cctype>
No using statement is required. The definitions in
<cctype> are in the global namespace.
The ASCII Code Table
toupper (aChar);
returns the upper case value of aChar as an integer.
tolower (aChar);
returns the lower case value of aChar as an integer.
islower (aChar);
returns true of the value in aChar is lower case.
isalpha (aChar);
returns true if the value in aChar is a letter.
isdigit (aChar);
returns true if the value in aChar is a digit 0 through 9
isspace (aChar);
returns true if the value in aChar is white space.
Vectors
Vectors can be thought of as arrays that grow as
required, while a program is executing. They are
Very similar to C#’s generic List class.
Vectors are formed from a template class in the
Standard Template Library (STL).
Declaring a Vector
#include <vector>
using namespace std;
...
vector <int> v;
the notation <int> defines the type of vector.
In this case, we have declared a Vector of integers.
Accessing Vector Elements
You can use the square bracket notation [ ] to access
elements of a vector, just as you do for an array. Note
however, that you can only access existing Vector
elements this way, you cannot initialize them!
Initializing Vector Elements
To add an element to a Vector for the first time, you
must use the push_back function. push_back adds an
element in the next available position.
v.push_back ( 23 );
The size of a Vector
As noted, the size of a Vector changes as needed, to
accommodate new elements. The current size of a
Vector ( the number of elements in the Vector ) can be
found by
unsigned int n = v.size( );
note that the size( ) function returns an unsigned int.
This can be automatically converted to an int by most
compilers. To be safe, do an explicit cast or use the
unsigned int data type, as shown above.
Passing a vector as a parameter
Keep in mind that a vector is an object. The rule for
passing objects is to pass them by reference, so that
it is not necessary to create a copy of the vector.
If the function will not change the contents of the
Vector, it should be passed by const reference.
Example
#include <iostream>
#include <vector>
using namespace std;
int main ( )
{
vector<int> v;
cout << “Enter a list of positive numbers.\n”;
cout << “End the list with a negative number.\n”;
int next;
cin >> next;
while ( next > 0 )
{
v.push_back( next );
cout << next << “ added to the Vector\n.”;
cout << “v.size( ) = “ << v.size( ) << endl;
cin >> next;
}
cout << “You entered:\n”;
for ( unsigned int i = 0; i < v.size( ); i++ )
cout << v[ i ];
return 0;
}
No foreach loop in C++ 