More than just the > and < can use used to make
decisions with variables. There are a few more operators.
- == is the equal comparison
- != is the not equal to comparison
- >= is greater than or equal to
- > greater than
- < less than
- <= less than or equal to
Comparisions return a value which can actually be stored in a variable called bool,
which is short for boolean. Comparisons either return true(non-zero) or false(zero).
If the expression in the if statement is non-zero it will evaluate true and execute
its code. Variables can be left by themselves in an if to test for this as well:
if (x) cout << "X is not zero" << endl;
! used by itself means "not" which reverses the expression:
if (!x) cout << "X is zero" << endl;
In addition to comparing numbers, boolean expressions can also be compared using
the logical comparison operators (use parenthesis to seperate the expressions):
- || (the double pipe symbol) means or
- && means and
if ((x > 10) && (x < 15)) cout << "x is between 10 and 15" << endl;
if ((x == 5) || (x == 6)) cout << "x is 5 or 6" << endl;
if ((x != 5) && (x != 6)) cout << "x is neither 5 nor 6" << endl;
The comparasions can be assigned to a bool variable like this:
bool xtest = (x>10) && (x<15);
if (xtest) cout << "x is between 10 and 15") << endl;
if (!xtest) cout << "x is not between 10 and 15" << endl;
This last segment could also use an else:
bool xtest = (x>10) && (x<15);
if (xtest) cout << "xtest is true" << endl;
else cout << "xtest is false" << endl;
A very common mistake made by programmers moving from other languages is using the
assignment operator, =, instead of the equals operator, ==
(double equal signs). Both of these operators are valid in an if, but an assignment
is rarely used in this case.
if (x = 5) //this is ALWAYS true since it will evaluate for 5, which is non-zero
if (x == 5) //this is probably what the programmer meant
On most compilers using the assignement instead of the equals will generate a courteous
warning.
Back To Top
Functions in C work just like they do in any other langage,
except that C programmers tend not to make the distinction between procedures, which
do not return values, and functions, which do return values. Like the main function,
each function declaration requires 3 parts: the return type, the function name,
and the parameter list. A function prototype(some programmers call this the "interface")
in C looks like this:
void MyFunction();
This function does not return a value, denoted by void, and its name is
MyFunction. There are no parameters, as denoted by the lack of parameter
information inside the parenthesis. Notice that the prototype ends with a semi-colon.
This tells the compiler that the function exists, but will be declared later(this
part is sometimes referred to as the "implementation"). This is done so
that the main function is at the very top of the program while the code for other
functions is declared below. This is not a nessacity--functions can be declared
without prototypes above the main function, but the program becomes harder to read
and follow. Below is a short example program demonstrating a basic function call:
#include <iostream>
using namespace std;
void DisplayGreeting();
void SayGoodbye();
int main() {
DisplayGreeting();
SayGoodbye();
return 0;
}
void DisplayGreeting() {
cout << "Hello user!" << endl;
}
void SayGoodbye() {
cout << "Goodbye!" << endl;
}
This method for functions is pretty straight forward. Parameters are not much more
complex:
void DisplayNumbers(int numb1, int numb2, float numb3) {
cout << "Number 1: " << numb1;
cout << "Number 2: " << numb2;
cout << "Number 3: " << numb3;
}
Notice that each variable in the list needs a variable type in front of it. Call
the function like this:
int main() {
int x = 26;
DisplayNumbers(50, x, 34.1);
return 0;
}
Returning values require only changing the variable type before the name and using
a return command at the end of the function.
float GetSquare(float numb);
int main() {
float sq = GetSquare(3.0);
cout << "sq is " << g;
cout << "Five squared is" << GetSquare(5.0);
return 0;
}
float GetSquare(float numb) {
return numb * numb;
}
A shortcut method to the function prototyes is to only include the variable type.
The compiler does not need to know the name until the function declaration later,
however most programmers still include the variable name because not only does the
name help to describe what the variable is, but also because it is easy to write
the function, then copy/paste the first line to the top of the program and just
simply replace the { with ;. Here are several ways to prototype the same function:
float FindDistance(float x1, float y1, float x2, float y2);
//or use:
float FindDistance(float, float, float, float);
//Notice how the names helped to clairify what is being passed
float FindDistance(float x1, float y1, float x2, float y2) {
return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
Notice how including the names clarified the function's purpose. Also, on a side
note, notice that in the implimentation of FindDistance
does NOT use a square function, since C does not have one, however the programmer
can choose to write a square function.
Back To Top
The true purpose for the int
main() has not yet been fully explained. Like other languages, functions
return values in C. Your program is called from a function in the operating system
just like it was any other function. An integer can be returned to the operating
system to denote an error in the program. Although this is a rarely used feature
in Windows, it is used in cases like scandisk, which the main function returns non-zero
if the user canceled or if an error was encountered, that is how the computer knew
to display the "scandisk was canceled or had an error" message. In UNIX
and Linux environments, the return code is often used to control the flow of scripts.
The return code can also be used in DOS/Windows batch files. Since some value is
always returned, C/C++ gives a warning about void main()
being void and not int.
Back To Top
The syntax for loops in C requires three parts, the beginning
condition, the test, and counter update. In reality, each of these lines are simply
just lines of code that are executed before the loop and after it. Below is a simple
C loop:
for (int c=0; c < 9; ++c)
cout << "Loop counter is " << c << endl;
The loop executes until the test becomes false, also note that if the test BEGINS
false the control will never enter the loop. Notice there were no braces on the
for loop, but if there were multiple lines the code would need to be in a block.
A while loop continues until the condition given becomes false, and like the for
loop, if the condition starts as false control will never enter the loop. The parameters
for the for loop can be better understood by looking at how the same code is written
as a while loop:
int c = 0;
while (c < 9) {
cout << "Loop counter is " << c << endl;
++c;
}
A do..while loop is virtually the same thing as a while loop, except that the test
comes at the END of the loop rather than at the start, so that the control will
enter the loop AT LEAST once. Do..while loops are used mostly for input protection:
float x = 0.0f;
do {
cout << "Enter a number between 5 and 6: ";
cin >> x;
} while ( ( x > 5.0f ) && ( x < 6.0f ) );
The two major diffences between this loop and the rest are using two keywords, one
at the beginning, and one at the end, and using a semi-colon after the structure.
Notice that the variable is declared outside of the loop's "scope." A
variable declared in a block can only be viewed in that block and blocks inside
that block. So if a variable would be declared in the loop, only the loop can see
that variable.
Back To Top
User input, espically with menus, will require many
decisions. Imagine a menu of choices, and the user enters a number to select which
option he or she desires:
#include <iostream>
using namespace std;
void EnterNewUser();
void DeleteUser();
void FindUser();
int main() {
bool cont = true;//For use in while loop
while (cont) { //Contiune until user selects quit
//Display Menu
cout << "Network Management--Users" << endl;
cout << "1 - Enter a new user" << endl;
cout << "2 - Delete a user" << endl;
cout << "3 - Find a user" << endl;
cout << "4 - Exit this menu" << endl;
int choice;
cout << "Enter choice: "; cin >> choice;
if (choice == 1)
EnterNewUser();
else if (choice == 2)
DeleteUser();
else if (choice == 3)
FindUser();
else if (choice == 4)
cont = false;
else
cout << "Invalid choice!" << endl;
} //End of while loop
return 0;
} //End of main()
After some time the if..else if statements can become cumbersome and redundant.
C allows for a shortcut decision structure which only works on integer types (char,
short, int, long). Below is the same decisions from the program above except in
a "switch" statement:
switch (choice) {
case 1:
EnterNewUser(); break;
case 2:
DeleteUser(); break;
case 3:
FindUser(); break;
case 4:
cont = false; break;
default:
cout << "Invalid choice!" << endl; break;
}
A block of code under the case need not be in braces, UNLESS a variable is declared
inside the switch, then braces are needed to define its scope. The break statement
tells the computer to exit the swtich instead of continuing the statements. If the
breaks are eliminated, control simply passes through any other case statements and
continues until the end of the switch or a break statement. This is not used often,
but the following is an example of how a switch could be used for this:
int x=0;
cout << "Enter an integer: "
cin >> x;
switch (x) {
case 1:
cout << "X is 1" << endl;
case 2:
cout << "X is 2 or 1" << endl;
case 3:
cout << "X is 3 or 2 or 1" << endl;
break; //This will stop control from going into default
default:
cout << "X is less than 1 or greater than 3" << endl;
}
And an example of using braces (x can ONLY be seen inside the braces and not in
other cases or outside the switch, as the braces denote its scope):
switch(x) {
case 1: {
int x = 0;
cout << "Enter for x: "; cin >> x;
cout << "x is " << x << endl;
break;
}
}
Back To Top
When using larger amounts of data, a seperate name for each
variable would be redundant and masochisitc at best, so a better method would be
to use an array. An array declaration is just like a variable declaration except
a number is added:
int myarray[10];
This statement declares an array of 10 integers. The indexes for the array start
from 0 and go to 9. For those curious why the indexes are numbered this way, Pointers
I will explain in depth the exact reason for this.
A for loop is the best structure for accessing a fixed size array like this one.
This program asks the user to enter data into the array above then displays it.
for (int c=0; c < 10; c++) {
cout << "Enter an integer: ";
cin >> myarray[c];
}
for (int c=0; c < 10; c++)
cout << "Element " << c << " is " << myarray[c];
Accessing the array only requires the name, followed by the element number in brackets,
which can be a constant (myarray[2]=3;) or a variable
(myarray[c]=6;). However, when using variables to
access the array, in C there is NO error checking. The statement
myarray[50]=10; will execute in the above program despite it being obviously
out of range. This will overrun the array, and write in memory which may contain
other variables, or even your code! Obviously this will cause major problems and
the program may not crash immedately until the corrupted memory is accessed, or
may never even crash at all! So if a program is performing weird actions without
any other explanation, check for "memory overruns" like this one. Security
experts will call this problem a "buffer overrun", and buffer overruns due to user
or program input and are the current leading cause of virii and worms.
To initalize an array, braces and data seperated by commas will fill the array with
data, like this:
int myarray[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
You do not even have to initalize all elements either. If the list stops before
the end of the array, the rest of the elements become 0.
int myarray[10] = {}; //All elements are 0
Two dimentional arrays, or matrices work just like their one-dimentional or vector
counterparts, just that they use more brackets. The same pattern applies for 3D
and so on to infinity.
int matrix[5][5]; //2D array
int space[100][100][100]; //3D array
int wow[3][3][3][3]; //Even 4D and more work!
Keep in mind that 2D arrays are really an array of arrays. For example the matrix
above is really a 5 element array contaning int arrays of 5 elements. I mention
this for understanding that accessing an array sequentially requires looping the
last values, for faster access, since it accesses sequentially and does not jump
around. Two ways of looking at the elements is [row][col]
or [y][x]. This is best shown in code:
for (int row=0; row < 5; row++)
for (int col=0; col < 5; col++)
cout << matrix[row][col] << endl;
This is the fastest way to access the array in memory. If row and col were switched,
the computer would jump in memory. The best way to show this is visually. In memory
the array is stored like this:
[0][0], [0][1], [0][2], [1][0], [1][1], [1][2]
Going from [0][0] to [0][1]
requires only a simple addition to the computer, while going from [0][0] to [1][0]
the computer needs to skip over 2 elements.
Initializing an array makes sense when seen--you need to initialize the array with
arrays:
myarray[2][2] = {{56, 76}, {12, 78}};
Notice how arrays are the elements, which have elements as well.
Back To Top
Strings in C are MUCH more compicated than in a language
like BASIC. Other languages like BASIC tend to hide the fact that strings are arrays
of characters and need to be treated that way. In C++, many programmers use the
string class which lets the programmer use strings like in BASIC. I will first describe
C-style strings.
The asterisk after char means it is a pointer or an array. Until the Pointers I
lession, regard both char[] and char* as meaning the same thing. I note this because
most programmers refer to a C-style string as char *, and when passed to a function
the parameter type is char *. When you declare a string, the easiest way to do it
is to declare it as an array.
char mystring[500] = "";
This declares a string of 500 characters. Note the double quotes. Each string must
ALWAYS be initialized before using it, since all C-style strings must end with a
NULL character (ASCII 0). The compiler interprets strings this way--it contines
to process characters (in a cout or cin or string operation) until it hits a character
with value 0 -- the NULL character. If this NULL character does not exist, then
the computer will process the memory in the string and flow over, until it happens
to hit a NULL by chance or runs out of memory. This is also considered a memory
overrun and will cause your program to crash or print out random characters.
Strings cannot be copied since they are arrays. This rule applies to any string
operation. Below are some things that will not work with strings that might for
other variables. Also keep in mind the array needs to be large enough to contain
any possible strings that may enter it, or the array may "overrun."
char str1[100] = "Mom";
char str2[100] = "Dad";
char str3[100] = "Mom";
str3 = str1 + str2; //Cannot add strings like this
if (str1 == str3) //Cannot compare strings
In order to work with strings like this, one needs to use the C library string functions.
Below are equalvalent statements to those above that work (the declarations are
not repeated):
/* C-only code */
#include <string.h> //For C string functions
strcpy(str3, str1); //Moves str1 to str3
strcat(str3, str2); //Adds str2 to the end of str3
if (strcmp(str1, str3) == 0)//If these are equal
Fortunately C has a way for simplifing this process of processing and comparing
strings. Sprintf works just like printf but sends the data to a buffer (the string).
sprintf(str1, "I am a %s and my spouse is a %s", str2, str3);
//str1 becomes "I am a dad and my spouse is a mom"
Sprintf simplifies most string operations. These operations are the reason why the
strings were declared with more characters than they really needed, since in this
case, str1 grew to be much larger. The size of str1 needs to be big enough to hold
the output from sprintf.
With all this work one can see why most programmers in C++ choose to use a string
class which allows operations like the first ones listed. The C++ string class helps
to prevent buffer overruns and allows high-level operations more easily.
#include <iostream> //for cout
#include <string> //for string class
using namespace std;
int main() {
string x = "Hello, ";
string y = "World!";
string s = x + y; //this is allowed, unlike for char* and char arrays
cout << s << endl;
if ( s == "Hello, World!" ) //this also works with C++ strings
cout << "comparison succeeds" << endl;
return 0;
}
It is possible to construct C++ strings similar to how cout works -- this invovles
using an ostringstream object:
#include <iostream> //for cout
#include <string> //for string class
#include <sstream> //for ostringstream
using namespace std;
int main() {
ostringstream temp;
//construct like you might with cout
temp << "Hello, World! 15 + 20 = " << (15 + 20) << endl;
string s = temp.str(); //this gets the string constructed
cout << s << endl;
return 0;
}
This code is somewhat advanced for this part of the tutorial, so if you do not understand
it at this time, don't worry until to read the object-oriented programming tutorial,
but you can use the above code as a template to construct C++ strings.
Back To Top
Move onto the first section of part 3