Paul's Tutorials - logoC++Tips and Tricks



This page details a few tips and tricks you can employ to accomplish varying tasks and would not normally be explained in this tutorial. Some of them require a certain level of understanding. That level will be written under each heading.

Note that the levels listed here are the absolute minimum levels of knowledge you will need to implement them. It may be easier for you to learn them at a later time.

printf()

Required Level: Lesson 1-1

The printf() function is another method of output from C (the language C++ is based on). It allows you to print variable values right in a text string.

This will be useful later when you start programming the robot.

When you use it, you need to include the library cstdio.

#include <cstdio>

using namespace std;

int main()
{
	int x;
	x=5;
	printf("I have %d puppies!\n",x);

 	return 0;
}

The code above prints I have 5 puppies!

Here is a shortened table of format specifiers (the %d above is an example) that printf() accepts:

This table is from the www.cplusplus.com reference page on printf()

Specifier Type Example
d or i Signed integer -49
u Unsigned integer 435
f Floating point number 58.9784
c Character g
s C String "hello"

See here for a complete table and more details on printf.

Please note that printf will not accept C++ strings (variable type string) If you need to output a string in this manner, use this method for now:

Code Output
string mystring;
mystring = "hello";
printf("I would like to say %s", mystring.c_str());
I would like to say hello

Another way to do this would be to declare a C string; however, you need to have learned the concepts in lesson 6 in order to do that.

Random Numbers

Required Level: Lesson 1-1

First off, the numbers you will obtain through this method are not quite random, as they are created through a predictable algorithm. However, for most purposes, this process is acceptable.

In order to use it, you must include the following libraries:

cstdlib
ctime

Generating Random Numbers

Seeding

Such numbers are created through a random number generator. This generator must be seeded before it can generate any random numbers. The random number generator needs to be seeded ONCE and only ONCE. Seeding multiple times will render the random number generator useless.

Seed it like this:

srand(time(NULL));

This provides a random number seed that changes every time the program is run, because the seed is the time the srand() function is called.

You should generally always seed the random number generator at the beginning of main. Seeding it elsewhere (for example, in a class constructor or in another function) may actually seed it multiple times.

rand()

Then, you can generate random ints like this:

int my_int = rand();

Note that the rand() function takes no parameters. No matter what, the rand() function alone will generate a number from 0 to a value known as RAND_MAX, which can vary, but is at least 32767 (the largest number an int is accepted to handle -- though it can handle more, but memory comes into play there).

Regardless, to bring it into a range, use the modulo operator, like so:

int my_int = rand() % 20;

This will generate a number from 0 to 19. If you want to generate numbers in a specific range, use the following formula:

rand() % ((max-min)+1) + min;

Remember that addition and subtraction ignore the index number (the number you start from). This is why you need to add 1 after the range calculation. Also, DO NOT TAKE THE RESULT OF THE ABOVE EQUATION AND WRITE rand() % result, AS THIS CHANGES THE RANGE OF NUMBERS TO BE GENERATED! (Order of Operations - modulo is grouped with multiplication/division)

For example:

int my_int = rand() % 31 + 1983;

will generate years from 1983 to 2013.

I/O Manipulation

Required Level: Lesson 1-1

If you are a stickler about presentation, there is a whole library for that.

#include <iomanip>

Note that the functions below only work on cout. For a full list of functions provided by this library, see iomanip. Some listed there will also work on cin.

Output operation

An output operation is one of the clauses you put between the << operators in cout statements.

Example

cout << OutputOperation1 << OutputOperation2 << OutputOperation3;

Note that the following functions are not considered output operations.

When considering how to set it up, the following functions do affect following cout statements, if applicable.

setw()

The setw() function allows you to set the width of a specific output operation.

iomanip::setw(int width)

setw() parameters

int width
The number of characters that the following output operation should contain. If there is an excess, the fill character is repeated and put adjacent to the characters output by the following operation.

setw() use

Place this function before the desired output operation.

Code Output
cout << "Not affected" << setw(30);
cout << "Affected" << " Not affected" << endl;
cout << "Not affected"  << setw(30) << "Affected" <<  " Not affected" << endl;
Not affected                      Affected Not affected

setfill()

The setfill() function allows you to set the fill character (normally a whitespace). The fill character is used if an output operation contains fewer characters than the field width.

setfill() affects all output operations following it.

iomanip::setfill(char_type c)

setfill() parameters

char c
Character to use as the fill character in the following output operation.

setfill() use

Place this function before the desired output operation.

Code Output
cout << setfill('+') << setw(10) << "hi" << endl;
++++++++hi

Text alignment

These functions are actually a part of iostream, so iomanip is not required to use them.

They change the alignment of output operations depending on the field width, not necessarily the screen size.

It is also important to note that these functions affect all output operations following their use, meaning if you want it to change back, you have to use the proper function.

Text is normally aligned to the right.

left

Sets the output stream to put fill characters after successive output operations (causing a left alignment).

left parameters

The parameter for left is the following output operation, therefore, parentheses are unnecessary.

left use

Use left before the output operations to be left-aligned.

Code Output
cout << setfill('+') << setw(10) << left << "hi" << endl;
hi++++++++

right

Sets the output stream to put fill characters before successive output operations (causing a right alignment).

right parameters

The parameter for right is the following output operation, therefore, parentheses are unnecessary.

right use

Use right before the output operations to be right-aligned.

Code Output
cout << setfill('+') << setw(10) << right << "hi" << endl;
++++++++hi

internal

Sets the output stream to put fill characters in the middle of successive output operations (splitting the readout in two).

internal parameters

The parameter for internal is the following output operation, therefore, parentheses are unnecessary.

internal use

Use internal before the output operations to fill internally.

Code Output
cout << setfill('+') << setw(10) << internal << "hi" << endl;
h++++++++i

Clearing the Screen

Required Level: Lesson 1-1

Clearing the screen actually depends on which platform you are using, because how the terminal is implemented between different platforms changes.

Clearing the Screen on Windows

Use this function.

Clearing the Screen on Unix-Derived Systems

Unix-derived systems are systems such as OS X, Linux, BSD, or basically anything that is POSIX-compliant. This will work for any such system.

Unix-derived systems actually have a rather standard way to do this, since someone developed a library that made terminal handling easier. All you have to do is print the right control sequence to the terminal. The code below (borrowed from here) provides a fairly robust way to do it:

#include <unistd.h>
#include <term.h>

void clearScreen()
{
	if (!cur_term)
	{
   		int result;
   		setupterm(NULL, STDOUT_FILENO, &result);
	   	if (result <= 0)
      		return;
	}
  
	putp(tigetstr("clear"));
}

The last line (the putp(tigetstr("clear"))) basically asks the terminal for the control sequence to clear the screen, and then prints it.

If you use this, you will need to link the right library (older systems use -lterminfo, newer Ubuntu systems use -ltinfo, other POSIX-compliant systems might use -lcurses or so on).

Reading from Unbuffered Input

Required Level: Lesson 1-1

Unbuffered input is basically input that has not been ended by a strike of the enter key. This is useful for writing programs that respond immediately to a key stroke.

Again, unbuffered input depends on the implementation of the terminal you are using, so this is platform-dependent.

Unbuffered Input on Windows

Really, the easiest way to do this is using conio.h. There is a way to do it using the Windows API, but it requires knowledge from beyond this tutorial.

#include <conio.h>

char c;
c = _getch();

//or if _getch() doesn't work
c = getch();

Unbuffered Input on Unix-Derived Systems

There are multiple different ways to do this. You could set the associated variable with stty or you could use the getch() function from curses. However, the former is a little tricky, and curses is not compatible with stdin and stdout (i.e. cin and cout), so you would have to learn all of curses to use it. I would suggest looking at this.

Input Validation

Required Level: Lesson 1-3

When the user inputs data into your program, he/she may not know what data type you are looking for. If that is a concern, you can use the following method to keep your program running properly, should that happen.

#include <iostream>
#include <limits>	//you need this library!!

using namespace std;

int main () {
	unsigned myUInt;
	//note that this is the same as unsigned int myUInt;

	while (!(cin>>myUInt))
	{
    		cout <<"Please input a positive integer."<<endl;
    		cin.clear();
 		cin.ignore(numeric_limits<streamsize>::max(),'\n');
	}

	cout<<"You input a positive "<<myUInt<<'.'<<endl;

	return 0;
}

The above code would run like this:

Input Output
2 You input a positive 2.
abc Please input a positive integer.
-9 Please input a positive integer.
0.25 Please input a positive integer.

Note that you may need to double the cin.ignore() statement

Why it works

Despite the fact that the cin statement is inside the parentheses for the while loop, the program still looks for input at that point. If the user inputs the wrong data type, cin throws a couple of flags (fail and/or bad, to be exact). The computer interprets this to be a false value, so it runs the loop.

The Bubble Sort

Required Level: Lesson 2-2

When dealing with a set of numeric data, you may find it useful to have that data sorted in either ascending or descending order. In computer science, there are many different algorithms that you can implement to sort data stored in arrays. Despite the many different algorithms available to us, here we will go into depth about the simplest algorithm: the bubble sort. The idea behind the bubble sort is that the smallest (or the largest, depending on how you're sorting) elements of the array rise to the top of the array like bubbles.

Let's say we have the following array of ints which we wish to sort in ascending (smallest first) order:

int myNums[5] = {2, 9, 5, 11, 7};

Using a bubble sort, you need to check the value of each element against the following element, swapping them if they are out of order. You would do that inside a for loop, checking each element and performing the swap using a holding varible if they need to be swapped:

int myNums[5] = {7, 11, 5, 9, 2};
int tmp;

for (int i = 0; i < 4; ++i)
{
	/* We can't have i equal 4, 
	 * because the last element in myNums has index 4,
	 * and this algorithm requires that we access the 
	 * element i+1, which would cause the program to crash.
	 */
	 
	if (myNums[i] > myNums[i++])
	{
		/* remember: a ++ following a numeric variable only increments
		 * the variable if it is used alone. Used here, it just returns the incremented
		 * value to the [] operator.
		 */
		 
		 tmp = myNums[i];
		 myNums[i] = myNums[i++];
		 myNums[i++] = tmp;
	}
}

After this block finished executing, the array would look like this:

7 5 9 2 11

If you notice, this array still isn't sorted in ascending order — the 2 should be first, and 7 is bigger than 5. So, the trick here is to put the for loop inside a do-while loop that runs until the array is sorted. The condition that we need to check for the do-while loop is whether or not a swap was made — if a swap was made, then we can safely assume that we're not done sorting. When the array is sorted, no swaps will be made, and the do-while loop will exit.

int myNums[5] = {7, 11, 5, 9, 2};
int tmp;
bool swap;

do
{
	swap = false;
	/* we need to assume that the array is sorted at the beginning.
	 * If we find anything out of order, then we simply change swap to true
	 */
	 
	for (int i = 0; i < 4; ++i)
	{
		if (myNums[i] < myNums[i++])
		{
			tmp = myNums[i];
			myNums[i] = myNums[i++];
			myNums[i++] = tmp;
			swap = true;
		}
	}
} while (swap);

Now, when we run the code, the sort will be complete:

Pass Array
0 (before sort) 7 11 5 9 2
1 7 5 9 2 11
2 5 7 2 9 11
3 5 2 7 9 11
4 2 5 7 9 11

As you can see, after pass 4, the array has been sorted. The do-while loop will repeat one more time and check all of the array elements, but since the array has been sorted by this point, no elements will be switched, the swap flag will not be thrown, and the loop will exit, resulting with a sorted array.

The bubble sort works in both directions. The only change that you would need to make to sort the array in descending order (largest first) would be to change the comparison between the two array elements from a > to a <.

As was mentioned before, there are more algorithms that you can use to sort arrays. This is the simplest, but it is also the least efficient. If you would like to explore more sort algorithms, see here.

Vector: The Resizable Array

Required Level: Lesson 3-2

Arrays are quite useful: they allow you to store related information in sequence. The problem is, a standard array set up using the [] operator has a fixed size. Once created, you cannot add or remove array elements, you can only change them.

But what if you don't know how many array elements you need? Do you just create an incredibly large array and hope that the user doesn't need more than the amount you have defined?

There are immediately three problems with this approach:

  1. Every element in this array has a value (even if it is NULL), so you cannot tell how many values you actually have.
  2. Every element in this array is held in memory, including the ones that are not in use, and take up the amount of space according to the array's data type. So, if you have an array of 10 billion chars, and a single char requires a single byte, the entire array will be 9.3 GiB large. Note that this array is being held in the computer's RAM, so this array is likely to crash most common computers (with 4 or 8 GiB of RAM).
  3. You should never write a program and simply hope that its limitations suit your end users. You should make your program shape itself based on the needs of your users.

If only there were a resizable array that where you could add and remove elements...

C++ provides something referred to as the standard template library, or STL. It contains a number of template classes, or classes that can be cast to any data type. Of these class templates, there is one named vector. This is, effectively, a resizable array to/from which you can add/remove elements.

Creating a Vector

Because a vector is a class template, you need to create it differently than you would a normal array. Firstly, you need to include the vector header file. Then, you can create a variable of type vector with the data type you wish to store in the vector as the template argument:

#include <vector>

//...

std::vector<int> myInts;
// vector is a part of the std namespace!

This will create an empty vector of ints. You can, furthermore, use some of the vector class constructors:

				std::vector<int> myInts (10, 5); //creates a vector containing 10 ints, all with the value 5
				std::vector<int> myIntsTwo (myInts); //copies myInts

Accessing Vector Elements

There are five ways to access vector elements. The first you are already familiar with:

//remember that indices start with 0!
myInts[0]

You can access elements of a vector just like you would an array by using the [] operator along with the index of the element you want.

You can also access vector elements by using the at() function, if your compiler supports C++11 (most recent versions of g++, the compiler in Eclipse and Code::Blocks, do). This function works effectively in the same manner as the [] operator, except the at() function has better error handling.

myInts.at(0)

You can access the first and last elements of a vector with the front() and back() functions, respectively:

myInts.front()
myInts.back()

Iterators

The vector class provides a subclass called iterator which you can also use to access the vector's elements. This class is especially helpful if you are trying to run through the vector in a for loop.

In order to use an iterator, you need to declare an iterator variable. The tricky thing here is that because iterator is a subclass of vector, you still need to provide the proper template type to vector, so that it matches the vector you wish to apply the iterator to:

vector<int>::iterator it;

Once you have an iterator variable, get the iterator reference from the vector:

it = myInts.begin();

This will get an iterator that references the first element in the vector. If you want to get a specific element in the vector, you can add its index to the iterator, like so:

//get an iterator to the 6th element (index 5)
it = (myInts.begin() + 5);

You can also use the end() function to work from the end of the vector, as well. Note that end() returns an iterator to the space after the last element of the array (there is no element stored in this location).

//get an iterator to the 2nd to last element
it = (myInts.end() - 2)

Once you have the iterator reference, you can then access the element to which the iterator reference. In this case, the iterator works a lot like a pointer, you can just dereference it to get the element:

*it

If you want to use an iterator with a for loop, you need to keep in mind that the method for doing so is slightly different:

vector<int> myInts (10,5);
vector<int>::iterator it;

for (it = myInts.begin(); it != myInts.end(); ++it)
{
	//do some stuff with the elements of myInts
	*it = 100 - (*it);
}

This is the recommended method for using a for loop with an array.

How Big?

Since a vector is resizable at runtime, you cannot really tell how many elements that it contains at any given moment. However, the vector keeps track of this number itself:

myInts.size()

This will return the current number of elements in the vector. Note that this is not equal to the last index; the last index will always be equal to this number minus one.

Adding Elements

There are a few ways that you can add elements to a vector.

Appending elements

If the order doesn't matter to you that much, or if you are building the vector, then this choice is probably for you.

Appending elements is accomplished with the push_back() function:

myInts.push_back(7);

This will place a new int at the end of the array with a value of 7.

Inserting elements

If the order of the vector is important, and you want to place the new element in the middle or beginning of the array, then use this method.

Insertion of elements into a vector is accomplished through the insert() function:

myInts.insert(it, 7);

This will insert a new element with a value of 7 to the position referenced by the iterator it, pushing the element that formerly held the position at it and all of the elements following it one index further.

Removing Elements

There are also multiple methods by which you can remove elements. The ones listed here correspond to the methods shown above for creating elements.

Popping an element

You can use this method if you wish to delete the last element of the vector. The function to do this is pop_back().

myInts.pop_back();

Erasing an element

The erase() function allows you to erase specific elements from a vector, using an iterator.

myInts.erase(it);

Or, you can erase a range of elements, using iterators to define the beginning and end of the range (including the beginning but not the end):

vector<int>::iterator first_it;
vector<int>::iterator last_it;

first_it = myInts.begin()+2;
last_it = myInts.end()-2;

//erases everything except for the first two elements and the last two elements
myInts.erase(first_it, last_it);

Clearing all elements

You can also delete every element in the vector quite easily:

myInts.clear();

This resource was compiled with reference to the following resources: