You are on page 1of 92

Introduction

To Cut a Long Story Short...


C is a high-level programming language developed To learn C you must PRACTICE!!!! Reading is not
by Dennis Ritchie in 1972. He named it C because enough.
there was an existing programming language called You should also get a C compiler and write and test
B. your own programs - I learnt best from my (many)
Other programming languages, such as C++, Perl, careless mistakes. There are many free compilers
Java and JavaScript, all have one common ancestor: available on the net. For freeware, shareware and
C. demo programs, try performing a search at:
Programs are written in C. Computers don't http://download.cnet.com
understand C - the code needs to be compiled and So why should you learn C? Well, It opens the doors
turned into machine (binary) code before the to other languages like C++, Java and even
program can be executed. Binary code is the lowest JavaScript. Flash ActionScript follows on nicely from
level language and can be thought of as consisting JavaScript too.
of 1's and 0's.

The Basics
Syntax
The C code you write is called the SYNTAX. Note that C is CASE SENSITIVE! For example, words
Syntax is a mixture of: like cat, Cat, cAt and CAT are all considered different
• C keywords like int, for and return. from one another.
• Constants and variables. Also, the amount of "white space" you use in a C
• Operators like + (arithmetic "addition"), || program does not affect the way it's compiled. Use
(logical "or") and & (the "address of" extra spaces to make your programs more readable -
operator). indentation of code is very common. Obviously, you
can NOT put spaces or line breaks in the middle of
keywords like this: str uct !!

Compilers
At home, you may use a Borland C++ compiler.
Nowadays, Microsoft's Visual C++ 6.0 is popular. This is a powerful package and is suitable for people
who are interested in software engineering.
In general, C++ packages are fine for compiling C programs - the compiler executed depends on the
extension of your source file(s).
Whilst at university, you may also use UNIX-based compiler (gcc ie). The command for compiling is of the
form: cc world.c -o world , where cc ran the gcc compiler. The filename after cc is the file to be
compiled, which is "world.c" in this case, the filename after -o is the output file, which is "world". The
output filename is the word you type to run the program.

Commenting Your Code


You can add comments to your code by enclosing /* Comments spanning several */
your remarks within /* and */. However, nested /* lines can be commented*/
comments aren't allowed. /* out like this!*/

/* But this is a
A few properties of comments: simpler way
• They can be used to inform the person of doing it! */
viewing the code what the code does. This is
helpful when you revisit the code at a later // These are C++
date. // style comments
• The compiler ignores all the comments. // and should NOT
Hence, commenting does not affect the // be used with C!!
efficiency of the program.
/* /* NESTED COMMENTS
• You can use /* and */ to comment out
ARE ILLEGAL!! */ */
sections of code when it comes to finding
errors, instead of deletion.

Creating Executable Programs


There are several tasks that need to be performed before you can run a program: coding, compiling and
linking.
1. You have to write the source code in C. You declare which header files you want to include within
the source code. The source code must be saved with the extension .c.
2. Then you run the compiler, which translates the source code into machine, or binary code, which
the computer can understand. Computers do NOT understand C!
3. Sometimes the source code is still lacking some parts, so after going through the compiler, the
code is passed through a LINKER. This basically "links" the source code to other library or object
files so that the final binary code is produced. Don't worry, I'll explain compiling and linking in
greater detail in a later section.

Hello World
Your First Program
Let's write and compile your first program! #include <stdio.h>
Enter or copy the following code into your favorite
text editor (e.g. Notepad, Emacs, SimpleText etc.) int main() {
and save it with the .c extension. These MUST be printf("Hello World!\n");
saved in text only format - try and avoid word return 0;
}
processors like MS Word.
EditPad is also very good. Plus it's free - make sure
you download it!!

When saving in Notepad you should surround a filename with quote marks, for
example, "world.c". This ensures that the filename will be saved with the correct
extension, rather than world.c.txt, which is incorrect.

The #include Directive


If a line starts with a hash, denoted by #, it tells the Basically, when the preprocessor finds #include it
compiler that a command should be sent to the C looks for the file specified and replaces #include with
PREPROCESSOR. The C preprocessor is a program the contents of that file. In a way, this makes the
that is run when you compile. #include is one of code more readable and easier to maintain if you
the many C preprocessor commands you'll use. needed to use common library functions. More
preprocessor commands in the later sections.....

Header Files
Header files have the extension .h and the full There are two ways to include a header file:
filename follows from the #include directive. #include "stdio.h" and
They contain declarations to certain functions that #include <stdio.h>
you may or may not have used in your program. If you use the double quote marks, it means that the
For example, the stdio.h file is required if you have directory you're currently in, will be searched for first
used functions like printf and scanf in your for the header file, before any other directories are
program. More about these two functions in the searched.
Standard Input and Output section. If you use the square brackets, directories other than
the one you're currently in, will be searched for the
header file.

The main Function


A FUNCTION can be thought of as a group of If a function returns nothing, its return type is of type
instructions that are evaluated when the function is void - i.e. nothing is returned.
CALLED. The main function is special, as it returns an integer
All C programs must have a main function. You can by default, which is why you'll see me write return
only have one, but you can place it anywhere within 0; at the end of the program. Zero is usually returned
the code. to indicate error-free function termination.
The program always start with the main function Another way to terminate a program is to use the
and ends when the end of main is reached. exit function - there's an example later on.
Functions return a value too - this will be explained
later.

Constants and Variables


The Main Idea
Variables are like containers in your computer's Constants are like variables, but once a valued is
memory - you can store values in them and retrieve stored (i.e. the constant is INITIALIZED), its value
or modify them when necessary. cannot be changed.

Naming Variables
There are several rules that you must follow when naming variables:

Variable names.... Example


CANNOT start with a number 2i
CAN contain a number elsewhere h2o
CANNOT contain any arithmetic operators... r*s+t
... or any other punctuation marks... #@x%£!!a
... but may contain or begin with an underscore _height_
CANNOT be a C keyword struct
CANNOT contain a space im stupid
CAN be of mixed cases XSquared

There's a quiz on naming variables later...

Some Terminology
EXPRESSIONS consist of a mixture of constants, 17 /* a constant */
variables and operators (more about operators x /* a variable */
later). They return values. Here are some examples x + 17/* a variable plus a constant */
of expressions:

STATEMENTS are instructions and are terminated x = 1 + 8;


with a semicolon, ;. Statements consist of a mixture printf("We will learn printf soon!\n");
of expressions, operators, function calls and various int x, y, z; /* more on "int" later */
keywords. Here are some examples of statements:

STATEMENT BLOCKS, on the other hand, can if(x==10) {/* block 1 */


contain a group of statements. The C compiler printf("x equals 10\n");
compiles the statement block as if it was just one x = 11;
statement. To declare a statement block you printf("Now x equals 11\n");
x = x + 1;
enclose your statements between curly braces.
printf("Now x equals 12\n");
This example has a statement block in an if-else
} /* end of block 1 */
statement - don't worry if you can't understand the else { /* block 2 */
code just yet. Everything in each statement block is printf("x not equal to 10\n");
somewhat merged into a single statement. There printf("Good bye!\n");
are 2 statement blocks here: } /* end of block 2 */

Types of Constants
Numbers are considered as LITERAL constants - you But for now, we'll use the const keyword.
can't change the number 20, nor can you assign Suppose you had a circle with a fixed radius of 5
something else into 20. units. You can create a symbolic constant like this:
On the other hand, SYMBOLIC constants can be const int radius = 5;
assigned a value during initialization and are Since radius is declared using the const keyword,
represented by a word. statements like: radius = 12; would be illegal.
There are several ways to define constants in C.
Later, we will meet the #define directive and the
enum keyword - two more ways of defining
constants.

The 4 Data Types


Introduction
In C, there are four data types: char, int, float, Later on, we will use the sizeof operator to
and double. Each one has its own properties. For determine the size of various data types.
instance, they all have different sizes. The size of a In the meantime, let's look at the four data types in a
variable can be pictured as the number of bit more detail...
containers / memory slots that are required to store
it.

The charData Type


Variables of the char data type can store a single #include <stdio.h>
character from a set of 256 characters.
In fact, all of the characters on your keyboard have int main() {
int i,j;
a unique numerical code associated with it, so in
for(i=0 ; i<26 ; i++) {
reality, you're storing numerical codes into char
for(j=0 ; j<10 ; j++) {
variables. The set of codes are known as ASCII printf("%d=%c ", 10*i+j, 10*i+j);
codes, where ASCII stands for "American Standard }
Code for Information Interchange" and is usually printf("\n");
pronounced "ask-ee". }
The following program prints out the 256 ASCII return 0;
characters - don't worry if you can't understand the }
code just yet.

I assume the "blocks" occur when there is no character with that numerical value. Incidentally, the
"newline" character has the value of 10. I'm assuming that 8 is the backspace character (why else would
the equals sign be missing?) and goodness knows what has happened to the characters with value 11
through to 13! The maximum numerical value of a character is 255 - after that, the pattern repeats itself.
You can clearly see that A is represented by 65, where as a is represented by 97.
Try and guess the result of this example...
#include <stdio.h>

int main() {
printf("%c%c%c", 105, 111, 116);
printf("%c%c%c", 97, 45, 115);
printf("%c%c%c", 105, 120, 46);
printf("%c%c%c", 99, 111, 46);
printf("%c%c%c", 117, 107, 10);

return 0;
}

Declaring and Initializing Variables


To DECLARE a variable, means to reserve memory INITIALIZING a variable involves assigning (putting
space for it. in) a value for the first time. This is done using the
Declaring a variable involves inserting a variable ASSIGNMENT OPERATOR, denoted by the equals sign,
name after a data type. You can also declare many =.
variables of the same data type all on one line by Declaration and initializing can be done on separate
separating each one with a comma. This is
demonstrated in the example directly below. lines, or on one line.

Initializing char Variables


To store a character into a char variable, you must #include <stdio.h>
enclose it with SINGLE quote marks. Double quote int main() {/* this program prints Hello */
marks are reserved for STRINGS (an ARRAY of char a,b,c,d; /* declare char variables */
char e = 'o'; /* declaration and
characters). Strings and arrays are covered in the
initialization */
later sections. The characters you assign are
a = 'H'; /* initialize the rest... */
CHARACTER CONSTANTS. So for the example, 'H' is b = 'e'; /* b = e is incorrect */
a character constant. c = 'l'; /* so is c = "l" - you MUST
You can also assign a char variable an integer, that enclose the character with
is, the ASCII code. single quote marks*/
This example should help clarify the declaration and d = 108; /* the ASCII code for l */
initialization of char variables. Once again, ignore
the printf function for now. printf("%c%c%c%c%c\n", a, b, c, d, e);
return 0;
}

The intData Type


Variables of the int data type represent whole #include <stdio.h>
numbers. If you try to assign a fraction to an int int main() {
int a,b,c,d,e;
variable, the decimal part is ignored and the value
a = 10;
assigned is rounded down (or TRUNCATED) from the
b = 4.3;
actual value. c = 4.8;
Also, assigning a character constant to an int d = 'A';
variable assigns the ASCII value. e = 4.3 + 4.8;

printf("a = %d\n", a);


printf("b = %d\n", b);
printf("c = %d\n", c);
printf("d = %d\n", d);
printf("e = %d\n", e);
printf("b+c = %d\n", b+c);

return 0;
}

The output of the example is: 4.8 gets rounded down to 4 when assigned to c - not
a = 10 up to 5 as one may have expected.
b = 4 Now, d gets assigned 65 - the ASCII code for the
c = 4 character 'A'.
d = 65
e = 9 9 gets assigned to e because 4.3+4.8 equals 9.1,
b+c = 8 which gets rounded down.
The first 5 printf statements prints out the integer
Obviously, 10 gets assigned to a without any
values of a through to e.
problems.
The last printf statement prints out the sum of b
4.3 gets rounded down to 4 when assigned to b.
and c, that is, 4 and 4 and not 4.3 and 4.8.

The floatData Type


To store variables correct to six decimal places, you #include <stdio.h>
can use the float data type. int main() {
Floats are relatively easy to use but problems tend
float a,b,c,d,e,f;
to occur when performing division.
In general:
a = 1/3;
An int divided by an int returns an int. b = 1/3.0;
An int divided by a float returns a float. c = 1.0/3;
A float divided by an int returns a float. d = 1.0/3.0;
float divided by a float returns a float. e = (float)1/3;
If you want to store the result of a division as a f = (float)(1/3);
decimal number, make sure you store it in a float
declared variable. printf("1 divided by 3 is %f\n", a);
If you want the decimal result of the division printf("1 divided by 3.0 is %f\n", b);
between two integers, you can use a method called printf("1.0 divided by 3 is %f\n", c);
COERSION (or CASTING). This involves placing printf("1.0 divided by 3.0 is %f\n", d);
printf("\nThe float-casting of \n");
(float) before an expression you wish to cast.
printf(" 1, divided by 3 is %f\n", e);
printf("\nf equals %f\n", f);

return 0;
}

The output of the example is: With e, we've used casting. (float) occurs just
1 divided by 3 is 0.000000 before the 1, so 1 is effectively 1.0, therefore the
1 divided by 3.0 is 0.333333 result of 1.0 divided by 3 gets assigned to e, that is,
1.0 divided by 3 is 0.333333 0.333333.
1.0 divided by 3.0 is 0.333333
We've also used casting for f, but not in the correct
The float-casting of manner. Because of the brackets, 1 divided by 3 gets
1, divided by 3 is 0.333333 evaluated first, then the result gets casted to a
float. Since 1 divided by 3 returns 0, 0.000000 gets
f equals 0.000000
assigned to f.
Now, the printf functions prints out most of the text
Firstly, five variables of the float data type are between the double quote marks with a few
declared and initialized with the return values of exceptions.
various calculations:
\n is known as the NEWLINE character - it acts like a
a stores the result of an int divided by an int. The line break, and is commonly used to make the output
integer value of 0.333333... is zero, so 0.000000 is look neater.
assigned to a.
%f is a FORMAT SPECIFIER and is replaced with the
b stores the result of an int divided by a float, so float-value of specified expressions.
0.333333 as expected. Format specifiers will be discussed at a later date - for
now you need to understand why a and f gets
c stores the result of a float divided by an int, so assigned 0.000000 and b to e gets assigned
0.333333 as expected. 0.333333.
Finally, notice that we are unable to store certain
d stores the result of a float divided by a float, so fractions like a third, exactly in C.
0.333333 as expected.

The doubleData Type


You can store decimals correct to ten decimal places Once again, be careful when it comes to calculations
using the double data type. However, doubles take that involve divisions - use casting when necessary.
up twice as much memory than floats, so use
doubles when it's really necessary.

Scientific Notation
It is possible to express numbers in scientific Basically, xey translates to "x times 10 to the power
notation, which is handy if the numbers get very of y".
large or small. For example, 1.2e3 is 1.2*1000 = 1200
In C, scientific notation is of the form xey - you 1.23e4 is 1.23*10000 = 12300
should replace x and y with numbers (y must be an 4.5e-2 is 4.5*0.01 = 0.045
integer).

Type Modifiers
The signed and unsigned Keywords
When you declare a variable of the type, int, by default, its value is SIGNED. In other words, the variable
could be positive or negative.
On my machine, the minimum value of a signed int is -32768 and the maximum value is 32767 (that is,
215-1).
An unsigned int on the other hand, can only store positive values, and has the range from 0 to 65535
(that is, 216-1).

The short and long Keywords


The cases above all apply when the integer is of the short type, which takes up less memory than the
long type. The range of values that a short int could store is somewhat limited, so if you're planning to
store huge numbers you'd want to use the long type.
Most of the time, an integer with be of the signed short type by default, which is why you've never seen
me declare a signed short int.
Here's a summary:
Type Minimum Value Maximum Value
signed short int -32768 32767
unsigned short int 0 65535
signed long int -2147483648 2147483647
unsigned long int 0 4294967295
Note that:
215 = 32768
216 = 65536
231 = 2147483648
232 = 4294967296

The sizeof Operator


This function enables you to find out how many BYTES a variable occupies. A byte is defined as EIGHT
BINARY DIGITS (or "8-bits"). Binary numbers are covered later. For now, think of a byte as a container in
the computer's memory.
The sizeof operator takes one OPERAND. An operand is an expression that is required for an operator to
work.
You can use a data type as an operand, to find out how much memory is required to store variables of
that data type, as demonstrated by this example:
#include <stdio.h>

int main() {
printf("Size of int is %d bytes\n",sizeof(int));
printf("Size of short int is %d bytes\n",sizeof(short int));
printf("Size of long int is %d bytes\n\n", sizeof(long int));

printf("Size of signed int is %d bytes\n",sizeof(signed int));


printf("Size of signed short int is %d bytes\n",sizeof(signed short int));
printf("Size of signed long int is %d bytes\n\n", sizeof(signed long int));

printf("Size of unsigned int is %d bytes\n",sizeof(signed int));


printf("Size of unsigned short int is %d bytes\n",sizeof(unsigned short int));
printf("Size of unsigned long int is %d bytes\n\n",sizeof(unsigned long int));

printf("Size of char is %d byte\n",sizeof(char));


printf("Size of float is %d bytes\n",sizeof(float));
printf("Size of double is %d bytes\n", sizeof(double));

return 0;
}

Notice the use of extra white space to add readability to the code.
The output shows that the amount of memory required is not affected by the signed or unsigned type
modifiers:
Size of int is 2 bytes
Size of short int is 2 bytes
Size of long int is 4 bytes
Size of signed int is 2 bytes
Size of signed short int is 2 bytes
Size of signed long int is 4 bytes
Size of unsigned int is 2 bytes
Size of unsigned short int is 2 bytes
Size of unsigned long int is 4 bytes
Size of char is 1 byte
Size of float is 4 bytes
Size of double is 8 bytes

You can also pass the function a declared variable, to find out how much memory that variable occupies.

Arithmetic Operators
Five and Not Four...
Arithmetic operators are commonly used in a variety The multiplication, division and modulus operators
of programming languages. In C, there are five of have higher PRECEDENCE over the addition and
them, and they all take two OPERANDS. Recall that subtraction operators. This means that if an
an operand is an expression that is required for an expression contains a mixture of arithmetic operators,
operator to work. For example, for 8 + 4, 8 and 4 multiplication, division and modulus will be carried out
are considered as the operands. first in a LEFT TO RIGHT order, then any addition and
Operator Name Symbol subtraction.
Brackets (also known as PARENTHESES) can be used
Multiplication * to change precedence, as everything enclosed within
Division / brackets is always evaluated first.
For example, 2*4+3 returns 11 because 2*4 is 8, and
Modulus %
8+3 is 11.
Addition + On the other hand, 2*(4+3) returns 14 because 4+3 is
Subtraction - 7, and 2*7 is 14.
Let me explain why I listed the five operators in this
particular order...

What's With the % ?!


Multiplication, addition and subtraction are the If it helps, play around with this:
simplest to use. Division is also easy, but watch out
%
for the truncation of an int divided by an int! Use
casting if necessary. Now, the one that confuses Note that anything modulus with zero returns infinity
novices is the modulus operator, sometimes known because anything divided by zero is infinity. In
as the remainder operator. JavaScript, NaN means "Not a Number" - either it's
To keep things simple, a%b returns the REMAINDER infinity, or you entered something daft!
that occurs after performing a/b. For this operator, Anything modulus with itself is always zero because
a and b MUST be integers! that number goes into itself exactly.
For example, 6%3 returns 0 because 3 goes into 6 15%37 returns 15
EXACTLY. Similarly, 4%4, 8%2 and 16%8 all return 0. 32%4 returns 0
So why does 3%4 return 3? Picture it this way: you 0%18 returns 0
have 3 holes to fill, but you can only fill 4 holes at a 3%18 returns 3
time. You can't fill a group of 4 holes, therefore the 44%35 returns 9
3 holes you had are still empty. Similar story for
7%4 because you can fill in one group of 4 but still
have 3 holes remaining.

Arithmetic Assignment Operators


Sometimes you'd find yourself writing something Long Hand Short Hand
like: x = x + 2;
x = x * y; x *= y;
There is a better (and efficient) way of writing
expressions like these by combining the operator x = x / y; x /= y;
with an equals sign, as shown in the table opposite. x = x % y; x %= y;
Be careful with these though: x = x + y; x += y;
x *= y+z is the same as:
x = x - y; x -= y;
x = x*(y+z) NOT:
x = (x*y) + z.

Increment and Decrement Operators


Increasing an integer variable by 1 is a common If x was 5, y = x++; would assign x to y, THEN
process. I've seen people write statements like increase x by 1. The end result is that y equals 5 and
x+=1; or even worse, x=x+1; x equals 6.
There is an easier way: x++; If x was 5, y = ++x; would increase x by 1, THEN
(POST-INCREMENT) assign x to y. The end result is that y equals 6 and x
Alternatively, you can use ++x; equals 6.
(PRE-INCREMENT) As their names suggest, post-incrementing is done
So what's the difference? They both increase x by 1 AFTER the assignment, pre-incrementing is done
(note that x MUST be an integer), and I tend to use BEFORE the assignment.
post-increment. They differ when it comes to Similar rules apply for decrementing. If you wanted to
statements like these: decrease x by 1 you're free to write x--; (POST-
y = x++; DECREMENT) or --x; (PRE-DECREMENT), as opposed
y = ++x;
to: x-=1; or x=x-1;

Standard Input and Output


Introduction
Displaying output is a common process, and there To use the input and output functions, you'll need to
are a variety of functions that do exactly that. include the Standard Input and Output header file
So far, I've used the printf function in every (stdio.h) in your program, which explains why I've
example as a way of displaying program output. written #include <stdio.h> in previous examples.
Similarly, getting input from the user (or from
external files) is another common process.

The Standard Input File Stream, stdin


To input a value, the easiest way is to use a library This is basically a series of bytes that is transferred
function called scanf. There are other functions like from the input source to the program (recall from the
getc and getchar (both used for inputting data types section that each character is one byte
characters), but I find that scanf is by far the large, so a stream can be thought of as a series of
easiest to use. gets is another one that is covered characters). In C, stdin is the standard input file
in the future. scanf is actually a simplified version stream and links to the keyboard.
of a function called fscanf which requires you to
specify an INPUTFILE STREAM.

The Standard Output File Stream, stdout


putc, putchar, puts and printf are all used to stdout is the standard output file stream and refers
output values. The latter is the simplest to use. to the monitor.
Some of these require an OUTPUT FILE STREAM stderr is also an output file stream but makes sure
which is a series of bytes that is transferred from that the output, usually an error message, is seen.
the output source to the program.

getc() and getchar()


These functions allow you to input a character and getchar is EXACTLY the same as getc with the input
assign it to a variable. file stream set to stdin.
getc requires you to specify an input file stream like Both functions return integer values, which you could
stdin, or as we'll see later, a file pointer (you don't assign to variables for later use.
need to know what a pointer is just yet!).

putc() and putchar()


To output a character, you can use one of these two #include <stdio.h>
functions.
putc requires you to specify two things - the int main() {
char a,b;
variable whose character value should be printed
printf("Enter a 2 letter word ");
out, and the file output stream.
printf("and press return: ");
putchar is exactly the same as putc, but with the a = getc(stdin);
output file stream set to stdout. You only need to b = getchar();
specify the character value to print out. printf("The first letter was: ");
The following example demonstrates the previous putc(a, stdout);
four functions... printf("\nFollowed by: ");
putchar(b);
putchar(10);
printf("Goodbye!\n");
}

Suppose I entered YO and pressed return. The output generated would be:
Enter a 2 letter word and press return: YO The first
letter was: Y
Followed by: O
Goodbye!

After declaring two character variables, I used two printf statements to display the first line of text
(printf is discussed in the next section!), simply because I was running out of space!
AS SOON AS the user enters a character, it gets assigned to the variable a because the getc function was
INVOKED - a term meaning the calling of a function. Noticed how the standard input stream, stdin had to
be PASSED into getc. Values passed into a function are called ARGUMENTS - a function sometimes needs
extra information for it to work.
As soon as the user enters a second character, it gets assigned to b - notice how getchar requires no
arguments.
The program continues when you press return - any additional characters after the second aren't stored.
The putc function takes a char or int variable as its first argument, followed by the standard output
stream, stdout and prints out the specified character.
putchar only requires one argument, and also prints out the specified character.
As a reminder, \n is the NEWLINE character and is the equivalent to a carriage return. Is has an ASCII
code of 10, so putchar(10) inserts a newline before printing "Goodbye!".

printf and scanf


printf
At last! Here's that function I keep using in my Here's printf in action once again:
examples. It gives you the power to print output printf("Hello World!\n");
onto the screen, and is relatively simple to use. Notice how the string, "Hello World!\n" is enclosed
The number of arguments required varies, but the in double quote marks. I've said it at least once, but
first argument you pass should be a STRING - think I'll say it again: the \n is the NEWLINE character and
of a string as a sequence of characters for now. acts like a line break!
Recall that a string must be surrounded by double
quote marks.

Format Specifiers
In the past, I've provided examples where a value There are several format specifiers - the one you use
of some variable was printed out. should depend on the type of the variable you wish to
To do so, requires you to embed a format specifier print out. Here are the common ones:
in your text string, and to pass extra arguments to
the printf function. An example: Format Specifier Type
printf("x equals %d \n", x);
This statement prints the value of x out. I had to %d (or %i) int
pass the value of x into the printf function. When %c char
you pass arguments to functions, you separate each %f float
one with a comma - here,
"x equals %d \n" is an argument, so is x. %lf double
%s string
To display a number in scientific notation, use
%e. To display a percent sign, use %%.

Don't try to display a decimal number using the integer format specifier, %d, as this
displays unexpected values! Similarly, don't use %f for displaying integers. Mixing
%d with char variables, or %c with int variables is all right, as shown in this
example:
#include <stdio.h>
a equals 72
a equals H
int main() { b equals 65
int a = 72; b equals A
char b = 'A';
printf("a equals %d \n", a); The reason why this works is because a character
printf("a equals %c \n", a); constant is just an integer from 0 to 255.
printf("b equals %d \n", b);
printf("b equals %c \n", b);
}

Two or More Format Specifiers


You could use as many format specifiers as you If a, b and c were integers, this statement will print
want with printf - just as long as you pass the the values in the correct order. Rewriting the
correct number of arguments. statement as...
The ordering of the arguments matters. The first printf("a=%d, b=%d, c=%d\n", c,a,b);
one should correspond to the first format specifier in ... would still cause the program to compile OK, but
the string and so on. Take this example: the values of a,b and c would be displayed in the
printf("a=%d, b=%d, c=%d\n", a,b,c); wrong order!

scanf
I've still yet to use this function in my examples. It's The first one is a string that can consist of format
a lot more flexible to use than the getchar and specifiers. The rest of the arguments should be
getc functions, simply because you can input variable names preceded with the address-of
numbers and strings, as well as characters. operator. Try to picture the previous scanf statement
Have a look at this: by this: "Read in an integer from the input string,
printf("Enter a number "); then go to the address of the variable called a and put
printf(" and press Enter: "); the value there". Remember that a variable is like a
scanf("%d", &a); container in your computer's memory - each one has
Before I move on, I'll mention briefly that the & is a different address.
known as the ADDRESS-OF operator - you'll be Like with printf, the number of arguments after the
using it a lot more when you meet POINTERS at a string argument should match the number of format
later date! specifiers contained in that string.
Back to the example. scanf takes at least two Similarly, the type of the format specifier should
arguments. match the type of the corresponding variable. The
ordering of the variables also matters.

Inputting Multiple Values


If you have multiple format specifiers within the Now consider:
string argument of scanf, you can input multiple scanf("%d, %d, %d", &x,&y,&z);
values. All you need to do is to separate each If I entered 1 2 3 and pressed enter 1 would get
format specifier with a DELIMITER - a string that assigned to x but 2 and 3 won't get assigned to y or
separates variables. For convenience, the delimiter z, simply because I didn't separate the numbers with
should be one character that's a punctuation mark, commas.
like a comma or a space. As a default, scanf stops Entering 1,2,3 works, but why does 1, 2, 3 also
reading in a value when space, tab or Enter is work? scanf ignores spaces, tabs and carriage
pressed. returns immediately after the delimiters.
Consider scanf("%d %d", &x, &y); Just don't put a space, tab or carriage return before
(Assume that x and y have been declared the delimiter! 1 ,2, 3 won't work.
beforehand!). If you want the user to press return after each
If I entered: 1 2 and pressed Enter, 1 would get number, try something along the lines as:
assigned to x, and 2 would get assigned to y. scanf("%d\n%d\n%d", &x,&y,&z);
But if I entered 1, 2 and pressed Enter, x would Note that you shouldn't put a delimiter after the last
equal 1, but y won't get assigned 2 because scanf format specifier!
was not expecting a comma in the input string.

This is probably past the novice stage, but if you wanted to enter a value for a
double variable using scanf, you need to use %lf as the format specifier - it's
the specifier for a long float variable, which we'll encounter later.

Exercises
I think we've covered enough material for you to apply your knowledge in a few mini exercises!
1a. Write a program that declares four variables in total (one of each data type).
1b. Initialize each variable, then use 4 printfs to display each value.
1c. Use scanf to fetch input for each variable. Once stored, print them out (tip: use %lf for doubles).
2. Recall an earlier example:
#include <stdio.h>

int main() {
printf("%c%c%c", 105, 111, 116);
printf("%c%c%c", 97, 45, 115);
printf("%c%c%c", 105, 120, 46);
printf("%c%c%c", 99, 111, 46);
printf("%c%c%c", 117, 107, 10);

return 0;
}
Write a similar program that displays your name.
3a. Write a program that requests input for 2 integers a and b.
3b. Display the sum of a and b.
3c. Display the product of a and b.
3d. Display the remainder of a divided by b.

More on Format Specifiers


Minimum Field Width
Suppose you want the program to display output For example, if you want to display an integer using a
that occupies a minimum number of spaces on the minimum of 8 spaces, you'd write %8d in your printf
screen. You can achieve this by adding an integer statement.
value after the percent sign of a format specifier. This example gives a demonstration:
#include <stdio.h>

int main() {
int x = 123;

printf("Printing 123 using %%0d displays %0d\n", x);


printf("Printing 123 using %%1d displays %1d\n", x);
printf("Printing 123 using %%2d displays %2d\n", x);
printf("Printing 123 using %%3d displays %3d\n", x);
printf("Printing 123 using %%4d displays %4d\n", x);
printf("Printing 123 using %%5d displays %5d\n", x);
printf("Printing 123 using %%6d displays %6d\n", x);
printf("Printing 123 using %%7d displays %7d\n", x);
printf("Printing 123 using %%8d displays %8d\n", x);
printf("Printing 123 using %%9d displays %9d\n", x);

return 0;
}

Output:
Printing 123 using %0d displays 123
Printing 123 using %1d displays 123
Printing 123 using %2d displays 123
Printing 123 using %3d displays 123
Printing 123 using %4d displays 123
Printing 123 using %5d displays 123
Printing 123 using %6d displays 123
Printing 123 using %7d displays 123
Printing 123 using %8d displays 123
Printing 123 using %9d displays 123

Notice that in the first 4 cases, 123 is displayed in the same way as when you normally use %d. Why?
Simple - the number of spaces on the screen that 123 can be displayed is greater than or equal to 3.
But also, if you write %09d, the program will display zeros before the number itself. In the above example,
it will display:
Printing 123 using %09d displays 000000123
An advantage of using this, is that you can count the minimum field of the number!

Making It Look Neater


The output from the example above doesn't look To align your output on the left, you insert a minus
very neat does it?! That's because the numbers are sign before the number in the format specifier. But if
aligned to the right of the minimum field. In other you do this to the previous example, all the output
words, 1,2 and 3 are the digits in the furthest 3 lines will be the same.
spaces of the minimum field. A better example:
#include <stdio.h>

int main() {
int x = 12;
int y = 123;
int z = 12345;

printf("Printing 12 using %%9d \t\t displays %9d\n", x);


printf("Printing 12 using %%09d \t\t displays %09d\n", x);
printf("Printing 12 using %%-9d \t\t displays %-9d\n", x);
printf("Printing 12 using %%-09d \t displays %-09d\n", x);

printf("Printing 123 using %%9d \t\t displays %9d\n", y);


printf("Printing 123 using %%09d \t displays %09d\n", y);
printf("Printing 123 using %%-9d \t displays %-9d\n", y);
printf("Printing 123 using %%-09d \t displays %-09d\n", y);

printf("Printing 12345 using %%9d \t displays %9d\n", z);


printf("Printing 12345 using %%09d \t displays %09d\n", z);
printf("Printing 12345 using %%-9d \t displays %-9d\n", z);
printf("Printing 12345 using %%-09d \t displays %-09d\n", z);

return 0;
}

Output:
Printing 12 using %9d displays 12
Printing 12 using %09d displays 000000012
Printing 12 using %-9d displays 12
Printing 12 using %-09d displays 12
Printing 123 using %9d displays 123
Printing 123 using %09d displays 000000123
Printing 123 using %-9d displays 123
Printing 123 using %-09d displays 123
Printing 12345 using %9d displays 12345
Printing 12345 using %09d displays 000012345
Printing 12345 using %-9d displays 12345
Printing 12345 using %-09d displays 12345

\t acts like a standard tab. Notice how it begins with a backslash, \ - just like the newline character.
More Precision
You can gain more control with the displaying of If you're using %f, the format specifier for floating
integers by placing a dot, followed by an integer, point numbers, you can control the number of
after the minimum field specifier. The dot and this decimal places that is displayed (which is 6 by
integer is known as a PRECISION SPECIFIER. default). How? By using the precision specifier. This
The integer you add specifies the maximum field time, the number after the dot is the number of
width when displaying an integer or string. decimal places. The number before the dot is still the
minimum field width.
This example should help clarify things:
#include <stdio.h>

int main() {
float x = 3.141592;

printf("Printing 3.141592 using %%f \t displays %f\n", x);


printf("Printing 3.141592 using %%1.1f \t displays %1.1f\n", x);
printf("Printing 3.141592 using %%1.2f \t displays %1.2f\n", x);
printf("Printing 3.141592 using %%3.3f \t displays %3.3f\n", x);
printf("Printing 3.141592 using %%4.4f \t displays %4.4f\n", x);
printf("Printing 3.141592 using %%4.5f \t displays %4.5f\n", x);
printf("Printing 3.141592 using %%09.3f displays %09.3f\n", x);
printf("Printing 3.141592 using %%-09.3f displays %-09.3f\n", x);
printf("Printing 3.141592 using %%9.3f displays %9.3f\n", x);
printf("Printing 3.141592 using %%-9.3f displays %-9.3f\n", x);

return 0;
}

Output:
Printing 3.141592 using %f displays 3.141592
Printing 3.141592 using %1.1f displays 3.1
Printing 3.141592 using %1.2f displays 3.14
Printing 3.141592 using %3.3f displays 3.142
Printing 3.141592 using %4.4f displays 3.1416
Printing 3.141592 using %4.5f displays 3.14159
Printing 3.141592 using %09.3f displays 00003.142
Printing 3.141592 using %-09.3f displays 3.142
Printing 3.141592 using %9.3f displays 3.142
Printing 3.141592 using %-9.3f displays 3.142

You may have noticed that if you use a negative value for the minimum width specifier, the output will
not be affected by a zero after the minus sign.
Also, in the case for decimal numbers, the decimal point occupies a character space on the screen.

Comparison and Logical Operators


More Than One Outcome
Programs would be very boring if they only For example: "If it is raining I will stay indoors, else I
produced one outcome - we should be grateful for will walk the dog!"
the conditional statements, which you'll encounter But before I move on and talk about conditional
soon. These let us branch off at one point in the branching, let me introduce two new families of
program, resulting in different outcomes. Notice operators.
how much branching goes on in our lives.

Comparison Operators
For us to make decisions, we must act according to Here are the six comparison operators:
a condition. In the previous example, "it is raining" Operator Name Symbol
is a condition, where as "I will stay indoors" and "I
will walk the dog" are results based on the Less than <
condition. Programming uses a similar concept. We Less than or equal to <=
can say:
Greater than >
"If x plus 1 is equal to 5, then x equals 4, else it is
not equal to 4". Greater than or equal to >=
COMPARISON operators are used to compare Equal to ==
numerical values. In the example, "is equal to" is
the comparion operator. Not equal to !=
RELATIONAL operators is an alternative name for The top four have higher precedence than the "equal
comparison operators. to" and "not equal to" operators.
All arithmetic operators have higher precedence than
the comparison operators.

Don't confuse the "equal to" operator with the assignment operator! Visual Basic
and Flash 4 ActionScript annoyingly uses "=" as its "equal to" operator and "<>" as
the "not equal to" operator.
Comparison operators can only be used to compare numerical values. To compare
strings, use the strcmp function, discussed in the string section.

Logical Operators
Conditions are expressions that can return one of two values: 1 (true) or NOT reverses the truth value of
0 (false). Any non zero value is considered true, where as zero is its operand:
thought of as false. Return
Experiment with the comparison operators: Expression
Value
!1 0
If you wanted to test for more conditions, you can use the logical !0 1
operators. AND returns 1 if both operands
The first one is the NOT operator (some call it negation). It is denoted by return non zero values (like 1):
the ! symbol and takes one expression as its operand.
Return
Then we have the AND operator, represented by &&, and the OR Expression
Value
operator, denoted by || (double broken vertical bar symbols - shift
backslash on my home keyboard). Both of these operators requires two 1&&1 1
expressions as their operands. 1&&0 0
Now, their return values depend on the TRUTH VALUES of their operands
- do they return 1 or 0? Logical operators are commonly summarized 0&&1 0
using TRUTH TABLES, which lists all the different truth combinations of 0&&0 0
the operands and the final logical operator truth value.
OR only returns 0 if both
operands return zero:
Return
Expression
Value
1||1 1
1||0 1
0||1 1
0||0 0
NOT has higher precedence than
AND, which has higher
precedence than OR.

Operator Precedence
A summary of the operators so far: But what about x<3 && y<7 || y==5 ?
Highest Precedence Suppose x is 4 and y is 5. Since the comparison
( ) ! operators have higher precedence than the logical
ones, we can rewrite the line as:
* / % 0 && 1 || 1 because 4<3, 5<7 and 5==5 return 0, 1
+ - and 1 respectively.
< <= > >= Now, && gets evaluated first, then ||.
0 && 1 returns 0. Then we have 0 || 1, which
== !=
returns 1.
&& This tends to get confusing, which is why you should
|| use brackets when you have many operators on a
single line! The following is easier to understand than
Lowest Precedence the original:
This precedence stuff is a little tricky to explain, so (x<3 && y<7) || y==5
let's have a look at an example. Suppose we had: - Expressions in brackets are evaluated first.
x+5 == 6
Since + has higher precedence than ==, x+5 is
evaluated first, then the result is compared with 6.

Conditional Branching 1
if This Happens, Do This... else Do This...
CONDITIONAL BRANCHING is a term that is used to If the condition returns zero, sometimes you want the
describe the way program flow diverges, depending program do something else. In that case, after the if
on certain condition(s). statement, you use an else statement.
if statements play an important role in conditional This time, there is no need for a condition.
branching and their usage is quite easy to get the Once again, you can use a single statement or a
hang of. After typing if, you put the condition in a statement block for multiple statements.
pair of brackets, followed by a statement you want
the program to read if the condition expression
returns a non zero value. If you want multiple
statements, use a statement block.
#include <stdio.h>

int main() {
int a;

printf("Input an integer and push return:\n");


scanf("%d", &a);

if (a%2==0 && a%5==0) { /* Start of if block */


printf("%d is a multiple of 2 and 5\n", a);
} /* End of if branch */
else { /* This is the else branch */
printf("%d is not a multiple of both 2 and 5\n", a);
} /* End of if block */

return 0;
}

The program output for this example will depend on Now, a%2==0 returns 1 (true) if a%2 is equal to 0.
the value you enter. Similar story for a%5==0.
This example covers recent material, like using the a%2==0 && a%5==0 returns 1 if BOTH operands of the
printf and scanf functions, relation and logical && operator return 1. In that case, the if branch is
operators, and finally the if and else statements. executed, and the else branch is ignored.
The printf functions are simple enough, but scanf If a%2==0 && a%5==0 returns 0, the else branch is
reads in an integer (due to the %d format specifier), executed and the if branch is ignored.
and assigns it to the int declared variable, a. Notice how I've added curly brackets, despite having
a%2==0 && a%5==0 is the condition part of the if only one statement after the if and else statements.
statement - it is surrounded by a pair of brackets. If I have a habit of doing that, as it makes the code
I wanted to, I could've made this a little more more readable in some ways.
readable by adding more brackets, like this: The following would've worked fine:
if ((a%2==0) && (a%5==0)) if (a%2==0 && a%5==0)
Onto the condition itself... recall that a%2 returns printf("...");
the remainder of the division of a by 2. If zero is else
returned, then a must be a multiple of 2. Similarly, printf("...");
a%5 returns zero if a is a multiple of 5.

Saying "else if"...


To test additional conditions, you can use an else After the if branch (but always before the else
if statement, which works in the same way as a branch if it exists), you can have as many else if
normal if statement. branches as you want, each with their own conditions
One thing to note, is that you must have one and and statement blocks.
only one if branch in an entire if block. This example demonstrates how useful else if
The else branch is entirely optional. statements can be:
#include <stdio.h>

int main() {
int a;

printf("Input an integer and push return:\n");


scanf("%d", &a);

if(a%2==0 && a<0) {


printf("%d is even and less than zero.\n", a);
}
else if (a%2!=0 && a<0) {
printf("%d is odd and less than zero.\n", a);
}
else if (a%2==0 && a>0) {
printf("%d is even and greater than zero.\n", a);
}
else if (a%2!=0 && a>0) {
printf("%d is odd and greater than zero.\n", a);
}
else {
printf("You entered zero.\n");
}

return 0;
}

Once again, the program output will depend on the One final note: I tend not to end an if block on an
value you enter. else if.
The main focus is on the if block, with the solitary If I wanted to say, "else do nothing", rather than
if and else statements, as well as the else ifs. missing the else statement totally, I insert a blank
Now, the program evaluates the if condition. If it statement block:
returns a non zero value, the if branch is executed. if(x==0) {
Once all the statements in that branch have been printf("x is zero\n");
executed, THE PROGRAM IGNORES THE REST OF }
else if(x==1){
THE IF BLOCK. In other words, the remaining
printf("x is 1\n");
conditions are not evaluated.
}
If, on the other hand, (a%2==0 && a<0) returns else { /* Do nothing */
zero, the first else if condition is evaluated and so }
on.
The main thing to remember is that once the
program chooses a branch in the if block, the
remaining branches are totally ignored.

DON'T put a semi colon after if, else if and else statements like this:
if (x==1);
Also, beware Visual Basic programmers: else if is two words, ElseIf is one!!

Nesting if Blocks
When you place statement blocks within other This is when you should indent and use curly
blocks, you are NESTING blocks. You can place if brackets, as these will make your code easier to read
blocks within branches of another if block. as this example demonstrates:

#include <stdio.h>

int main() {
int a,b,c;

printf("Input two integers separated with a space and push return:\n");


scanf("%d %d", &a, &b);

c = a + b;

if(a==b) {
printf("%d is equal to %d.\n", a, b);
printf("And their sum is even.\n");
}
else if(a<b) {
printf("%d is less than %d.\n", a, b);
if(c%2==0) {
printf("And their sum is even.\n");
}
else {
printf("And their sum is odd.\n");
}
}
else {
printf("%d is greater than %d.\n", a, b);
if(c%2==0) {
printf("And their sum is even.\n");
}
else {
printf("And their sum is odd.\n");
}
}

return 0;
}

Make use of the extra whitespace. Indentation will make your code easier to
read, especially when you have lots of if and else statements kicking around.
Get into the habit of indenting! Also, lining up your curly brackets will help you
when it comes to finding and fixing errors (a process known as DEBUGGING).

Conditional Branching 2
The Conditional Operator
It's possible to say: "If this condition is true, do a should be a condition you want to test for. b is an
this.... , otherwise, do this .... " all in one line. expression that is evaluated if a returns a non zero
This can be achieves using the CONDITIONAL value (in other words, if a is true), else expression c
OPERATOR, which is represented by is represented is evaluated. For example:
by ? : x<1 ? printf("x<1") : printf("x>=1");
It may look a bit odd at first, but it takes 3 Note the terms I used: the 3 separate operands are
expressions as operands, like this: a ? b : c; expressions - the whole line is a statement.

It's a common mistake to put a semi colon in the middle expression like this:
x<1 ? printf("x<1"); : printf("x>=1");
- this will generate an error when you compile!

The switch Statement


There are times when you'll find yourself writing a switch (expression) {
huge if block that consists of many else if case expression1:
statements. /* one or more statements */
case expression2:
The switch statement can help simplify things a
/* one or more statements */
little. It allows you to test the value returned by a /* ...more cases if necessary */
single expression and then execute the relevant bit default:
of code. /* do this if all other cases fail */
You can have as many cases as you want, including }
a default case which is evaluated if all the cases The program will branch off depending on what is
fail. returned by the expression in the parentheses.
Let's look at the general form... However, all is not what it seems. Examine the output
of this example:
#include <stdio.h> (Suppose I entered 2...)
Pick a number from 1 to 4:
int main() { 2
int a; You chose number 2
You chose number 3
printf("Pick a number from 1 to 4:\n"); You chose number 4
scanf("%d", &a); That's not 1,2,3 or 4!
switch (a) { You'll notice that the program will select the correct
case 1: case but will also run through all the cases below it
printf("You chose number 1\n"); (including the default) until the switch block's
case 2:
closing bracket is reached.
printf("You chose number 2\n");
case 3: To prevent this from happening, we'll need to insert
printf("You chose number 3\n"); another statement into our cases...
case 4:
printf("You chose number 4\n");
default:
printf("That's not 1,2,3 or 4!\n");
}
return 0;
}

The break Statement


#include <stdio.h> On first inspection you'll find that it's virtually
identical to the last example, except I've inserted a
int main() { break statement at the end of each case to "break"
int a;
out of the switch block.
printf("Pick a number from 1 to 4:\n"); Now it should work as expected:
scanf("%d", &a); Pick a number from 1 to 4:
2
switch (a) { You chose number 2
case 1: Notice that you don't need to surround you
printf("You chose number 1\n");
statement(s) in each case with opening and closing
break;
case 2: brackets - not like the "usual" statement blocks
printf("You chose number 2\n"); you've seen in previous chapters.
break; Personally, I tend to use an if block with multiple
case 3: else if statements, as this gives the option to add
printf("You chose number 3\n"); logical operators if required.
break;
case 4:
printf("You chose number 4\n");
break;
default:
printf("That's not 1,2,3 or 4!\n");
}
return 0;
}

The goto Statement


This is going back a long way... #include <stdio.h>
Rumour has it that the goto statement should be
avoided because it can cause errors. int main() {
int attempt, number = 46;
No harm in using it in the most simplest of
programs though, but don't make a habit of using
looping: /* a label */
it!! printf("Guess a number from 0-100\n");
The goto keyword is followed by a label, which is scanf("%d", &attempt);
basically some identifier placed elsewhere in the if(number==attempt) {
program - like a hyperlink the points to a place on printf("You guessed correctly!\n\n");
the same web page. }
You'll never see another example with goto in! else {
printf("Let me ask again...\n\n");
goto looping; /* Jump to the label*/
}
return 0;
}

Looping
The Concept of Looping
The term "looping" describes the way in which the It is possible to simulate each type by writing code
program executes statements over and over again, using other loops.
before exiting the loop and continuing with program Tell a lie - there is a fourth kind of loop but has no
flow. specific keyword. INFINITE LOOPS can cause your
In C, there are three types of loops: for loops, computer to hang! They sometimes end after a while,
while loops and do while loops. but in theory they should go on forever.

for Loops
I use for loops a lot. Here's the basic form: b determines whether or not the program loops. If b
for (a ; b ; c) { returns a non zero value, an iteration of the loop is
/* statements */ performed. In other words, the program enters the
} loop and executes the statements inside. b should
Brief example: therefore be some sort of condition. You can use
for(i=10, j=0 ; i!=j ; i--, j++) {
logical operators in your condition as usual.
printf("%d - %d = %d\n", i, j, i-j);
c is evaluated after an iteration of the loop, i.e. after
}
all the statements inside the loop body have been
a, b and c are expressions that are evaluated at
executed. If you have multiple expressions you want
different times.
evaluating, you can separate each one with a comma
a is evaluated once only - before entering the loop.
like this: i--, j++
It is a very good place to assign values to variables.
The round brackets and semi colons are required at
If you wanted to assign values to multiple variables,
all times. The three expressions aren't compulsory,
you can separate each assignment with a comma
but omitting b and failing to place a break statement
like this: i=10, j=0
somewhere in the loop can result in an infinite loop!
Let's look at a proper example:

#include <stdio.h> Before entering the loop, i is initialized with 10 and j


with 0. Let's step through the loop one iteration at a
int main() {
time:
int i,j;
for(i=10, j=0 ; i!=j ; i--, j++) { Iteration Before Loop After Loop
printf("%d - %d = %d\n", i, j, i-j); i j i!=j i j
}
return 0; 1 10 0 1 9 1
} 2 9 1 1 8 2
Output: 3 8 2 1 7 3
10 - 0 = 10 4 7 3 1 6 4
9 - 1 = 8
8 - 2 = 6 5 6 4 1 5 5
7 - 3 = 4
6 - 4 = 2 6 5 5 0 - -
At the end of each iteration, i is decremented by 1, j
is incremented by 1.
You should be familiar with the logic behind the The sixth evaluation of i!=j returns 0 for false,
printf statement, so I'll focus on the loop itself. because i and j are equal at that time, so the loop
body is not executed.

while Loops
Some might say that while loops are simpler to #include <stdio.h>
use, since they only require one expression in the
brackets: int main() {
while (expression) { int i=10; /* initialize variables */
/* statements */ int j=0; /* part a of a for loop */
}
while (i!=j) { /* test for condition
The loop body is executed if expression returns a
part b of for loop */
non zero value. Most of the time, you'd want to put printf("%d - %d = %d\n", i, j, i-j);
some sort of condition to be evaluated. i--; /* do something to variables */
I mentioned earlier on that you can simulate one j++; /* part c of for loop */
type of loop with another type - there is no unique }
way to loop. return 0;
The previous example can be rewritten using a }
while loop.

Infinite Loops
Having an expression that always returns a non I say "should" loop forever, but sometimes the
zero value in the brackets of a while loop (or the computer crashes and the program is shut down.
second expression of a for loop) can result in an while (1) {} also causes an infinite loop.
infinite loop. Missing the second expression in a for To combat infinite loops, you can use the break
loop will also result in an infinite loop, but missing statement (or in the last resort, Ctrl-Alt-Delete!).
the expression in the brackets of a while loop
causes a compilation error. This program should
loop forever:
#include <stdio.h> #include <stdio.h>

int main() { int main() {


int i; int i;
for(i=0 ; /* no expression */ ; i++) { for(i=0 ; /* no expression */ ; i++) {
printf("%d\n", i); printf("%d\n", i);
} if(i==1000) {
return 0; break; /* exits the loop when */
} } /* i equals 1000 */
}
return 0;
}

do while Loops
The last type of loop I rarely use. Don't forget the semi colon after the
It's almost identical to a while loop, except the loop while(expression) part!
body is executed at least once - the while If you run the example again, but initialize i with 11
(expression) part is after the loop body, like this: you'll notice that the loop body is still executed.
do { Simulating a do while loop with either a for or while
/* loop body */ loop is fiddley - most of the time I'd write the
} while (expression); statements in the loop body once, before the loop:
This example prints out the numbers 0-9:
#include <stdio.h> #include <stdio.h>

int main() { int main() {


int i = 0; int i = 0;
do {
printf("%d", i); printf("%d", i); /* "loop body" */
i++; i++;
} while (i<10);
return 0; while (i<10) {
} printf("%d", i);
i++;
}
return 0;
}

Hexadecimal Numbers
The Decimal System
From an early age, we've been taught how to count To understand different bases, try to think of it as "2
using the DECIMAL system, where the numbers lots of 102, 3 lots of 101 and 7 lots of 100", or:
consist of a mixture of the ten digits from 0 to 9. 2*100 + 3*10 + 7*1 = 237.
We say the the decimal system has a BASE of 10 - So what's "4560"?
the number of digits we can use to form our "4 lots of 103, 5 lots of 102, 6 lots of 101 and 0 lots of
numbers. 100", or:
What do you think when you see the number "237"? 4*1000 + 5*100 + 6*10 + 0*1 = 4560
"Two hundred and thirty seven"?
The Hexadecimal System
This section can get quite confusing, but I'll do my - The subscript number is the base.
very best! Having said that, it'd be easier if I stuck to words
HEXADECIMAL IS BASE 16. instead!
We still use digits 0 to 9, but there's also A, B, C, D, So what does "38" in hexadecimal really mean? In
E, and F to represent the decimal numbers 10, 11, decimal: "3 lots of 161 and 8 lots of 160", or:
12, 13, 14 and 15 respectively. 3*16 + 8*1 = 48 + 8 = 56.
But I write "38", do I mean 38 in decimal or 38 in What decimal number does "21C" in hexadecimal
hexadecimal? Who knows... represent? "2 lots of 162, 1 lot of 161 and 12 lots of
3810 is the formal notation for saying "Three eight 160", or:
base ten" (or "Three eight in decimal"), where as 2*256 + 1*16 + 12*1 = 512 + 16 + 12 = 540.
3816 represents "Three eight in hexadecimal".

Converting From Decimal to Hexadecimal


The past two examples saw the relatively easy Click here to recap on the % operator!
conversion from hexadecimal back to decimal. Now, decreasing the power, find out how many times
Before I move on, the case of the hexadecimal 162 goes into 683:
digits A to F do not matter - uppercase does seem 683 / 256 = 2.6679.... so 256 goes into 683 2 times.
more readable though, which is why I use it. Therefore the next hexadecimal digit is 2.
But first, let's go through some powers of 16... Now work out the remainder of 683 / 162:
160 = 1 =1 Remainder = 683 - (2*256) = 171.
161 = 16 = 10 Now find out how many times 161 goes into 171:
162 = 256 in hex... = 100 171 / 16 = 10.6875 so 16 goes into 171 10 times.
163 = 4096 = 1000 Therefore the next hexad ecimal digit is A (for 10).
164 = 65536 = 10000 Now work out the remainder of 171 / 161:
Now take a decimal number like 8875. Remainder = 171 - (10*16) = 11.
Find the highest power of 16 that is smaller or equal Now we're below the base value, so the rightmost
to 8875: 163 in this case. hexadecimal digit is B (for 11).
The number of the highest power plus 1 tells us how Stringing the hexadecimal digits together, we get
long the resulting hexadecimal number is going to 22AB as the hexadecimal equivalent of 887510.
be, so in this case, 3+1 = 4 hexadecimal digits. Quick check:
Now work out how many times 163 goes into 8875: 2*4096 = 8192
8875 / 4096 = 2.1667.... so 4096 goes into 8875 2 2*256 = 512
times and so the leftmost hexadecimal digit is 2. 10*16 = 160
Now work out the remainder of 8875 / 163: 11*1 = 11
Remainder = 8875 - (2*4096) = 683. 8192 + 512 + 160 + 11 = 8875
Alternatively:
Remainder = 8875 % 4096.

Other Points
Hexadecimal is sometimes abbreviated with HEX. #include <stdio.h>
Expressing negative decimal numbers in hex format
is possible, but as a beginner, you probably won't int main() {
need to know how. int i = 0xF0;
There is a hex format specifier: %X for an uppercase printf("%d is %X in hex\n", i, i);
printf("%d is %o in octal\n", i, i);
representation, or %x for lowercase. printf("%d is %X in hex\n", -i, -i);
To initialize a hex number in C, prefix the hex printf("%d is %o in octal\n", -i, -i);
number with 0x (zero x), like this: return 0;
int i = 0xFF; /* assigns 255 to i */ }
I will briefly mention OCTAL numbers. They have a Output:
base of 8, and work in a similar way to hex, for
240 is F0 in hex
example: 65 in decimal is 101 in octal because: 240 is 360 in octal
1*82 + 0*81 + 1*80 = 65. The octal format specifier -240 is FFFFFF10 in hex
is %o - you probably won't use octal numbers as -240 is 37777777420 in octal
often as hex though. Negative hex is mentioned in the bitwise operators
section, but you probably don't need to know it!
Binary Numbers
Zeros and Ones
In a nutshell: BINARY IS BASE 2. Anyway, back to binary numbers themselves, base 2
So the only two digits you use to form binary implies that you should know the powers of 2:
numbers are 0 and 1. 20 = 1 26 = 64 212 = 4096
I mentioned earlier that binary code is the lowest 2 =2
1
2 = 128
7
213 = 8192
level language and that it's sometimes referred to 22 = 4 28 = 256 214 = 16384
as "machine code". This is because that the 2 =8
3
2 = 512
9
215 = 32768
computer interprets a string of zeros and ones as a 24 = 16 210 = 1024 216 = 65536
sequence of instructions: zero meaning an "off" 2 = 32
5
2 = 2048
11

state, one meaning an "on" state. - Any higher, and I must get my calculator :)

Converting From Decimal to Binary


The procedure is very similar to the method used 4 goes into 6 once, so the 5th bit is 1. The remainder
for hexadecimal numbers - the only difference is is 6 - 4 = 2.
that you're using powers of 2 as opposed to 16. 2 goes into 2, so the 6th bit is also 1.
Take the number 70 in decimal. Now, there is no remainder, so the rest of the bits are
Find the highest power of 2 that goes into 70. all zeros - the 7th bit in this case.
Obviously, it's 64, so the highest power of 2 is 6, Then we can conclude that 70 in decimal is expressed
therefore you should expect 7 binary digits (or 7 as 1000110 in binary.
BITS for short). Notice how you much of this you can do in your head,
64 goes into 70 so the 1st bit is 1. compared to hexadecimal. Because you're only
Now work out the remainder: 70 - 64 = 6. working with zeros and ones - either a power of 2
Decreasing the power... how many times does 32 goes into a number or not.
go into 6? Zero times, so the 2nd bit is 0. Converting negative decimals into binary will be
Similarly, 16 and 8 don't go into 6, to the 3rd and covered in the bitwise operators section!
4th bits are both zeros.

Converting From Binary to Decimal


The reverse is easier. Take the binary number Then multiply the bottom with 20, the next one up
100011011. with 21 and so on...
First write the bits in a column with the first bit at 1*28 = 256
the top: 0*27 = 0
1 0*26 = 0
0 0*25 = 0
0 1*24 = 16
0 1*23 = 8
1 0*22 = 0
1 1*21 = 2
0 1*20 = 1
1 Add up the right hand side to get your answer:
1 256 + 16 + 8 + 2 + 1 = 283.

Converting From Hexadecimal to Binary


This sounds scary but it's not that bad. Check: 10*16 + 13*1 = 160 + 13 = 173.
Isn't it a pure coincidence that 16 is 24?! We can 1*27 = 128
expand on this by saying that any number from 0 to 0*26 = 0
F (0 to 15) can be expressed using 4 bits: 1*25 = 32
0 = 000 4 = 0100 8 = 1000 C = 1100 0*24 = 0
1 = 0001 5 = 0101 9 = 1001 D = 1101 128 + 32 = 160.
2 = 0010 6 = 0110 A = 1010 E = 1110 1*23 = 8
3 = 0011 7 = 0111 B = 1011 F = 1111 1*22 = 4
Then take any hexadecimal number: AD say. 0*21 = 0
Replace each hex digit with the 4 bit equivalent: 1*20 = 1
A = 1010 8 + 4 + 1 = 13.
D = 1101 160 + 13 = 173.
So AD in hex is 10101101 in binary.

Converting From Binary to Hexadecimal


This is just as easy. Check: 6*16 + 10*1 = 96 + 10 = 106.
Take a binary number, 1101010 say, and starting 0*27 = 0
from the right, group the bits into four bits: 1*26 = 64
0110 1010 1*25 = 32
- Notice how I added an extra zero as the first bit to 0*24 = 0
make it look a little nicer. 64 + 32 = 96.
Now simply replace each group of 4 with the hex 1*23 = 8
value: 0*22 = 0
0110 = 0 + 4 + 2 + 0 = 6. 1*21 = 2
1010 = 8 + 0 + 2 + 0 = 10 = A. 0*20 = 0
So 1101010 = 6A. 8 + 2 = 10.
96 + 10 = 106.

Bitwise Operators 1
What Are They?
As the name suggests, bitwise operators are used to First of all, to understand the logic behind these
perform calculations using binary digits (this is why operators, you need to know to convert to and from
I had to write a section about binary numbers). decimal and binary. Secondly, don't confuse the
In the C source code, you'd have to use bitwise bitwise operators with the logical and relation ones!
operators with decimal numbers. I will run through the six operators...

& - Bitwise AND


Bitwise AND requires two operands - just like logical - Now you'll see why I've added that extra zero! So
AND. However, bitwise operators return a variety of now we have the return value of 9 & 23 - it is simply
numbers - not just 1 or 0. 1.
So how does bitwise AND work? The easiest way is More examples:
to look at an example: 9 & 23 1000 & 1101 = 1000
First, you must convert decimal into binary: 00100 & 10111 = 00100
9= 01001 01111 & 11100 = 01100
23 = 10111
- Notice how I've added an extra zero for the binary It's not easy doing these calculations in your head.
representation of 9, simply to match the number of You can type your working here if you want -
bits of 23.
Now align the right most bits:
01001
10111
Starting from the right, if BOTH numbers are 1,
write a 1 underneath:
01001
10111
____1
Remember that x && y returns 1 if x and y are both
non zero.
Then work your way to the left:
01001
10111
00001

| - Bitwise OR
Bitwise OR also requires two operands, and works in More examples:
a similar fashion as bitwise AND. Let's look at the 1000 | 1101 = 1101
00100 | 10111 = 10111
previous example but with bitwise OR: 9 | 23 01111 | 11100 = 11111
You follow the same steps, up until the point where
you compare bits:
01001
10111
Starting from the right, if BOTH numbers are 0,
write a 0 underneath, else write a 1:
01001
10111
____1
Remember that x || y returns 0 if both x or y are
zero, else it returns 1.
Then work your way to the left:
01001
10111
11111
So 9 | 23 returns 31.

^ - Bitwise XOR
Bitwise XOR also requires two operands, and works More examples:
in a similar fashion as the bitwise AND and OR. XOR 1000 ^ 1101 = 0101
is an abbreviation of eXclusive OR. 00100 ^ 10111 = 10011
If there was a logical operator called XOR, x XOR y 01111 ^ 11100 = 10011
will return 1 if EITHER x or y return non zero values.
If x and y are BOTH non zero, x XOR y would return
0. If x and y are both zero, x XOR y would again,
return 0.
You follow the same steps, up until the point where
you compare bits:
So what's 9 ^ 23 ? Using the same routine and
applying the logic behind XOR:
01001
10111
11110
So 9 | 23 returns 30.

A Little Note on Bitwise XOR...


If you wanted to know what is bitwise XOR in terms on NOT, AND and OR, here's your answer:
1 AND 1 = 1 1 OR 1 = 1 NOT 1 = 0
1 AND 0 = 0 1 OR 0 = 1 NOT 0 = 1
0 AND 1 = 0 0 OR 1 = 1
0 AND 0 = 0 0 OR 0 = 0

NOT (1 AND 1) = 0
NOT (1 AND 0) = 1
NOT (0 AND 1) = 1
NOT (0 AND 0) = 1

(1 OR 1) AND ( NOT (1 AND 1)) = 1 AND 0 = 0


(1 OR 0) AND ( NOT (1 AND 0)) = 1 AND 1 = 1
(0 OR 1) AND ( NOT (0 AND 1)) = 1 AND 1 = 1
(0 OR 0) AND ( NOT (0 AND 0)) = 0 AND 1 = 0

1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0

Bitwise Operators 2
<< - Bitwise Left-Shift
Bitwise Left-Shift is useful when to want to More examples:
MULTIPLY an integer (not floating point numbers) 5 << 3 = 5*23 = 5*8 = 40
by a power of 2. 8 << 4 = 8*24 = 8*16 = 128
The operator, like many others, takes 2 operands 1 << 2 = 1*22 = 1*4 = 4
like this:
a << b More space for working things out:
This expression returns the value of a multiplied by
2 to the power of b. Bitwise shifts are said to be more efficient than the
Why is it called a left shift? normal arithmetic operations, but I'm still yet to write
Answer: Take the binary representation of a, and a computer game :)
add b number of zeros to the right, consequently Bitwise shifting of negative numbers reuires
"shifting" all the bits b places to the left. knowledge of the binary representation of negative
Example: 4 << 2. numbers.
4 is 100 in binary. Adding 2 zeros to the end gives
10000, which is 16, i.e.
4*22 = 4*4 = 16.
What is 4 << 3 ? Simply add 3 zeros to get 100000,
which is 4*23 = 4*8 = 32.
Notice that shifting once to the left multiplies the
number by 2. Multiple shifts of 1 to the left, results
in multiplying the number by 2 over and over again.
In other words, multiplying by a power of 2.

>> - Bitwise Right-Shift


Bitwise Right-Shift does the opposite, and takes Another example: 29 >> 3.
away bits on the right. 29 is 11101 in binary. Take of the last 3 bits to leave
Suppose we had: 11, which is 3 in decimal. Check: 29 / 8 is 3.625,
a >> b which rounds down to 3, so we're okay :)
This expression returns the value of a divided by 2
to the power of b. More space for working things out:
Example: 8 >> 2.
8 is 1000 in binary. Performing a right shift of 2
involves knocking the last 2 bits off: 1000, which
leaves us with 10, i.e. 2.
8 >> 2 is the as doing 8 / 22 = 8 / 4 = 2.
But what happens if we had a left operand that's not
a power of 2? Let's try 9 >> 2.
9 is 1001. Now take off the last 2 bits, leaving us
with 10, which is 2. But this does make sense, since
9 / 4 = 2.25, which rounds down to 2.

Bitwise Operators 3
The First Bit
Before I talk about the last bitwise operator, I will The size of a short int is 16 bits. This means that
give a brief lesson on negative binary numbers. This 16 binary digits can be used to represent any integer.
is probably past the beginner stage, but I've added Now, 32767 is 0111 1111 1111 1111 in binary (I've
it in for completeness (I didn't even learn much added the spaces to make it easier to count the bits!).
about hex and binary at university!). 65535 is 1111 1111 1111 1111 in binary.
Recall from the Type Modifiers section, that an As you can see, the only difference between the two,
int could be signed, or unsigned. is the first bit on the left. Basically, the unsigned type
If it's signed, the range is usually -32768 to 32767, modifier turns "on" that bit, so that it could be used
where as an unsigned int has a range of 0 to to represent a number from 32768 to 65535.
65535. On the other hand, the signed keyword "disables"
Note that 215 = 32768 and 216 = 65536. that bit from being used to represent a number from
These figures only apply to short ints - assume 32768 to 65535. Instead, it's used to represent
that an int is a short int by default for this negative numbers from -1 to -32768.
lesson.
~ - Bitwise NOT (Complement)
Logical NOT reverses the truth value of expressions. Now, unlike the previous 3 bitwise operators: AND,
i.e. turns true (non zero) into false (zero) and vice OR and XOR, NOT takes just one operand, plus the
versa. return value depends on the type of int - usually,
Bitwise NOT (also known as complement), takes the ints are signed short ints by default.
binary representation of a number, and turns all For an unsigned short int, the maximum number
zeros into ones, and ones into zeros. in binary is 1111 1111 1111 1111 (or 65535 in
decimal, i.e. 216-1).

unsigned short int


Using bitwise NOT in unsigned short int mode is 9 is 0000 0000 0000 1001
relatively straightforward. ~9 is 1111 1111 1111 0110
Basically, you MUST write the integer in its full 16 This might seem like a horrid number to convert back
binary digit format, turn all zeros into ones and to decimal, but the easiest way to think of it, is the
ones into zeros, and you'll end up with the binary maximum 16 bit number, minus 9: 65535 - 9.
representation of your return value. If you want, go back to the binary-decimal
Take 9 as an example. Suppose we assign ~9 to an converter to check that the binary for ~9 is equivalent
unsigned short int declared variable. to 65535 - 9 = 65526.
If we were to use bitwise NOT, we'd have to write in Let's look at a C program...
all the extra zeros, then reverse the bits...

#include <stdio.h> #include <stdio.h>

int main() { int main() {


unsigned short int j = ~9; unsigned short int i = 9;
printf("~9 is %d\n", j); printf("~%d is %d\n", i, ~i);
return 0; return 0;
} }

Output: Output:
~9 is 65526 ~9 is -10

Notice the way I've declared my variable. I did end ... looks like the value returned depends on the type
up with unexpected results first time around, as my of int (if any) you assign it to.
initial program demonstrates...

Negative Binary Numbers


Now let's move to signed short int mode, and Examples: 2+1: 2 is 10 in binary, last bit is zero, so
take 10 as our example. To find out what -10 is in change it to 1 to get 11, which is 3.
binary, first we must use bitwise NOT on 10: 3+1: 3 is 011 in binary. First bit from the right is 1,
10 is 0000 0000 0000 1010. so that gets turned into a 0. Second bit from the right
~10 is 1111 1111 1111 0101 is 1, so that's changed to 0. 3rd bit from the right is
Now add 1 to ~10. This could be tricky - if the 0, so change that to 1 to get 100 which is 4.
rightmost bit is zero, simply change it to 1 and Back to the example, 1 added to ~10 gives:
you're done. 1111 1111 1111 0110 - that is -10 in binary.
If it's already 1, change it to zero and look at the
next bit. If that's zero, change it to 1 and you're
done. If not, change it to zero and move on... keep
going until you can change a zero into a 1.

signed short int


Using bitwise NOT and assigning to a signed short ... OR in general, ~x is simply -1 - x !!
int isn't as hard as initially thought. In case you wondered, to subtract 1 from a binary
First write out its 16 bit format, change all ones into number, starting from the right again, if the bit is 1,
zeros and vice versa and you have your answer. It's turn it into a zero and you're done, else change it to a
just converting it back into decimal that's a little 1 and move left. Keep doing this until you can change
trickier! a 1 into a zero.
Take 12: 0000 0000 0000 1100 ~12 - 1 is 1111 1111 1111 0010
Then ~12 is: 1111 1111 1111 0011 Now bitwise NOT this to get 0000 0000 0000 1101
To convert it back into decimal, subtract 1 from ~12 ... stick a minus sign in front of the decimal format to
and bitwise NOT it. Then convert that back into get your answer: -(8+4+1) = -13.
decimal (easier), and insert a minus sign in front.

Remember that in unsigned short int mode, ~x is -1 - x !

Negative Hex Numbers?


Here's a thought: what if we converted the binary Now Add 1 to ~240:
format of a negative decimal number into hex 1111 1111 0001 0000
format?! Surely that should yield the hex for a - This is -240 in binary. Now covert each set of 4 bits
negative number... Let's take -240, whose hex into their hex values:
value is FFFFFF10 (seen in the hex section). 1111 = decimal 15 = F in hex
Convert 240 into binary: 0001 = decimal 1 = 1 in hex
240 - 128 = 112 0000 = decimal 0 = 0 in hex
112 - 64 = 48 ... We get FF10, which is the last 4 digits of what
48 - 32 = 16 MSVC++ displayed.
16 - 16 = 0 Having said that, FFFFFF10 suggests that there are
240 is 11110000 in binary. 8*4 = 32 bits (Each hex digit is 4 bits as 24=16).
Now perform bitwise NOT: Anyway, all of this, is probably out of a beginner's
240: 0000 0000 1111 0000 scope!
~240: 1111 1111 0000 1111

Functions
Introduction
A function can be thought of as a mini-program, You've already encountered a few functions: main,
where a group of statements are executed when the printf and scanf.
function is called. The main function is special, in the way that it's called
A function is CALLED (or INVOKED) when you need automatically when the program starts.
to branch off from the program flow and execute In C, and other programming languages, you can
the group of statements within that function. Once create your own functions.
the statements in the function are executed,
program flow resumes from the place where you
called your function.

A Typical Function
Functions have 5 main features: If the function does not return a value, we put the
1. The RETURN TYPE is the data type of the void keyword before the function name.
RETURN VALUE of the function. This function has one argument, which is of the type
2. The NAME is required as an identifier to the int. If you have arguments, you must put variable
function, so that the computer knows which declarations in the round brackets.
function is called. Naming of functions follows The function body consists of 2 statements. The first,
the same set of rules as the naming of sees an int variable b declared and assigned a*a, i.e.
variables. a squared. The second statement uses the return
3. Functions can take ARGUMENTS - a function keyword to pass the value of b back into the main
might need extra information for it to work. program, hence exiting the function.
Arguments are optional. Within the program, one might write:
4. The function BODY is surrounded by curly x = squareNumber(5);
brackets and contains the statements of the This would assign 25 to x. We say that 5 is passed as
function. an argument to the function squareNumber.
5. The RETURN VALUE is the value that is passed The variables within the squareNumber function are
back to the main program. Functions exit
LOCAL VARIABLES - when the function exits,
whenever you return a value.
variables a and b are deleted from memory.
This is what a function definition might look like: int squareNumber(int a) is also known as the
int squareNumber(int a) { FUNCTION HEADER.
int b = a*a;
return b;
}
squareNumber is the name of this function. Because
an integer is returned, the int keyword must be
placed before the function name.

Example
#include <stdio.h>

void printAverage(int x, int y, int z); /* the function declaration */

int main() {
int a, b, c;

printf("Enter 3 integers separated by spaces: ");


scanf("%d %d %d", &a, &b, &c);

printAverage(a, b, c); /* the function call */

return 0; /* exit main function */


}

void printAverage(int x, int y, int z) { /* the function definition */


float average = (float) (x + y + z) / 3; /* coersion in practice! */
printf("The average value of %d, %d and %d is %f\n", x, y, z, average);
}

It's common practice to place the function definition The function declaration is a single statement
underneath main - if you're editing main most of the consisting of the function header - don't forget the
time, you wouldn't want to scroll too far down the semi colon at the end!
page to get to it! Notice that in the function call I had to pass three
You can put the function definition above it if you arguments to match the three arguments in the
wanted. But if you place it underneath main, make function definition. And the variable names in the
sure you put the function declaration above main - function's argument section didn't have to match the
see the example. This is because the computer variable names in the function call. The most
won't know if the function exists if you call it important thing is that the data types had to match.
without it being declared in the first place. It's the And notice my use of the void keyword for the
same with variables: you can assign anything to x printAverage function, since no value is returned.
unless you've declared x beforehand.

Functions That Call Other Functions


#include <stdio.h>

int triangular(int x);

int main() {
int x;
printf("Enter an integer: ");
scanf("%d", &x);

if(x%10>3 || x==11 || x==12 || x==13) {


printf("\n%d is the %dth triangular number\n", triangular(x), x);
}
else {
switch(x%10) {
case 1:
printf("\n%d is the %dst triangular number\n", triangular(x), x);
break;
case 2:
printf("\n%d is the %dnd triangular number\n", triangular(x), x);
break;
case 3:
printf("\n%d is the %drd triangular number\n", triangular(x), x);
break;
}
}
printf("You entered: %d\n", x);
return 0;
}

int triangular(int a) { /* the nth triangular number is 1+2+3+ ... +n */


int x = (a * (a + 1)) / 2;
return x;
}

Above main, we see the function declaration. The The if, else and switch blocks determine how to
triangular function takes an integer argument, display the result.
and returns an integer. One important thing to remember is that the x in
Below main, we have the function definition - it main is totally different to the x in triangular.
works out and returns the triangular number of the You see that the value of x in main remains
number passed to the function. unchanged after calling triangular.
Inside main, observe that inside printf, we call the
triangular function.

Functions That Call Themselves


#include <stdio.h>

int factorial(int x);

int main() {
int a, b=1, temp;

printf("Enter an integer: ");


scanf("%d", &a);

printf("\n%d factorial is %d\n\n", a, factorial(a));

printf("Enter another integer: ");


scanf("%d", &a);

temp = a;

for( ; a>0 ; a--) {


b*=a;
}

printf("\n%d factorial is %d\n", temp, b);

return 0;
}

int factorial(int x) { /* n factorial, (or n!) is 1*2*3* ... *n */


if(x!=0) {
return (x*factorial(x-1));
}
else {
return 1;
}
}

A function that calls itself is said to be a RECURSIVE There's nothing new in the last example for me to
function. explain. Later, I will show you how to define your
Recursive function calls can be less efficient than a functions in file different to the one where main sits.
loop, and I don't personally use them.

Arrays 1
Introduction
Arrays allow you to store a sequence of variables of the same data type. You can picture an array in the
computer's memory as a row of consecutive spaces, each of which can store a data item, known as an
ELEMENT.

Declaring Arrays
You need to make a declaration before using an This reserves memory for an array that to hold five
array. To declare an array, you need to specify its integer values. The number of elements should be
data type, its name and, in most cases, its size. enclosed in the square brackets. If you don't specify
Make sure the array has a valid name. Here's an the number of elements during the declaration, you
example: have declared an UNSIZED array - the size will be
int arrayOfInts[5]; calculated when you insert values into it.

Initializing Arrays
You can assign values to the array in several ways. For example, if I wanted an array to hold the numbers
1 through to 10, I could do this in several ways, as this example demonstrates:
int main() {

int arrayOfInts1[10] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };
int arrayOfInts2[10];
int arrayOfInts3[] = {1,2,3,4,5,
6,7,8,9,10}; /* an unsized array */
int arrayOfInts4[10];
int i;

arrayOfInts2[0] = 1;
arrayOfInts2[1] = 2;
arrayOfInts2[2] = 3;
arrayOfInts2[3] = 4;
arrayOfInts2[4] = 5;
arrayOfInts2[5] = 6;
arrayOfInts2[6] = 7;
arrayOfInts2[7] = 8;
arrayOfInts2[8] = 9;
arrayOfInts2[9] = 10;

for(i=0 ; i<10 ; i++) {


arrayOfInts4[i] = i + 1;
}

return 0;
}

You may have noticed that the first element of an array is indexed 0 rather than 1. This
is a simple, yet important idea that you need to take into account. From now on, start
counting at zero!

Printing Out Arrays


One of the commonest ways to print out the contents of the array is to use a loop. I personally prefer
using a for loop, like this:
#include <stdio.h>

int main() {
int anotherIntArray[5] = {1,2,3,4,5};
int i;

for(i=0 ; i<6 ; i++) {


printf("anotherIntArray[%d] has a value of %d\n", i, anotherIntArray[i]);
}
return 0;
}
Output:
anotherIntArray[0] has a value of 1
anotherIntArray[1] has a value of 2
anotherIntArray[2] has a value of 3
anotherIntArray[3] has a value of 4
anotherIntArray[4] has a value of 5
anotherIntArray[5] has a value of 6684216

I iterated one element too far to demonstrate what happens if you did. As you can see, MSVC++ seemed
to print out a random number.
You can also use a loop with scanf to insert elements:

#include <stdio.h>

int main() {
int anotherIntArray[5];
int i;

printf("Enter 5 integers one by one, pressing return after each one:\n");

for(i=0 ; i<5 ; i++) {


scanf("%d", &anotherIntArray[i]);
}

for(i=0 ; i<5 ; i++) {


printf("anotherIntArray[%d] has a value of %d\n", i, anotherIntArray[i]);
}
return 0;
}

What the output might look like:


Enter 5 integers one by one, pressing return after each one:
3
7
2
856
324
anotherIntArray[0] has a value of 3
anotherIntArray[1] has a value of 7
anotherIntArray[2] has a value of 2
anotherIntArray[3] has a value of 856
anotherIntArray[4] has a value of 324

Character Arrays
So far I've used arrays of integers in my examples - Each element of the array can hold one character. But
probably the type I've been using the most. You can if you end the array with the NULL CHARACTER,
use arrays for floats and doubles as well as chars. denoted by \0 (that is, backslash and zero), you'll
Character arrays have a special property... have what is known as a STRING CONSTANT. The null
character marks the end of a string - useful for
functions like printf. Time for an example.....

#include <stdio.h>

int main() {
char charArray[8] = {'F','r','i','e','n','d','s','\0'};
int i;

for(i=0 ; i<8 ; i++) {


printf("charArray[%d] has a value of %c\n", i, charArray[i]);
}

printf("My favourite comedy is %s\n", charArray); /* Alternative way */

return 0;
}

Output:
charArray[0] has a value of F
charArray[1] has a value of r
charArray[2] has a value of i
charArray[3] has a value of e
charArray[4] has a value of n
charArray[5] has a value of d
charArray[6] has a value of s
charArray[7] has a value of
My favourite comedy is Friends

Notice I enclosed each of the characters with single quote marks - double quote marks are reserved for
strings. I also used the character and string format specifiers (%c and %s respectively).
Strings will be covered in a later section.

Stupid me - when I first wrote this lesson, I accidentally used the wrong slash symbol
for the null character with the above example!! I've learnt my lesson now.

Arrays 2
Into The Next Dimension...
So far, I've been giving you examples with one You already know how to declare a 1D array, but
dimensional arrays. An array's DIMENSION is the what about 2D? Simple. Take this example:
number of indices required to reference an element. int array2D[3][5];
For example, arrayOfInts[0] is the first element. This tells the computer to reserve enough memory
The index is 0 - there is only 1 index so space for an array with 15, that is, 3 x 5 elements.
arrayOfInts is one dimensional. One way to picture these 15 elements is an array with
Now suppose we want arrayOfInts[0] to hold 2 3 rows and 5 columns.
integers. So we'll move into the next dimension... But there are times when you don't know the size, so
arrayOfInts[0][0] could hold the first integer, and you'd want to use an unsized array. However, you
must specify every dimension size except the left one.
arrayOfInts[0][1] could hold the other. We need
Like this:
2 indices to reference each integer, so arrayOfInts int array2D[][5];
is two dimensional.
2 dimensions is probably the most you'll need, but 3
dimensions is like arrayOfInts[0][0][0] !! 2D
arrays are useful for storing grid-base information,
like coordinates.

Initializing 2D Arrays
Methods used are similar to those of the 1D arrays:
#include <stdio.h>

int main() {
int first[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

int second[3][4] = {0, 1, 2, 3,


4, 5, 6, 7,
8, 9,10,11};
/* a clearer definition than the first */

int third[][5] = {0,1,2,3,4};


/* third[] only has one index of 1 */

int fourth[][6] = {0,1,2,3,4,5,6,7,8,9,10,11};


/* fourth[] has 2 indices - 0 or 1 */

int i,j;

int fifth[5][4];

int sixth[2][6];

int seventh[2][3];

for(i=0 ; i<5 ; i++) {


for(j=0 ; j<4 ; j++) {
fifth[i][j] = i * 4 + j;
}
}

for(i=0 ; i<2 ; i++) {


printf("Enter 6 integers separated by spaces: ");
for(j=0 ; j<6 ; j++) {
scanf("%d" , &sixth[i][j]);
}
printf("\n");
}

printf("You entered:\n");
for(i=0 ; i<2 ; i++) {
for(j=0 ; j<6 ; j++) {
printf("%d ", sixth[i][j]);
}
printf("\n");
}

seventh[0][0] = 0;
seventh[0][1] = 1;
seventh[0][2] = 2;
seventh[1][0] = 3;
seventh[1][1] = 4;
seventh[1][2] = 5;

return 0;
}

For loops are dead handy. And not just for initialization - they are commonly used for printing out arrays. I
tend to iterate the "rows" in the first loop, then the "columns". Whichever way you choose, keep it
consistent!

Array Sizes
If you ever wanted to find out how much memory your arrays occupy (1D or multidimensional), you can
use the sizeof operator like this:

#include <stdio.h>

int main() {
char arrayChar[] = {'A','r','r','a','y','\0'};

int arrayInt[5] = {1,2,4,8,16};

float arrayFloat[3] = { 1.24 , 2 , 4.68756 };

double arrayDouble[2];

int arrayInt2D[][4] = {1,6,3,7,


0,3,8,9,
2,5,2,3};

arrayDouble[0] = 23.23456532;
arrayDouble[1] = 2.3422267;
printf("The size of arrayChar is %d\n", sizeof(arrayChar));
printf("The size of arrayInt is %d\n", sizeof(arrayInt));
printf("The size of arrayFloat is %d\n", sizeof(arrayFloat));

/* Alternative way */

printf("The size of arrayDouble is %d\n", sizeof(double) * 2);


printf("The size of arrayInt2D is %d\n", sizeof(arrayInt2D));
printf("The size of arrayInt2D[0] is %d\n", sizeof(arrayInt2D[0]));

return 0;
}
Output:
The size of arrayChar is 6
The size of arrayInt is 20
The size of arrayFloat is 12
The size of arrayDouble is 16
The size of arrayInt2D is 48
The size of arrayInt2D[0] is 16

You can use sizeof to find out the maximum of "rows" there are in a 2D array. For example, how many
"rows" are there inarrayInt2D[][4]?
This is given by: sizeof(arrayInt2D) / sizeof(arrayInt2D[0]), which is 48/16 = 3. Think of this
calculation as "size of entire array / size of a column".
So there are 3 "rows" and 4 "columns" to this 2D array.
Having said all that, the "rows and columns" visualization shouldn't confuse you with the way the data is
stored in memory.
int arrayInt2D[][4] = {1,6,3,7, 0,3,8,9, 2,5,2,3};
- This uses 12 consecutive memory slots, with 1 placed in the first slot, 6 in the next one and so on. So 7
is next to the 0. In fact, arrayInt2D[0][4] returns 0, arrayInt2D[0][5] returns 3 and so on.
arrayInt2D[3] returns some random number because there is no 4th row.

Passing Arrays to Functions


Single Dimensional Arrays
Sometimes it's inconvenient to call a function that requires a long list of arguments.
One way around this, is to store your variables into an array, then pass a pointer to the array to the
function. This method will be discussed in greater detail in the pointers section, but for now you need to
know that the array isn't actually passed to the function - just the array's location in the memory. This is
known as PASS BY REFERENCE. The name of an array references the array's location in the memory, its
ADDRESS.
#include <stdio.h>

int addNumbers(int fiveNumbers[]); /* declare function */

int main() {
int array[5];
int i;

printf("Enter 5 integers separated by spaces: ");

for(i=0 ; i<5 ; i++) {


scanf("%d", &array[i]);
}

printf("\nTheir sum is: %d\n", addNumbers(array));


return 0;
}

int addNumbers(int fiveNumbers[]) { /* define function */


int sum = 0;
int i;

for(i=0 ; i<5 ; i++) {


sum+=fiveNumbers[i]; /* work out the total */
}
return sum; /* return the total */
}

Notice that I've left the size of the array blank in both the function declaration and definition - the
compiler works it out for you. Also, when I called the function, I passed on the name of the array. This is
the equivalent to passing &array[0] - the address of the first element. You'll learn about the address-of
operator later.

Multidimensional Arrays
This is similar to passing 1D arrays but, in the function declarations you must specify all the dimension
sizes (but the leftmost one is optional).
#include <stdio.h>

void printArray(int array[][4]); /* declare function */

int main() {
int array[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
printArray(array);
return 0;
}

void printArray(int array[][4]) { /* define function */


int i, j;

for(i=0 ; i<3 ; i++) {


for(j=0 ; j<4 ; j++) {
printf("%2d ", array[i][j]);
}
printf("\n");
}
}

Pointers 1
& - The "Address of" Operator
Before I tell you what a pointer is, I'd have to Now suppose we wanted to find out where in the
introduce you to this operator. memory a variable lives. We can use the address-of
It looks familiar - we saw it in the bitwise operators operator. &x returns the "address of x" in hex format.
section. However, bitwise AND takes two operands #include <stdio.h>
like this: a & b, but the ADDRESS OF operator only int main() {
takes one on the right: &x. int x = 0;
printf("Address of x = 0x%p \n", &x);
Recall that when you declare a variable, you reserve
return 0;
bytes in the computer's memory for that variable.
}
The allocated memory is referenced by the variable
Output: Address of x = 0x0065FDF4
name and must be unique.
%p is the format specifier for addresses (%x would still
You can picture the computer's memory as a very
long row of slots. Now, each slot has a unique compile OK). 0x in the printf function is there to
ADDRESS, which is expressed in hexadecimal signify that a hex number follows.
format. It's like a long road of houses - each house Recall: scanf("%d", &x);
has a unique number in decimal format. In each - You can translate this as: "take the inputted integer
occupied house, there are people. and put it in the address of x".
In our case, the houses are memory slots, and the
people are the variables.

Left and Right Values


Now let's look at the assignment operator: So x is an L-value because it can appear on the left as
x = 1; takes the value on the right (e.g. 1) and we've just seen, or on the right like this:
puts it in the memory referenced by x, say. y = x;
Also known as L-VALUES and R-VALUES However, constants like 1 are R-values because 1
respectively L-values can be on either side of the could appear on the right, but 1 = x; is invalid.
assignment operator where as R-values only
appear on the right.

Pointers
POINTERS are VARIABLES that store the memory Let's look at declaring and initializing pointers...
address of other variables. int x;
Suppose we had an integer variable, x. We know float y;
how to get the address of x using &, but how do we
int *pointer_to_x;
store the hex value returned by &x ?
pointer_to_x = &x;
This is where pointers come into play. A pointer is a
variable, so it is declared just like a variable. The float *pointer_to_y = &y;
only difference is that pointer variables must have /*a simpler way*/
the DEREFERENCE OPERATOR, *, before its name. Finally, *pointer_to_x = &x; causes a compilation
Don't confuse this with the multiplication operator error, so be careful with the way you declare and
though - multiply takes two operands (e.g. x*y), initialize your pointers.
dereference only takes one (e.g. *x). char * is somewhat special, and will be looked at in
The data type of a pointer must match the data type the string section.
of the variable it points to.

You compiler might complain if you try and declare variables after creating pointers,
so it's best if you declare all your variables at the beginning of main, rather than
"on the fly" e.g. halfway through main.

Accessing Variable Values Using Pointers


Now that you have a pointer that points to a Output:
variable, how can we retrieve the value it's pointing Address of x: 0x0065FDF4
to? Address of x: 0x65fdf4
Answer: you can access the variable's value using Address of ptr: 0x65fdf0
the dereference operator. Here's an example: Value of x: 12
#include <stdio.h>
The first 2 printf statements demonstrates that the
int main() { address of x is stored in the pointer variable, ptr.
int x = 12; Notice how %p returns a full 8 digit hex value in
int *ptr = &x; uppercase - maybe I should've used %X for the
address of x for clarity.
printf("Address of x: 0x%p\n", ptr); The 3rd printf demonstrates that ptr itself has a
printf("Address of x: 0x%x\n", &x); place in the memory, which shows it's a variable.
printf("Address of ptr: 0x%x\n", &ptr);
The final printf uses the dereference operator to
printf("Value of x: %d\n", *ptr);
extract the value pointed to by ptr, like this: *ptr.
return 0;
}

Pointers and Arrays


When I first learnt pointers, I kept thinking: "Why #include <stdio.h>
should I use pointers?!!". Looking at my previous
example, I could've simplify things a little by not int main() {
using pointers. int x[10] = {0,1,2,3,4,5,6,7,8,9};
Pointers are useful when it comes to arrays.
printf("Address of x[0]: 0x%p\n", &x[0]);
One less obvious fact is that the name of an array is
printf("Address of x: 0x%p\n", x);
a pointer, simply because the name points to the
first element of that array. printf("Value of x[0]: %d\n", x[0]);
Try and picture this: when you initialize an array (of printf("Value of x[0]: %d\n", *x);
size 10, lets say), the computer picks a row of 10
CONSECUTIVE unused memory slots and stores the return 0;
values in them. }
The name of the array refers to the base of the Output:
array, that is, the very first memory slot of that Address of x[0]: 0x0065FDD0
array (which holds the first element). Address of x: 0x0065FDD0
So if the name is a pointer, we should be able to Value of x[0]: 0
extract the first element using the dereference Value of x[0]: 0
operator. In other words, *nameOfArray should
So the name of the array points to the first element,
return the value of nameOfArray[0]. as assumed.

Pointer Arithmetic
Once we've created a pointer that points to a Similarly, ptr--, --ptr and ptr-=1 will move the int
certain variable, we can either reassign it another pointer "back" 2 bytes.
variable's address, or we can move it around by And you're not restricted to move in steps of 1 either:
performing POINTER ARITHMETIC. ptr+=n will move it "forward" by n*2 bytes,
Suppose we had an int pointer, ptr. If we say ptr+ (assuming ptr is an int pointer).
+, ++ptr or ptr+=1, we're actually moving the The larger the data type, the larger the step size. So
pointer forward by 2 bytes (i.e. the size of its data if ptr was a double pointer, ptr-=3 will move it
type). So it'll point somewhere else in the "back" by 3*8 = 24 bytes.
computer's memory.

The arithmetic assignment operators you can use with pointers are += and -=
ptr*=2 and ptr/=2 cannot be used!

Pointers 2
Using Pointer Arithmetic With Arrays
I previously mentioned that arrays occupy consecutive memory slots in the computer's memory.
This is where pointer arithmetic comes in handy - if you create a pointer to the first element, incrementing
it one step will make it point to the next element.
#include <stdio.h>

int main() {
int *ptr;
int arrayInts[10] = {1,2,3,4,5,6,7,8,9,10};

ptr = arrayInts; /* ptr = &arrayInts[0]; is also fine */


printf("The pointer is pointing to the first array element, ");
printf("which is %d.\n", *ptr);
printf("Let's increment it.....\n");

ptr++;

printf("Now it should point to the next element, which is %d.\n", *ptr);


printf("But suppose we point to the 3rd and 4th: %d %d.\n", *(ptr+1),*(ptr+2));

ptr+=2;printf("Now skip the next 4 to point to the 8th: %d.\n", *(ptr+=4));

ptr--;

printf("Did I miss out my lucky number %d?!\n", *(ptr++));


printf("Back to the 8th it is then..... %d.\n", *ptr);

return 0;
}

Output:
The pointer is pointing to the first array element, which is 1.
Let's increment it.....
Now it should point to the next element, which is 2.
But suppose we point to the 3rd and 4th: 3 4.
Now skip the next 4 to point to the 8th: 8.
Did I miss out my lucky number 7?!
Back to the 8th it is then..... 8.

The first thing I must point out, is that although arrayInts is a pointer to the first element, you can't use
it to perform pointer arithmetic, since it is not a "real" int pointer, unlike ptr.
Expressions of the form (ptr+1) and (ptr+2) do not move the pointer: they are used to reference
elements one and two steps in front. ptr+=2 is the statement that moves the pointer.
Next let's look at *(ptr++). Note the POST INCREMENT operator - this returns the current value that the
pointer's pointing to, THEN the pointer is moved. If it was *(++ptr), the pointer is moved first. The same
applies for decrementing.

Use brackets to make your code more readable.

Modifying Variables Using Pointers


You know how to access the value pointed to using the dereference operator, but you can also modify the
content of variables.
To achieve this, put the dereferenced pointer on the left of the assignment operator, as shown in this
example, which uses an array:
#include <stdio.h>

int main() {
char *ptr;
char arrayChars[8] = {'F','r','i','e','n','d','s','\0'};

ptr = arrayChars;

printf("The array reads %s.\n", arrayChars);


printf("Let's change it..... ");

*ptr = 'f'; /* ptr points to the first element */

printf(" now it reads %s.\n", arrayChars);


printf("The 3rd character of the array is %c.\n", *(ptr+=2));
printf("Let's change it again..... ");

*(ptr - 1) = ' ';

printf("Now it reads %s.\n", arrayChars);


return 0;
}

Output:
The array reads Friends.
Let's change it..... now it reads friends.
The 3rd character of the array is i.
Let's change it again..... Now it reads f iends.

Remember that a char array with the null character, \0, as the last element is called a string constant.
%s is the string format specifier.
*(ptr+=2) moves the pointer 2 steps forward then returns the character it points to.
*(ptr - 1) = ' '; doesn't move the pointer - it simply replaces the element one step back from the
current position, with a space.

Passing Pointers to Functions


Recall from tutorial 23 that you can pass arrays to functions. The array isn't actually passed to the
function - just the array's address, or more precisely, a pointer to the array. This is known as PASS BY
REFERENCE. The name of an array is a pointer to the first element.
This example is similar to the one in tutorial 23, but notice the new function header and the pointer
arithmetic inside the function.
#include <stdio.h>

int addNumbers(int *fiveNumbers); /* declare function */

int main() {
int array[5];
int i;

printf("Enter 5 integers separated by spaces: ");

for(i=0 ; i<5 ; i++) {


scanf("%d", &array[i]);
}

printf("\nTheir sum is: %d\n", addNumbers(array));


return 0;
}

int addNumbers(int *fiveNumbers) { /* define function */


int sum = 0;
int i;

for(i=0 ; i<5 ; i++, fiveNumbers++) {


sum+= *fiveNumbers); /* work out the total */
}
return sum; /* return the total */
}

Notice that when you pass an int * to a function, there should be an int * declared variable in your
function header. The basic trick is to remove the [] and add a * before the array name. See the
alternative version back in the Passing Arrays to Functions section for a comparison.
Inside the for loop, the dereference operator is used to fetch the value pointed to and added onto sum. At
the end of each loop iteration, the fiveNumbers pointer is incremented to point to the next value.
Again, be careful with your pointer arithmetic and your usage of the dereference operator. You can only
get better with practice - when I first started using pointers I kept getting compilation errors!

Passing Pointers to Functions - Another Use


Recall that passing variables to function results in the creation of local variables in that function. These
local variables are destroyed when the function exits, so there was no easy way of modifying the variables
you pass into the function.
You can change all that by passing pointers to functions. For demonstrationg purposes, suppose we
wanted a function that when you pass in a variable, the function halves that variable. When the function
exits, the variable you passed in should stay halved...
#include <stdio.h>

void half(int *number); /* declare function */


void half2(int number); /* declare function */

int main() {
int i = 8;
int *ptr = &i; /* create a pointer to i */

half(ptr);
printf("The value of i is %d\n", i);

half(&i);
printf("The value of i is %d\n", i);

half2(i);
printf("The value of i is %d\n", i);

return 0;
}

void half(int *number) {


*number = *number/2;
}

void half2(int number) {


number = number/2;
}

Output:
The value of i is 4
The value of i is 2
The value of i is 2

You can see that passing ptr to half modifies i. Passing &i to half halves i again - remember that ptr
simply stores the address of i, i.e. &i.
Passing i to half2 (note the difference between half and half2) has no effect on i when program flow
returns to main.

Pointers 3
Arrays of int Pointers
Definition: a pointer is a variable that stores the memory address of another variable.
So it's possible to have an array of pointers. In other words, an array of memory addresses:
#include <stdio.h>

int main() {
int int_array[3] = {1,2,3}; /* an array of ints */

int *ptr1 = &int_array[0]; /* ptr1 stores address of int_array[0] */


int *ptr2 = &int_array[1]; /* ptr2 stores address of int_array[1] */

int *ptrs[3] = {ptr1, ptr2, &int_array[2]};

/* ptr_array is an array that stores the addresses of


int_array[0], int_array[1] and int_array[2] respectively
- notice the type of ptr_array is int * */

printf("The value of variable stored at 0x%p is %d\n", ptrs[0], *ptrs[0]);


printf("The value of variable stored at 0x%p is %d\n", ptrs[1], *ptrs[1]);
printf("The value of variable stored at 0x%p is %d\n", ptrs[2], *ptrs[2]);
return 0;
}

Output:
The value of variable stored at 0x0065FDF4 is 1
The value of variable stored at 0x0065FDF0 is 2
The value of variable stored at 0x0065FDEC is 3

I could've used a loop for the 3 printf statements, but since there are only 3, a loop is unnecessary.
Notice that ptr_array[0] returns 0x0065FDF4 - the address of int_array[0], and so *ptr_array[0]
returns the value of int_array[0] i.e. 1. The same applies to the other 2 addresses.

Arrays of char Pointers (AKA Strings)


The above example will work for floats and doubles - just replace int with float or double, and also, the
%d with %f - the float format specifier.
I previously mentioned that char * pointers can be assigned with a string constant - this is because a
char array with a null character, \0, as the last el ement is a string constant, and the name of the array is
also a pointer to the first element.
So in theory, we can have an array of strings:
#include <stdio.h>

void printStrings(char *ptr[]); /* declare function */

int main() {
char *strings[4] = { "Monday morning" , "6AM" ,
printStrings(strings);
return 0;
}

void printStrings(char *ptr[]) { /* function definition */


int i;
for(i=0 ; i<4 ; i++) {
printf("%s\n", ptr[i]);
}
}

Output:
Monday morning
6AM
Sunrise

Now, I passed the array to printStrings function here, and the array is of the type char *.
Now, we can tell printStrings to receive a pointer to the array by doing what we did before: remove the
[] and add a * before the array name. (See the top example, and its alternative version back in the
Passing Arrays to Functions section).
So void printStrings(char **ptr) would still work as the function header.
Alternatively...
But instead, if you pass a char pointer (in other words, an array element) as your argument.....
#include <stdio.h>

void printStrings2(char *ptr); /* declare function */

int main() {
char *pointerArray[4] = { "Monday morning" , "6AM" ,
printStrings2(pointerArray[0]);
printStrings2(pointerArray[1]);
printStrings2(pointerArray[2]);
printStrings2(pointerArray[3]);
return 0;
}

void printStrings2(char *ptr) { /* function definition */


printf("%s\n", ptr);
}

The output remains the same. This time you're passing an array element to the printStrings2 function,
i.e. a char *, hence the char *ptr in the argument section. Notice I had to call my function 4 times to
print out all the words.

Pointing to Functions
This is probably beyond the basic stage, but I've added this bit in for completeness... I came across
pointers to functions when I (briefly) looked at Windows Programming.
#include <stdio.h>

int add(int x, int y); /* declare function */

int main() {
int x=6, y=9;
int (*ptr)(int, int); /* declare pointer to function*/

ptr = add; /* set pointer to point to "add" function */

printf("%d plus %d equals %d.\n", x, y, (*ptr)(x,y));


/* call function using pointer */
return 0;
}

int add(int x, int y) { /* function definition */


return x+y;
}

Just remember to enclose the function pointer with brackets when declaring it. Notice that I only included
the arguments' types in the parameters in the pointer declaration. I think adding variable names in there
is optional, so this would still compile:
int (*ptr)(int x, int y);
Or even this:
int (*ptr)(int a, int b);
Also, the type of the pointer has to match that of the function it's pointing to.

Strings 1
Character Arrays Versus String Constants
Recall that each character has a unique ASCII value, String constants have double quote marks around
as mentioned in the Data Types section. A them, and can be assigned to char pointers, as
character constant is just a single character, previously mentioned. Alternatively, you can assign a
enclosed in single quote marks and can be assigned string constant to a char array - either with no size
to variables of the int or char data types. specified, or you can specify a size, but don't forget to
If you were to have an array of characters leave a space for the null character!
WITHOUT the null character as the last element, char *string_1 = "Hello";
you'd have an ordinary character array, rather than char string_2[] = "Hello";
a string constant. char string_3[6] = "Hello";

#include <stdio.h>

int main() {
int a = 'H'; /* character constants */
char b = 'i';
int i;

char array1[4] = {'B','e','e','r'}; /* a character array */

char array2[7] = {'C','o','f','f','e','e','\0'}; /* a string constant */


/* don't forget to add an extra element for the null character! */

char array3[] = "Or you can specify an unsized char array";


char *array4;
array4 = " just to be safe.";

printf("The numeric value of a is %d\n", a);


printf("The numeric value of b is %d\n\n", b);

printf("The character that a holds is %c\n", a);


printf("The character that b holds is %c\n", b);

/* printf("array1 holds %s\n", array1); is illegal - array1 NOT a string */

printf("\narray1 holds:\n\t");

for(i=0 ; i<4 ; i++) {


printf("%c", array1[i]); /* but is a character array */
}

printf("\narray2 holds:\n\t%s\n", array2);


printf("array3 and array4 holds:\n\t%s%s\n", array3, array4);
return 0;
}

Output:
The numeric value of a is 72
The numeric value of b is 105

The character that a holds is H


The character that b holds is i

array1 holds:
Beer
array2 holds:
Coffee
array3 and array4 holds:
Or you can specify an unsized char array just to be safe.

Note that you can only use the string format specifier, %s, for string constants and not char arrays.
As a reminder, \t is the tab character and \n is the widely used newline character (no doubt you knew
that already!).

Reading Strings
One possible way to read in a string is by using gets takes just one argument - a char pointer, or the
scanf. However, the problem with this, is that if name of a char array, but don't forget to declare the
you were to enter a string which contains one or array / pointer variable first! What's more, is that it
more spaces, scanf would finish reading when it automatically prints out a newline character, making
reaches a space, or if return is pressed. As a result, the output a little neater.
the string would get cut off. If you intended to use a char array, you MUST specify
So what now? We could use the gets function... its size before passing it into gets.

Writing Strings
Before I give an example, I'd like to introduce you puts is similar to gets in the way that it takes one
to puts. argument - a char pointer. This also automatically
Like with printf and scanf, if you want to use gets adds a newline character after printing out the string.
and puts you'd have to include the stdio.h header Sometimes this can be a disadvantage, so printf
file. could be used instead.
Example time:
#include <stdio.h>

int main() {
char array1[50];
char *array2;

printf("Now enter another string less than 50 characters with spaces: \n");
gets(array1);

printf("\nYou entered: ");


puts(array1);

printf("\nTry entering a string less than 50 characters, with spaces: \n");


scanf("%s", array2);

printf("\nYou entered: %s\n", array2);

return 0;
}

Output:
Now enter another string less than 50 characters with spaces:
hello world

You entered: hello world

Try entering a string less than 50 characters, with spaces:


hello world

You entered: hello

I got a warning from MSVC++ when I ran this: local variable 'array2' used without having been initialized.
It compiled ok, but when I initialized array2 with a value, the program crashed!
On the other hand, if I'd inputted a string back into array1 like this: scanf("%s", array1); it was fine,
though the string I entered still got cut off. So it's safer to use char arrays as opposed to char pointers.

Strings 2
scanf Versus gets - Round 2!
This example demonstrates another reason for avoiding scanf when inputting strings:

#include <stdio.h>

int main() {
char array1[50];
char array2[50];

printf("Try entering a string less than 50 characters, with spaces: \n");


scanf("%s", array1);

printf("\nYou entered: %s\n", array1);

printf("Now enter another string less than 50 characters with spaces: \n");
gets(array2);

printf("\nYou entered: ");


puts(array2);
return 0;
}

Output:
Try entering a string less than 50 characters, with spaces:
hello world

You entered: hello


Now enter another string less than 50 characters with spaces:

You entered: world

All I did was entered "hello world" and pressed return. The scanf captures your return press, so it tries to
read in what you entered. Because of the space, only "hello" is stored in array1.
Now for the gets. The remainder of what you inputted after the space gets read in - that includes the
return press, so the program continues and thinks you entered " world".
So scanf can do some pretty weird stuff - gets seems a safer bet!
However, you can solve this problem by FLUSHING the input stream, in other words, resetting it. Simply
call the fflush function, passing it the standard input stream, like this: fflush(stdin), and it'll solve the
problem. Here's the above example fixed:
#include <stdio.h>

int main() {
char array1[50];
char array2[50];

printf("Try entering a string less than 50 characters, with spaces: \n");


scanf("%s", array1);

printf("\nYou entered: %s\n", array1);

fflush(stdin); /* flush input stream */

printf("Now enter another string less than 50 characters with spaces: \n");
gets(array2);

printf("\nYou entered: ");


puts(array2);
return 0;
}

Other String Functions


There are two string functions I'd like to draw your Secondly, to copy a string from one place to another,
attention to, both of which require the string.h you could use the strcpy function. This takes 2
header file. arguments, both of which are char pointers. The first
First of all, if you ever wanted to find out how long a char * is where you'd like the string copied TO. The
string is without counting the number of characters second is where the string will be copied FROM.
manually, you could use the strlen function. It Obviously, you'll need to declare an array to copy a
takes one argument, which is char pointer. The string into!
number of characters in the string is returned, NOT
INCLUDING the null character.
#include <stdio.h>
#include <string.h> /* required for strlen and strcpy */

int main() {
char array1[50];
char array2[50] = "Boring!";
int size;

printf("Enter a string less than 50 characters: \n");


gets(array1);

size = strlen(array1); /* work out the length */

printf("\nYour string is %d byt%s long...\n", size, (size==1 ? "e" : "es"));


printf(" ... and contains %d characters\n\n", size);

printf("Before copying, array2[] contains \"%s\"\n", array2);


strcpy(array2, array1);

printf("Now array2[] contains \"");


puts(array2);
printf("\"\n");
return 0;
}

Output:
Enter a string less than 50 characters:
hello happy people

Your string is 18 bytes long...


... and contains 18 characters

Before copying, array2[] contains "Boring!"


Now array2[] contains "hello happy people
"

Nothing too complex about this example: the (size==1 ? "e" : "es") corrects the grammar, should the
size be 1 byte!
But look carefully inside printf - notice the \" bits. This denotes the double quote mark character in the
same way that \n denotes newline. You see, if I wrote,
printf("Now array2[] contains ""); the program would think that there were too many quote marks
in printf. So use \" every time you want to display a double quote mark.
Finally, notice that puts adds a newline when it exits - that's why there is a quote mark on the next line.

When copying a string to another array, make sure the array is big enough to hold all
the characters, including \0 - the null character.

A Word About The Null Character


Important fact: Every non zero value in a string is considered as logical TRUE. The null character is
considered logical FALSE.
This makes it possible to print out a string using loops:
#include <stdio.h>
#include <string.h>

int main() {
char array1[] = "String section is ";
char array2[] = "almost done! It's 23:40 \n";

int i = 0;

while(array1[i]!='\0') { /* \0 is treated as ONE character constant */


printf("%c", array1[i]);
i++;
}

for(i=0 ; array2[i] ; i++) { /* loop until false - \0 returns false */


printf("%c", array2[i]);
}

return 0;
}

Of course, this isn't the most efficient way of printing a string, but it demonstrates how to use the
existence of the null character at the end of a string constant.
The condition in the while loop is more readable than in the for loop. Note that the null character is
enclosed in single quote marks - this is because it's considered as a character constant and we're
evaluating character constants as we iterate through each element of the array.
In the for loop, one iteration is performed if the expression in the middle returns logical TRUE. All the
elements in character arrays return logical TRUE except for the null character. Therefore the for loop will
stop iterating once the null character (i.e. the end of the string) is reached.
One final remark is that in the second array in the example, the zero returns logical TRUE. Why? Because
it's a character constant and not an actual number.
I used unsized arrays to hold my strings in this example because I was too tired (or
lazy?!) to count the number of characters used! But I knew all I was going to do was
initialize them, then print them out. If I was going to copy one to another, or ask for
user input, I would've set some size for them.

atoi, itoa, sprintf and sscanf


Converting a String Into an int Using atoi()
Before I leave the string section, I'd like to talk #include <stdio.h>
about two useful functions that could come in handy #include <stdlib.h>
later on. Both of these require the stdlib.h header
int main() {
file.
char str1[] = "124z3yu87";
First of all, atoi. This converts strings, like "23" or
char str2[] = "-3.4";
even "29dhjds" into integers (returning 23 and 29 char *str3 = "e24";
respectively in this case). printf("str1: %d\n", atoi(str1));
atoi requires one char * argument and returns an printf("str2: %d\n", atoi(str2));
int (not a float!). printf("str3: %d\n", atoi(str3));
If the string is empty, or first character isn't a return 0;
number or a minus sign, then atoi returns 0. }
If atoi encounters a non-number character, it Output:
str1: 124
returns the number formed up until that point. str2: -3
str3: 0

Converting an int Into a String Using itoa() (NOT ANSI C)


Before I continue, I must warn you that itoa is NOT The last one is NOT the size of the array, but it's the
an ANSI function, (it's not a standard C function). BASE of your number - base 10 is the one you're
You should use sprintf to convert an int into a most likely to use. Base 2 is binary, 8 is octal and 16
string, which I'll show you in a moment. is hexadecimal.
I'll cover itoa in case you've ever wondered what it For a small lesson on bases, go back to the
does. Hexadecimal section.
itoa takes three arguments. itoa is a very useful function, which is supported by
The first one is the integer to be converted. some compilers - shame it isn't support by all, unlike
The second is a char * variable - this is where the atoi.
string is going to be stored. My program crashed if I Maybe converting a base 10 number into binary
pass in a char * variable I've already used, so I format as a string isn't so hard after all...
passed in a normal sized char array and it worked
fine.
#include <stdio.h>
#include <stdlib.h>

int main() {
char str[10]; /* MUST be big enough to hold all
the characters of your number!! */

printf("15 in binary is %s\n", itoa(15, str, 2));


printf("15 in octal is %s\n", itoa(15, str, 8));
printf("15 in decimal is %s\n", itoa(15, str, 10));
printf("15 in hex is %s\n", itoa(15, str, 16));
return 0;
}

Output:
15 in binary is 1111
15 in octal is 17
15 in decimal is 15
15 in hex is f

... itoa can be useful when you know your program doesn't have to be ANSI C only.
sprintf()
You can use this function as an alternative to itoa. The second argument is a string containing a format
It's only half as good as itoa because you can't specifier, depending on the format of the number you
specify the base of your number to be converted. want to convert.
sprintf takes three arguments. The third argument is the number you want to
The first has to be a char * variable, which means convert into a string.
you can use a char array, but make sure it's big sprintf returns the number of characters in the
enough to hold the converted number. string (not included the null character).
This example convert a few numbers into string
format, and prints out the result:
#include <stdio.h>

int main() {
char str[10]; /* MUST be big enough to hold all
the characters of your number!! */
int i;

i = sprintf(str, "%o", 15);


printf("15 in octal is %s\n", str);
printf("sprintf returns: %d\n\n", i);

i = sprintf(str, "%d", 15);


printf("15 in decimal is %s\n", str);
printf("sprintf returns: %d\n\n", i);

i = sprintf(str, "%x", 15);


printf("15 in hex is %s\n", str);
printf("sprintf returns: %d\n\n", i);

i = sprintf(str, "%f", 15.05);


printf("15.05 as a string is %s\n", str);
printf("sprintf returns: %d\n\n", i);

return 0;
}

Output:
15 in octal is 17
sprintf returns: 2

15 in decimal is 15
sprintf returns: 2

15 in hex is f
sprintf returns: 1

15.05 as a string is 15.050000


sprintf returns: 9

sscanf()
For completeness, I'm going to cover sscanf, The third is a memory location to place the result of
seeing that it's paired with sprintf. the conversion. Most of the time, you'll need the
You could've guessed that it converts a string into "address of" operator (&), then a variable name, or
various formats. you can place a char * variable here.
sscanf takes three arguments, for example: Now, if the string you pass into sscanf contains a
sscanf(str, "%d", %num); space, only the data up until that space is converted.
The first is a char * variable that contains data to sscanf returns the number of items converted.
be converted. This example performs conversions in several
The second is a string containing a format specifier formats:
that determines how the string is converted.
#include <stdio.h>

int main() {
char* ints = "20, 40, 60";
char* floats = "10.4, 24.66";
char* hex = "FF, F";

int i;
int n;
float f;
int h;
char* s;

i = sscanf(ints, "%d", &n);


printf("n: %d\n", n);
printf("sscanff returns: %d\n\n", i);

i = sscanf(floats, "%f", &f);


printf("f: %f\n", f);
printf("sscanff returns: %d\n\n", i);

i = sscanf(hex, "%x", &h);


printf("h: %d\n", h);
printf("sscanff returns: %d\n\n", i);

i = sscanf(ints, "%s", s);


printf("s: %s\n", s);
printf("sscanff returns: %d\n\n", i);

return 0;
}

Output:
n: 20
sscanff returns: 1

f: 10.400000
sscanff returns: 1

h: 255
sscanff returns: 1

s: 20,
sscanff returns: 1

Notice how sscanf ignores the comma when converting to a number (see the result for the string
variable, s).

strcpy, strncpy and strcmp


The functions in these sections require the string.h header file to be included.
They are probably past the beginner stage, so you're more than welcome to skip
these sections and return at a later date.

Using strcpy to Copy Strings


This function was given a mention a few lessons You can see how easy it was to reassign a value into
ago. It takes two arguments: a char * variable (the str. Unfortunately defining str as char str[]; will
destination string), and a constant char * value cause a compilation error.
(the source string), which will get copied into your Here's how to reassign values into char arrays:
char * variable. #include <stdio.h>
strcpy returns the value converted. #include <string.h>
One of the uses for strcpy is reassigning values to
int main() {
string variables defined as char arrays. char input_str[] = "Hello";
This example uses strings defined as char * char *output_str;
variables which get reassigned as you'd expect: output_str = strcpy(input_str, "World");
#include <stdio.h>
printf("input_str: %s\n", input_str);
int main() { printf("output_str: %s\n", output_str);
char *str;
str = "Hello"; return 0;
str = "World"; }
printf("str: %s\n", str); Output:
input_str: World
return 0; output_str: World
} The output_str part is unnecessary - I wanted to
Output: show you what gets returned from strcpy.
str: World Passing a char * defined variable into strcpy can
sometimes crash your program.

Using strncpy to Copy Strings


This function takes a three attributes. The destination and source strings, and the third attribute is the
number of characters you'd like to copy.
Now, to avoid unexpected results, pass in a sized initialized char array as the destination string. The
number of characters to copy from the source string must be less than the size of the destination char
array, otherwise random characters might get displayed.
Some examples:
#include <stdio.h>
#include <string.h>

int main() {
char str1[10] = "";
char str2[10] = "";
char str3[15] = "";
char str4[10];
char *str5;
char str6[10] = "";
char str7[10] = "123456789";

strncpy(str1, source, 9);


strncpy(str2, source, 10);
strncpy(str4, source, 9);
strncpy(str5, source, 9);
strncpy(str6 + 2, source, 7);
strncpy(str7 + 2, source, 7);

printf("%s\n", str1);
printf("%s\n", str2);
printf("%s\n", str3);
printf("%s\n", str4);
printf("%s\n", str5);
printf("%s\n", str6);
printf("%s\n", str7);

return 0;
}

Output:
www.iota-
www.iota-s¦¦www.iota-
www.iota-s
www.iota-¦¦¦www.iota-s
www.iota-
12www.iot

str1 was declared as a char array of size 10 and initialized with the empty string. We try to copy 9
characters from our source string and the expected result gets displayed by printf.
str2 was declared as a char array of size 10 and initialized with the empty string. This time we try to copy
10 characters from our source string. However, 9 is the maximum (remember all strings have the null
character, \0 at the end, which is considered as a character of the string). So printf displays something
unexpected.
Next we have str3, which was declared as a char array of size 15 and initialized with the empty string.
Again, we try to copy 10 characters from our source string, but this time we succeed, as the destination
char array is large enough.
str4 is a char array of size 10, but hasn't been initialized. Even if we copy across 9 characters, a weird
result is produced.
str5 was declared as a char * variable but wasn't initialized, but produced the same result as the str1
example.
str6 is a char array of size 10 and initialized with the empty string. In the strncpy statement you can see
that we access to the character 2 spaces away from the char pointer, and try to copy 7 letters from our
source string. This fails because the array elements of str6 are not defined.
The example of str7 is the same as str6 but because the array elements of str7 are defined, the strcpy
statement produces a better result.

Using strcmp to Compare Strings


I mentioned earlier on that the comparison You can use strcmp to perform string comparison. It
operators == (equal to) and != (not equal to) can takes two char * arguments and returns 0 if they're
only be used for integers. both equal.
So statements like if(name=="Eddie") would be However, strcmp performs a case sensitive
invalid (OK in JavaScript but not in C!). comparison, as demonstrated below:
#include <stdio.h>
#include <string.h>

int main() {
char *name = "EDDIE";
char *guess;
/* char guess[50]; also works */
int correct = 0;

printf("Enter a name in uppercase: ");

while(!correct) {
gets(guess);
if(strcmp(name, guess)==0) {
printf("Correct!\n");
correct = 1;
}
else {
printf("Try again: ");
}
}

return 0;
}

You can only exit the program by entering "EDDIE".


To perform a lowercase string comparison, use stricmp instead of strcmp but be warned: stricmp is NOT
an ANSI C so won't be supported by all C compilers.
Other useful non ANSI C functions are strlwr and strupr, which strings into lowercase and uppercase
respectively. Pass char arrays into them, if char * variables causes your program to crash.

Recall that strlen returns the length of a string you pass into it.

strstr, strchr and strrchr


Using strstr to Find Substrings
To determine if a string is contained within another string, use strstr.
This function takes two arguments: the string you want to search through, and the string you want to
search for. If it finds a substring, strstr returns a pointer to the FIRST occurrence of the substring, else it
returns a NULL pointer. Here's an example:
#include <stdio.h>
#include <string.h>

int main() {

printf("%s\n", strstr(url, "iota-six"));


printf("%s\n", strstr(url, "iota-6"));
if(strstr(url, "iota-seven")==NULL) {
printf("iota-seven not found in %s\n", url);
}

printf("Length of %s is %d\n", url, strlen(url));

return 0;
}

Output:

(null)

First of all, a string was declared an initialized (a char array would've worked in this example also).
In the first printf, we call strstr and try to search for "iota-six" in the url variable. Obviously, we
succeed, and so strstr returns a pointer to the first occurrence of "iota-six" in url. Hence, the rest of
the url string from the first character of "iota-six" onwards is displayed.
In the second printf, we search for "iota-6". strstr has no luck this time, so returns a NULL pointer.
The if statement shows how to check for a NULL pointer.
The last printf is just a reminder of how to use strlen to find the length of a string (not including the
null character, mind).

Using Pointer Arithmetic


To find the character number where the substring starts, you can do a little pointer arithmetic to calculate
the position. Remember that the first letter is considered as position zero.
#include <stdio.h>
#include <string.h>

int main() {
char *search_string = "iota-six";
char *position;
int index;

position = strstr(url, search_string);

if(position==NULL) {
printf("%s not found in %s\n", search_string, url);
}
else {
printf("Address of url: 0x%p\n", url);
printf("Address of position: 0x%p\n", position);

index = url - position; /* pointer arithmetic! */

if(index<0) {
index = -index; /* take the positive value of index */
}

printf("First occurrence of %s in %s\n", search_string, url);


printf("is at letter %d\n", index);
}

return 0;
}

Output:
Address of url: 0x00420080
Address of position: 0x0042008B

is at letter 11

In this example we search our usual string for "iota-six". Again, strstr succeeds, so returns a pointer
to the first occurrence of "iota-six".
The first two printf statements displays the hexadecimal for the addresses stored by the pointers
(remember that pointers are variables that store addresses). char variables occupy one byte each, so we
can take the difference between the two pointers and conclude that it returns the index of the "iota-six"
inside the url variable.

Using strchr and strrchr to Find Characters


These functions are similar to strstr, but instead they search for characters. They behave in the same
way - if they don't find an occurrence of the char you pass in, a NULL pointer is returned.
strchr returns a pointer to the FIRST occurrence of a char you pass in, where as strrchr returns a
pointer to the LAST occurrence, as demonstrated below:
#include <stdio.h>
#include <string.h>

int main() {
char *title = "Eddie's Basic Guide to C";
char search_char = 'e';
char *position;
int index;

position = strchr(title, search_char); /* search for first occurrence ... */

if(position==NULL) {
printf("%c not found in %s\n", search_char, title);
}
else {
index = title - position; /* pointer arithmetic to work out index */

if(index<0) {
index *= -1; /* take absolute value */
}

printf("First occurrence of %c in %s", search_char, title);


printf(" is at index %d\n", index);

position = strrchr(title, search_char); /* search for last occurrence */

index = title - position;

if(index<0) {
index *= -1;
}

printf("Last occurrence of %c in %s", search_char, title);


printf(" is at index %d\n", index);

return 0;
}

Output:
First occurrence of e in Eddie's Basic Guide to C is at index 4
Last occurrence of e in Eddie's Basic Guide to C is at index 18

We search forwards first. If we can't find a char whilst searching forwards, we can't find is backwards
either.
Try changing search_char to various values, for example, 'x', or 'C' - remember that character constants
require single quote marks around them! Try and predict your results before running the program also.
What results do you get if you set search_char to 100?

To change the sign of a variable x you can use either x = -x; or x *= -1;

Scope And Storage Specifiers


Knowing When Your Variables Are Accessible
All constants and variables have scope. In other There are 4 types of scope: block, function, file and
words, the values they hold are accessible in some program scope. Each one has its own level of scope.
parts of the program, where as in other parts, they
don't appear to exist.

Block Scope
Recall that a statement block is a group of This type of variable, is said to have BLOCK SCOPE,
statements enclosed within an opening and closing and is also known as a LOCAL VARIABLE.
curly brackets: {}. You've already used local variables before - when you
Now, if you declare a variable within a statement defined your own functions, for instance. Outside of
block, when the program exits the block, the the function definition, the variable would not be
variable will cease to exist. visible, as shown in this example:

#include <stdio.h>

void tripleInts(int a, int b); /* function declaration */

int main() {
int a = 1;
int b = 4;

tripleInts(a,b);
printf("The value of a in main is %d, the value of b is %d\n", a, b);
return 0;
}

void tripleInts(int a, int b) {/* function definition */


a *= 3;
b *= 3;
printf("The value of a in tripleInts is %d, the value of b is %d\n", a, b);
}

Output:
The value of a in tripleInts is 3, the value of b is 12
The value of a in main is 1, the value of b is 4

So despite having the same variable names, a in main differs from the a in tripleInts. The reason for
this, is that they have unique addresses, so are able to hold their own values.
There are times when your program contains a nested block, like a for loop inside main(). If you were to
declare and initialize a variable x outside the loop and then declare and initialize another variable called x
inside the loop, they will occupy up different memory slots and are considered as different variables. The
effect can be shown in this example:
#include <stdio.h>

int main() {
int x = 120;
int i;

printf("The value of x outside the for loop is %d\n", x);

for(i=0 ; i<5 ; i++) {


int x = i;
printf("The value of x inside the for loop is %d\n", x);
}

printf("The value of x outside the for loop is %d\n", x);


return 0;
}

Output:
The value of x outside the for loop is 120
The value of x inside the for loop is 0
The value of x inside the for loop is 1
The value of x inside the for loop is 2
The value of x inside the for loop is 3
The value of x inside the for loop is 4
The value of x outside the for loop is 120
Function Scope
This type of scope only applies to goto label names. You can't have the same label name inside a function.
However, you can have the same label name in different functions like this:
#include <stdio.h>

int powers(int x, int powerNum);

int main() {
int x,p;
char choice;

start:
printf("\nEnter an integer: ");
scanf("%d", &x);

printf("\nEnter a integer power: ");


scanf("%d", &p);

printf("\n%d to the power of %d is %d\n", x,p,powers(x,p));

printf("\nDo it again?! Enter Y or N: ");

scanf("%s",&choice);

/* (choice=='y' || choice=='Y') ? goto start : goto finish; DOESN'T WORK!!! */

if(choice=='y' || choice=='Y') {
goto start;
}
else {
goto finish;
}

finish:

printf("\nGoodbye!\n");
return 0;
}

int powers(int x, int powerNum) {


int temp = x;
start:

powerNum--;

if(powerNum==0) {
goto finish; /* I'd prefer to use a for loop instead! */
}

x *= temp;

goto start; /* I've heard rumours that goto can be unreliable */

finish:
return x;
}

Output:
Enter an integer: 2

Enter a integer power: 5


2 to the power of 5 is 32

Do it again?! Enter Y or N: y

Enter an integer: 1

Enter a integer power: 6


1 to the power of 6 is 1

Do it again?! Enter Y or N: n
Goodbye!

Program Scope
If you want to avoid passing arguments to your functions you can declare your variables outside any
function blocks. Such variables are sometimes known as GLOBAL VARIABLES. Their value can be accessed
from anywhere within the ENTIRE program. Take this example:
#include <stdio.h>

int x = 12;

void anotherFunction();

int main() {
printf("The value of x in main is %d\n", x);
int x = 38;
printf("Now x is %d\n", x);
anotherFunction();
return 0;
}

void anotherFunction() {
printf("The value of x outside of main is %d\n", x);
}

Output:
The value of x in main is 12
Now x is 38
The value of x outside of main is 12

The x declared in main is a local variable - you can see that the global one still exists and is accessed by
anotherFunction.

File Scope
FILE SCOPE is when a variable is only accessible This makes it impossible for x to be accessible by
until the end of the file. other files, other than the one it's declared and
A variable with file scope is a global variable initialized in.
declared with the the static keyword before the This is useful for when you come to write your own
data type, like this: header files and function prototypes as it can prevent
static int x = 15; compilation errors and potential bugs.

Summary
Let's recap:
1. Variables with block scope (variables declared in a block, i.e. local variables) are the least
accessible, as they are visible between an opening curly bracket and a closing one.
2. Variables with function scope (goto labels in this case) are the next least accessible, as they are
visible in a whole function.
3. Variables with file scope (global variables with the static specifier) are the second most
accessible, as they are visible in the whole file.
4. Finally, variables with program scope (variables declared outside any blocks, i.e. global variables)
are always accessible throughout the program.

Storage Specifiers
Storage specifiers give you control over how your The register specifier supposedly improves the
variables are stored. There are four of them, and efficiency of your program. When you declare a
they should be placed before your variable's data variable, like I've said many times before, space in
type. the computer's memory is set aside for it. The
The auto specifier is the default one, which is why computer's central processing unit (CPU) has a few
you wouldn't really use it. It gives the variable block registers which can also take variables in. For the
scope i.e. it makes it a local variable. computer, accessing a variable stored in the registers
The extern specifier is used when you've declared is quicker as opposed to the computer's memory.
global variables elsewhere in a separate file for your The downside is that it is not 100% guaranteed that a
program. Only global variables can be declared with variable declared with the register specifier is going
the extern specifier. When the compiler sees the to be stored in a register. And you cannot use the
extern keyword, it'll look in another file for the "Address of" operator with the variable (like in scanf)
definition of the variable. This can also be used for because it's not stored in the memory and wouldn't
function, which we'll see later on. have an address.
The static specifier was mention in the File Scope So when would you want to use the register
section, and can be used on local or global variables specifier? When you have a variable that changes its
to give them permanent duration for that file only. value often. Like, for example, in a for loop when the
In other words, the memory space reserved for the value changes after each iteration.
variable is not erased once the variable is out of its
scope.

enum And typedef


The enum Keyword
enum is the abbreviation for ENUMERATE, and we You can name your constants in a weird order if you
can use this keyword to declare and initialize a really wanted...
sequence of integer constants. Here's an example: #include <stdio.h>
enum colors {RED, YELLOW, GREEN, BLUE};
I've made the constant names uppercase, but you int main() {
can name them which ever way you want. enum {RED=5, YELLOW, GREEN=4, BLUE};
Here, colors is the name given to the set of
printf("RED = %d\n", RED);
constants - the name is optional. Now, if you don't printf("YELLOW = %d\n", YELLOW);
assign a value to a constant, the default value for printf("GREEN = %d\n", GREEN);
the first one in the list - RED in our case, has the printf("BLUE = %d\n", BLUE);
value of 0. The rest of the undefined constants have return 0;
a value 1 more than the one before, so in our case, }
YELLOW is 1, GREEN is 2 and BLUE is 3. Output:
But you can assign values if you wanted to: RED = 5
enum colors { YELLOW = 6
RED=1, YELLOW, GREEN=6, BLUE }; GREEN = 4
Now RED=1, YELLOW=2, GREEN=6 and BLUE=7. BLUE = 5
The main advantage of enum is that if you don't ... And enum would still work, though it could get a
initialize your constants, each one would have a little confusing!
unique value. The first would be zero and the rest
would then count upwards.

enum Variables
Enumerated constants are integers, so programs Declaring enumerated data types can also be done
with statements like x = RED; would still compile. after the list of constants, like this:
But you can also create your own enumerated data enum colors {BLACK, WHITE}, bg, fg;
types, for example, colors (see above) is now This makes bg and fg variables of the enumerated
considered an enumerated data type. So you can data type, colors. Statements like bg = BLACK; can
say: now be used.
enum colors background; However, there are drawbacks to using enumerated
This declares a variable called background, which is data typed variables, as opposed to say, integers.
of the enumerated data type, colors. This example looks ok, but has an error:

#include <stdio.h>

int main() {
enum colors {RED=1, YELLOW, GREEN, BROWN, BLUE, PINK, BLACK};

enum colors c;
c = RED
printf("I potted a RED ball, which is %d point.\n", c);
c = RED + GREEN;
printf("Then I potted the GREEN, which is %d points.\n", GREEN);
printf("So in total, I scored %d points.\n", c);

return 0;
}

This program supposedly describes a game of snooker - a popular sport in the UK, where players take
turns to pot balls of various points.
The red ball is worth 1 point, which is why I assigned RED a value of 1. Yellow through to black are worth 2
to 7 respectively, so I don't need to specify them, because their values are one more than the previous.
Then I declare an enum colors variable, c, which I then assign the RED constant.
Now for the printf: you can use %d with enumerated data types - they're simply integers in disguise.
Here's where MSVC++ complains: c = RED + GREEN;
It might looks correct, but on the right hand side we're doing RED + GREEN, i.e. 1+3 which returns 4 -
which is of the type int. The left hand side of the assignment operator is of the type enum colors, so we
have two choices: either declare c to be an int, or we can cast the right hand side:
c = enum colors(RED + GREEN);
- In either case, the program will compile, with output:
I potted a RED ball, which is 1 point.
Then I potted the GREEN, which is 3 points.
So in total, I scored 4 points.

I'd personally declare c to be an int, so that you could use statements like: c += GREEN;

Using Type Definitions


Writing enum colors before an enumerated variable You can call your new "types" anything you want. Just
can be a little tedious. We can simplify things a little remember the basic form of a type definition: the
by using the typedef keyword. typedef keyword, followed by the type you want to
As its name implies, we can define our own types. abbreviate, then the new type at the end. It can be of
So for our colors example, we can define a new any case - I use uppercase to make it stand out.
type called COLOR like this: #include <stdio.h>
typedef enum colors COLOR;
typedef statements could be placed anywhere in typedef unsigned short int USHORT;
typedef char* STRING;
your program - I tend to group them all before
main. Now, every time the compiler sees COLOR, it'll int main() {
know that you mean enum colors. Let's declare c USHORT i = 2001;
again: STRING c = "Year";
COLOR c = RED;
- Much simpler! printf("%s %d\n", c, i);
And we're not restricted to just enum data types. We
can simplify the various int types: return 0;
typedef unsigned short int USHORT; }
typedef unsigned long int ULONG; This prints out: Year 2001
Notice how you can use pointers in typedef
statements. Always remember to use typedef before
you use your new type in the program!

Structs 1
What is a struct?
A struct (short for STRUCTURE), is a collection of Variables in a struct are called MEMBERS or FIELDS,
variables of different types. Structures are and are accessed by their name.
sometimes referred to as ABSTRACT DATA TYPES, Variables in an array are called ELEMENTS, and are
or ADTs for short. accessed using square brackets an an index.
We already know how to store a group of variables
of the same type using arrays.

Declaring a struct
Declaring a struct requires the struct keyword, human is now a structure type, with three fields: name,
followed by a name. Then you declare your expressed as a string, an integer age and a floating
collection of variables between a pair of curly point height.
brackets. For example: You can put whatever data types you want. And
struct human { you're not limited to normal variables either - arrays
char *name; and pointers can also go into a struct, though, you
int age;
must specify an array size.
float height;
}; You can NOT use the assignment operator with the
/* don't forget this semi colon!!!! */ struct declaration.
It's best to declare your struct before main. NOTE: The size of a struct is the sum of the sizes of
all the variables it holds.

Declaring Structure Variables


Like with enum, you can insert a list of variables So instead, you can write this inside main:
after the end bracket like this: struct album CD1, CD2, CD3;
struct album { Or better still, declare your struct and write:
char *name; typedef struct album Album;
char *artist; ... then inside main:
int numTracks; Album CD1, CD2, CD3;
} CD1, CD2, CD3; Try and group all your typedef statements outside
This declares three variables of the struct album main - it makes the code look neater and easier to
type. maintain.
But if album was declared outside main, the three
variables will be global variables.

Initializing Structure Variables


Now that you know how to declare structure To reference an individual field, you use the DOT
variables, there are two ways to initialize them: all OPERATOR to separate the struct variable name and
the fields in one statement, or one field at a time. the field name.
To initialize all fields in one statement, you declare You can use the dot operator to initialize each field
your variable as usual, but assign it a list of individually:
variables enclosed in brackets, like this: struct human TR;
struct human TR = {"Tony", 12, 1.5}; TR.name = "Tony";
This is similar to the method of initializing arrays. TR.age = 12;
Now the struct human variable, TR has all three TR.height = 1.5;
fields initialized: the name field holds the string, To access each field, use the dot operator again.
"Tony", the age field holds the integer, 12, and the For example, TR.age will return 12.
height is 1.5.

Advantages of char*name Over charname[50]


When I first encountered structs I used a sized char TR.name = "Tony" won't work, simply because the
array to store strings. only way of assigning a string into an array is when
Suppose I redefine human: you declare an array: char name[5] = "Tony";
struct human { Recall that TR.name is actually a char pointer, but it's
char name[50]; an R-value in this case. In other words, assigning a
int age; value into it wouldn't work, as it wasn't declared as a
float height;
char *. But...
};
TR.name[0] = 'T';
The first disadvantage, is that the name array must TR.name[1] = 'o';
have a size big enough to store any string I was TR.name[2] = 'n';
going to use. TR.name[3] = 'y';
Secondly, the only (obvious) way to initialize a TR.name[4] = '\0';
string field, is to do it all at once: ... works because the elements of the name array are
struct human TR = {"Tony", 12, 1.5}; L-values.
If human was defined with char *name, you could use
TR.name = "Tony"; because pointers are L-values:
remember that strings are considered to be of type
char * as well.
Arrays of Structured Variables
Like with the usual data types, you can store a group of similar typed variables in an array.
The method of declaring an array is the same as before, but initializing your elements isn't as simple as
first thought...
#include <stdio.h>

typedef struct robot ROBOT;

struct robot {
char *name;
int energy;
};

int main() {
int i;

ROBOT robots[3];

robots[0].name = "Lunar Lee";


robots[0].energy = 50;
robots[1].name = "Planetary Pete";
robots[1].energy = 20;
robots[2].name = "Martian Matt";
robots[2].energy = 30;

/* robots[0] = {"Lunar Lee", 50}; WON'T WORK, BUT HERE'S ANOTHER WAY...

ROBOT robots[3] = { {"Lunar Lee", 50},


{"Planetary Pete", 20},
{"Martian Matt", 30} }; */

for(i=0 ; i<3 ; i++) {


printf("Robot %d is called %s ", i, robots[i].name);
printf("and has %d units of energy.\n", robots[i].energy);
}
return 0;
}

Output:
Robot 0 is called Lunar Lee and has 50 units of energy.
Robot 1 is called Planetary Pete and has 20 units of energy.
Robot 2 is called Martian Matt and has 30 units of energy.

Instinctively, I first declared my array of robots, then I tried initializing each element one by one like this:
robots[0] = {"Lunar Lee", 50};
Unfortunately, MSVC++ complained, and so I initialized each name and energy field separately for each
robot, as shown above.
There is a quicker way of initialization, as shown in the commented section. It involves initializing the
entire array all at once. Notice how I separated each array element with a line break for clarity. Also note
that a group of fields must be enclosed in brackets as well: {"Lunar Lee", 50}, for example.

Structs 2
Using an Array as a Field
Just thought I'll show you an example of using an array as a field (apart from char arrays!)...

#include <stdio.h>

struct human {
char *name;
int age[2];
};
struct human {
char *name;
int age[2];
};

int main() {
struct human user;
int m;

printf("What is your name? ");


gets(user.name);

printf("\nHow old are you?\nYears: ");


scanf("%d", &user.age[0]);

printf("\nMonths: ");
scanf("%d", &user.age[1]);

m = user.age[1];

printf("\nYour name is %s and you are %d years ", user.name, user.age[0]);


printf("and %d %s old.\n", m, (m==1 ? "month" : "months"));

return 0;
}

Output will depend on what you entered.


I must confess things didn't go according to plan: I declared user to be a global variable by placing it after
the definition of a struct human, but MSVC++ didn't like it (something about assertion failure whatever
that meant!). So I declared user inside main.
gets is used to get your name - we pass a char * into gets, which is ok here.
Then 2 scanfs are used to get your age: first the years, then the months. The program stores these
values in the age array.
The rest is pretty much self explanatory: the (m==1 ? "month" : "months") part basically does a
grammar correction.

Pointing to Structures and Using the Arrow Operator ->


Like with arrays, you can create pointers to Your compiler might complain if you try and declare
structures. This time, the pointer stores the memory variables after creating pointers, so it's best if you
address of a structure variable. declare all your variables at the beginning of main,
Declaring you pointer follows along the same lines rather than "on the fly" e.g. halfway through main.
as with arrays, for example, if user was of type Now that you've created a pointer, you now access
HUMAN (where HUMAN is struct human): fields using the arrow operator, which is made up of
HUMAN *human_ptr = &user; two characters: a hyphen, then the greater than sign:
Or: ->. This replaces the dot operator, but other than
HUMAN *human_ptr; that, accessing structure fields is similar:
human_ptr = &user; human_ptr->name = "Martin";
- Both of these would do the trick. However, make Is the equivalent of:
sure you've declared all your program variables user.name = "Martin";
before initializing pointers, else you'd encounter Here's the last example rewritten using pointers:
problems later on!
#include <stdio.h>

typedef struct human HUMAN;

struct human {
char name[50];
int age[2];
};

int main() {
HUMAN user;
HUMAN *human_ptr;
int m; /* Declare m here... */

human_ptr = &user;
printf("What is your name? ");
gets(human_ptr->name);

printf("\nHow old are you?\nYears: ");


scanf("%d", &(human_ptr->age[0]));

printf("\nMonths: ");
scanf("%d", &(human_ptr->age[1]));

/* int m; Declaring m here caused a compilation error!! */

m = human_ptr->age[1];

printf("\nYour name is %s and you are ", human_ptr->name);


printf("%d years and ", human_ptr->age[0]);
printf("%d %s old.\n", m, (m==1 ? "month" : "months"));

return 0;
}

If you compare this example to the previous, you'll notice how similar it looks. The only difference is the
pointer to user, human_ptr. Every occurrence of user. has been replaced by
human_ptr-> , as well as a few brackets added for clarity.

Passing Structures to Functions


This is similar to passing arrays to functions. Passing pointers is a better way, but for
In the function declaration you need to specify the demonstration purposes, here's a function that
structure's type, then a name and any other expects a ROBOT variable and displays some info:
arguments.
#include <stdio.h>

typedef struct robot ROBOT;

struct robot {
char *name;
int energy;
int IQ;
float velocity;
};

void info(ROBOT r); /* declare function */

int main() {
ROBOT r1 = {"Earthling Ed", 100, 231, 4.1}; /* initialize 2 ROBOTs */
ROBOT r2 = {"Toxic Tom", 150, 254, 2.5};

info(r1);
info(r2);

return 0;
}

void info(ROBOT r) {
printf("%s has %d units of energy, an IQ of %d...\n", r.name, r.energy, r.IQ);
printf("... and a velocity of %0.1f metres per second.\n", r.velocity);
}

Output:
Earthling Ed has 100 units of energy, an IQ of 231...
... and a velocity of 4.1 metres per second.
Toxic Tom has 150 units of energy, an IQ of 254...
... and a velocity of 2.5 metres per second.

Notice how I moved the function declaration below the typedef statement, since I used the defined type,
ROBOT, in the function's argument section.
info returns nothing, hence the void data type, and expects a ROBOT variable. r is a local variable that is
created whenever info is called.
The %0.1f format specifier in the second printf displays the velocity correct to 1 decimal place. The
zero is the minimum field width (the least number of spaces the number will occupy when displayed on
screen).

Structs 3
Passing Pointers to Structures to Functions
Now suppose we want to create a function that modifies a structure. Now we'll turn to pointers...
#include <stdio.h>

typedef struct robot ROBOT;

struct robot {
char *name;
int energy;
int IQ;
float velocity;
};

void info(ROBOT r); /* declare functions */


void harm(ROBOT *r);

int main() {
ROBOT r1 = {"Martian Martin", 140, 213, 5.1};
ROBOT r2 = {"Planetary Pete", 170, 309, 4.5};

ROBOT *ptr_r1 = &r1;

printf("Before damage: \n\n");

info(r1);
info(r2);

harm(ptr_r1);
harm(&r2);

printf("\nAfter damage: \n\n");

info(r1);
info(r2);

return 0;
}

void info(ROBOT r) {
printf("%s: Energy: %d IQ: %d ", r.name, r.energy, r.IQ);
printf("Velocity: %0.1f\n", r.velocity);
}

void harm(ROBOT *r) {


r->energy -= 20;
r->velocity -= 1;
}

Output:
Before damage:

Martian Martin: Energy: 140 IQ: 213 Velocity: 5.1


Planetary Pete: Energy: 170 IQ: 309 Velocity: 4.5

After damage:

Martian Martin: Energy: 120 IQ: 213 Velocity: 4.1


Planetary Pete: Energy: 150 IQ: 309 Velocity: 3.5
I would like to take this opportunity to apologize for the unimaginative names!!!
The info function is almost the same as before - just modified the way it displayed the information. I had
to use two separate printfs because using one distorted the web page!
harm expects a ROBOT pointer as an argument. Then it takes the ROBOT passed in, and decreases its
energy by 20, and its velocity by 1 (that should teach it a lesson).
You can see by the output that the fields have been modified when I called harm using the two different
methods: passing a pointer to r1 I created earlier, or simply passing the address of r2.

Structures Within Structures


You can have fields of any data type in a structure, as well as pointers and arrays AND other structures.
You must create a struct before you use it in another struct, but declaring the field is similar to
declaring an array.
#include <stdio.h>

typedef struct weapon WEAPON;


typedef struct robot ROBOT;

struct weapon {
int ammo;
char *name;
int damage;
};

struct robot {
WEAPON weapon1; /* struct within a struct */
char *name;
int energy;
};

int main() {
ROBOT boss = { {100, /* boss.weapon1.ammo */
"Laser Gun", /* boss.weapon1.name */
25}, /* boss.weapon1.damage */
"Krypton Kathy", /* boss.name */
250}; /* boss.energy */

ROBOT *ptr1;
WEAPON *ptr2;

/*boss.weapon1.ammo = 100; alternative initialization - notice I had to put


boss.weapon1.name = "Laser Gun"; this in AFTER declaring the 2 pointers above
boss.weapon1.damage = 25;
boss.name = "Krypton Kathy";
boss.energy = 250;*/

ptr1 = &boss;
ptr2 = &boss.weapon1;

printf("You have encountered %s.\n", ptr1->name);


printf("She has %d units of energy.\n", ptr1->energy);
printf("Her weapon is the deadly %s.\n", ptr2->name);
printf("Each hit takes up to %d units of energy off you.\n", ptr2->damage);
printf("She has %d shots left.\n", ptr1->weapon1.ammo);
printf("You have 10 units of energy left. Situation critical.\n");
printf("Abort mission.\n");

return 0;
}

Output:
You have encountered Krypton Kathy.
She has 250 units of energy.
Her weapon is the deadly Laser Gun.
Each hit takes up to 25 units of energy off you.
She has 100 shots left.
You have 10 units of energy left. Situation critical.
Abort mission.
In the definition of struct robot, you can see that I've used a struct weapon variable as one of the
fields. struct weapon must been defined before struct robot, otherwise your compiler will complain
about an undefined struct.
Inside main, I've declared and initialized a ROBOT variable. Look closely and you'll see that there are 2
brackets surrounding the first three items - this is because the first three items belong to the struct
weapon field.
After that, I declared two pointers - one that points to the boss and the other points to the weapon1 field
of boss.
The first four printf statements make use of ptr1 and ptr2 to access certain fields, but in the fifth,
notice that it's ptr1->weapon1.ammo and not ptr1->weapon1->ammo. This is because weapon1 is not a
pointer to a struct weapon, but an actual struct weapon field, hence the dot operator.

Unions
What is a union?
A union, is a collection of variables of different You can picture a union as like a chunk of memory
types, just like a structure. However, with unions, that is used to store variables of different types. Once
you can only store information in one field at any a new value is assigned to a field, the existing data is
one time. wiped over with the new data.

Declaring a union
Declaring a union is exactly the same as declaring a Once again, you can use a typedef statement to
struct, except you use the union keyword: simply the declaration of union variables.
union human { The size of an union is the size of its largest field.
char *name; This is because a sufficient number of bytes must be
int age; reserved for the largest sized field.
float height;
}; /* don't forget this semi colon!!!! */

Initializing Unions
Now, this is where things get a little different to structures. Like I said before, with a union, fields share
the same memory space, so fresh data replaces any existing data. This example demonstrates what
happens if you initialize all the data for a union variable, all at once:

#include <stdio.h>

typedef struct robot1 ROBOT1;


typedef union robot2 ROBOT2;

struct robot1 {
int ammo;
int energy;
};

union robot2 {
int ammo;
int energy;
};

int main() {
ROBOT1 red = {10,200};
/* ROBOT2 blue = {15,100}; DOESN'T WORK WITH UNIONS */

ROBOT2 blue;
blue.ammo = 15;
blue.energy = 100;

printf("The red robot has %d ammo ", red.ammo);


printf("and %d units of energy.\n\n", red.energy);
printf("The blue robot has %d ammo ", blue.ammo);
printf("and %d units of energy\n.", blue.energy);

return 0;
}

Output:
The red robot has 10 ammo and 200 units of energy.

The blue robot has 100 ammo and 100 units of energy.

First notice how similar the declaration of a union is to a struct.


Things get a little different inside main. You can't initialize fields of a union variable all at once - try
removing the correct initialization above and see what your compiler says. So I initialized each field
separately...
The first printf statement displays the expected for the struct version of our robot.
The second printf shows you that the program has overwritten data in the ammo field with data of the
energy field - this is how unions work. All fields share the same address, where as with structs, each field
has its own address.
This example is similar to the last, except I used printf before initializing the energy field of the union:

#include <stdio.h>

typedef struct robot1 ROBOT1;


typedef union robot2 ROBOT2;

struct robot1 {
int ammo;
int energy;
};

union robot2 {
int ammo;
int energy;
};

int main() {
ROBOT1 red = {10,200};
ROBOT2 blue;

printf("The red robot has %d ammo ", red.ammo);


printf("and %d units of energy.\n\n", red.energy);

blue.ammo = 15;
printf("The blue robot has %d ammo", blue.ammo);

blue.energy = 100;
printf(" and %d units of energy.", blue.energy);

return 0;
}

Output:
The red robot has 10 ammo and 200 units of energy.

The blue robot has 15 ammo and 100 units of energy.

Data in the energy field has still overwritten the ammo field though - rearranging the printfs has changed
made the outcome different from that of the last example.

Arrays of Union Variables


The concept is the same as that of structs. However, because of the problem of new data overwriting
existing data in the other fields, the struct version of the following example won't work if you simply
replace all instances of struct with union.

#include <stdio.h>

typedef union robot ROBOT;


union robot {
char *name;
int energy;
};

int main() {
int i;

ROBOT robots[3];

robots[0].name = "Lunar Lee";


robots[0].energy = 50;
robots[1].name = "Planetary Pete";
robots[1].energy = 20;
robots[2].name = "Martian Matt";
robots[2].energy = 30;

for(i=0 ; i<3 ; i++) {


/*printf("Robot %d is called %s ", i, robots[i].name);*/
printf("and has %d units of energy.\n", robots[i].energy);
}
return 0;
}

Output:
and has 50 units of energy.
and has 20 units of energy.
and has 30 units of energy.

The reason why I commented out the printf that displays the name is because I initialized everything at
once. As a consequence, by the time the program reaches the for loop the union holds an int variable,
rather than a char *. In general, my program crashes whenever an int is passed to the string format
specifier, %s - other compilers might produce a different result.

Unions Inside Structures


I can't see any obvioud reasons why one might use unions, but here's a case when they could be useful.
Suppose we want a field of a structure to contain a string or an integer, depending on what the user
specifies. Take this example:
#include <stdio.h>

struct choice {
union {
char *name;
int age;
};
int number;
};

int main() {
struct choice example;
char d[4];

printf("You can enter a name OR an age.\n");


printf("Would you like to enter a name? (Yes or No) : ");
gets(d);

if(d[0]=='y' || d[0]=='Y') {
printf("\nWhat's your name? ");
gets(example.name);
}
else {
printf("\nWhat's your age? ");
scanf("%d", &example.age);
}

printf("\nWhat's you favourite number? ");


scanf("%d", &example.number);
if(d[0]=='y' || d[0]=='Y') {
printf("\nYour name is %s ", example.name);
}
else {
printf("\nYour age is %d ", example.age);
}

printf("and your favourite number is %d.\n", example.number);

printf("The size of the struct is %d\n", sizeof(example));


return 0;
}

Output varies on what you entered, but I'll run through the program:
You can have an INLINE declaration of union within a struct declaration (inline is a term meaning
"embedded within"). So the first field of choice can either be a char * or an int.
Once inside main, a struct choice variable called example is declared, as well as a sized char array
called d.
The used is told to make a Yes / No choice - the response gets stored into d.
Now the program checks to see if the first character of d is Y or y - if so, the user can enter a name, else
an age. Entering a favourite number is compulsory.
Then the program prints out what the user has entered.
The last printf displays the size of the struct: 8 bytes in all cases.

Final Remarks on Unions


Firstly, nested unions are possibly, but are a little Pointing to unions, passing unions to functions and
pointless. One union has the same memory space passing pointers to unions to function are all done in
for all fields. If one of your fields is a union, that the same way as that of structs.
union would also let its fields share memory space -
the same memory space reserved for the first
union!!

File Input and Output 1


Streams Revisited and the FILE Structure
Cast your mind back to the Standard Input and In this section, we'll be reading data from a file, not
Output section when I talked about stdin and from stdin.
stdout. In stdio.h there is a defined structure called FILE.
In C, stdin is the standard input file stream and For file input and output, we usually create variables
refers to the keyboard. of type FILE * to point to a file located on the
scanf is the equivalent of fscanf, with the stream computer.
set to stdin by default. The same applies to the We could pass a FILE pointer into an input or output
other input functions we've encountered: getc and function, for example, fscanf.
gets are fgetc and fgets with the input stream set
to stdin.

Using fopen()
But first things first, we have to open a file to be The second argument is another char *, and
able to do anything else with it. determines how the file is opened by your program.
For this, we use fopen. This function takes two There are 12 different values that could be used, and
arguments - the first one is the path to your file, I will run through them throughout the File Input and
including the filename. So if your file sits in the Output sections.
same directory as your C source file, you can simply Finally, fopen returns a FILE pointer if the file was
enter the filename in here - this is probably the one opened successfully, else it returns NULL.
you'll use most.
Using fclose()
When you've finished with a file, it's best if you Simply pass it a FILE pointer, but be warned, don't
closed it - seems logical enough! pass a NULL pointer (it points to nothing), or your
program might crash.

Opening Files for Reading Only


Firstly, a text file is a file that you can open and For these tutorials, we're going to be looking at
read its contents visually - for example, C source standard text files. If you wanted to open a binary
files, .txt files, HTML etc - anything that looks "neat" file, simply put a b at the end of the second argument
in Notepad. of fopen.
A binary file is a file that is written in machine code To open a text file for reading only, pass "r" as the
- usually seen as a mass of weird characters in second argument of fopen, as demonstrated in this
Notepad! Examples are bitmaps, executables etc. example:
#include <stdio.h>

int main() {
FILE *file; /* declare a FILE pointer */

file = fopen("data/hello.txt", "r"); /* open a text file for reading */

if(file==NULL) {
printf("Error: can't open file.\n");
/* fclose(file); DON'T PASS A NULL POINTER TO fclose !! */
return 1;
}
else {
printf("File opened. Now closing it...\n");
fclose(file);
return 0;
}
}

Now, I created a file earlier in Notepad, named it "hello.txt" and put it in a folder called "data", which lives
in the folder where my source code is kept.
I could've simply moved the file into the same directory as the source code, but I just wanted to
demonstrate what you'd do if it was in a different directory.
Inside main, I created a FILE * called file. Afterwards, I call the fopen function, passing it the path to
my text file, as well as "r" to let the program know that I'm only intending to read from the file.
Notice I assigned the function call to file. If the file was successfully opened, file would point to that
file, else it'll point to nothing (a pointer that points to nothing is called a NULL POINTER).
Then I perform a check to see if file is a NULL pointer: if(file==NULL). If so, display an error message,
and quit the program by returning a non-zero value to signify that an error has occurred.
If file is not a NULL pointer, display a success message and close the file. Then quit the program by
returning 0 to show that the program terminated without errors.

Creating Files for Writing Only


To create a text file for writing only, pass "w" into fopen as the second argument.
This example follows along the same lines as the previous:
#include <stdio.h>

int main() {
FILE *file; /* declare a FILE pointer */

file = fopen("data/writing.txt", "w"); /* create a text file for writing */

if(file==NULL) {
printf("Error: can't create file.\n");
/* fclose(file); DON'T PASS A NULL POINTER TO fclose !! */
return 1;
}
else {
printf("File created. Now closing it...\n");
fclose(file);
return 0;
}
}

Now, if I went into my data folder, I could see a text file called "writing" was created. However, if my data
folder didn't exist, an error would occur.

Creating a file that already exists wipes all the data from that file!

Other Options When Opening Files


There are 4 other options I'd like to mention: "a+" will either create or open a text file for
"a" lets you open a text file for appending - i.e. add appending.
data to the end of the current text. Add a "b" to the end if you want to use binary files
"r+" will open a text file to read from or write to. instead of text files, like this:
"w+" will create a text file to read from or write to. "rb", "wb", "ab", "r+b", "w+b", "a+b".

fgetc()
First, we will look at a function that allows us to We usually use EOF to determine when we've finished
read one character at a time. reading from a file.
fgetc requires one argument - a stream. This could For the next example, I created a text file called
either be your FILE pointer OR stdin. Writing numbers.txt and placed it in the same directory as
fgetc(stdin) is the equivalent of writing getc(). my C program. Here are its contents:
one
We're going to be passing a FILE pointer to it.
two
fgetc returns the int that denotes a character from three
the file. For example, if the first character in the file
was "A", fgetc would return 65. four
five
After returning an int, the FILE pointer is moved to
Here's a demonstration the use of fgetc:
point to the next character. Should the pointer be
moved beyond the last character, fgetc returns
EOF - the END OF FILE constant.
#include <stdio.h>

int main() {
char c; /* declare a char variable */
FILE *file; /* declare a FILE pointer */

file = fopen("numbers.txt", "r"); /* open a text file for reading */

if(file==NULL) {
printf("Error: can't open file.\n");
/* fclose(file); DON'T PASS A NULL POINTER TO fclose !! */
return 1;
}
else {
printf("File opened successfully. Contents:\n\n");

while(1) { /* keep looping... */


c = fgetc(file);
if(c!=EOF) {
printf("%c", c); /* print the file one character at a time */
}
else {
break; /* ...break when EOF is reached */
}
}

printf("\n\nNow closing file...\n");


fclose(file);
return 0;
}
}
The output is as expected:
File opened successfully. Contents:

one
two
three

four
five

Now closing file...

If you get an error, check that your text file is in the right place!
Most of the program was covered above, but the while loop iterates through the contents of the file until
the end of the file is reached, reading and printing out one character at a time. Notice how the line breaks
in my file causes printf to print a line break - they have the ASCII code of 10.

File Input and Output 2


feof()
Here's a function you'll be using in the future. You I'll be using this function in the next section but in the
pass it a FILE pointer, and if you've reached the meantime, There are a few more functions I'd like to
end of the file, feof returns 1, else it returns 0. cover...

fgets()
Reading one character at a time can be a little You can't use an !=EOF check here, as we're not
inefficient, so we can use fgets to read 1 line at a reading one character at a time (but you can use
time. feof).
fgets takes three arguments. The first, has to be a For this example, I made a file called numbers2.txt
char * - the name of a sized char array would work in Notepad:
too. The second is an int - the maximum number 111 222 333
444 555 666
of characters read per line. 777 888 999
The third and last, is a stream - a FILE * for Although it's not obvious at first, I put tabs in the last
example (try it with stdin and see what happens). line.
fgets returns NULL if the end of the file is reached,
else it returns a char *.

#include <stdio.h>

int main() {
char c[10]; /* declare a char array */
FILE *file; /* declare a FILE pointer */

file = fopen("numbers2.txt", "r"); /* open a text file for reading */

if(file==NULL) {
printf("Error: can't open file.\n");
/* fclose(file); DON'T PASS A NULL POINTER TO fclose !! */
return 1;
}
else {
printf("File opened successfully. Contents:\n\n");

while(fgets(c, 10, file)!=NULL) { /* keep looping until NULL pointer... */


printf("String: %s", c); /* print the file one line at a time */
}

printf("\n\nNow closing file...\n");


fclose(file);
return 0;
}
}

Output:
File opened successfully. Contents:

String: 111 222 3String: 33


String: 444 555 6String: 66
String: 777 888 9String: 99

Now closing file...

The main area of focus is the while loop - notice how I performed the check for the return of a NULL
pointer. Remember that passing in char * variable, c as the first argument assigns the line read into c,
which is printed off by printf. I specified a maximum number of characters to be 10 - I knew the number
of characters per line in my text file is more than this, but I wanted to show that fgets reads 10
characters at a time in this case.
Notice how fgets returns when the newline character is reached - this would explain why 444 and 777
follow the word "String". Also, the tab character, \t, is treated as one character.

atoi Revisited
Notice how I've slipped in an extra lesson after the You could put each number on a separate line like
string section! I thought the atoi function would be this:
especially useful when reading numerical data from 6
7
an external text file. 8
So far, all the information extracted was returned as 9
strings. If our text file contained numbers, we could 10
use atoi to convert them into integer format for - I put this into a file called numbers3.txt so let's get
use in our program. a program to add them up...
Now, fgets treats each line in your text file as a
string (it stops reading when it finds a line break).
#include <stdio.h>
#include <stdlib.h> /* required for atoi */

int main() {
char c[10];
int sum = 0;
FILE *file;

file = fopen("numbers3.txt", "r");

if(file==NULL) {
printf("Error: can't open file.\n");
return 1;
}
else {
printf("File opened successfully.\n");

while(fgets(c, 10, file)!=NULL) {


sum += atoi(c); /* convert string to int then add it to sum */
}

printf("Now closing file...\n");


fclose(file);
printf("The sum of the numbers is: %d\n", sum);
return 0;
}
}

Output:
File opened successfully.
Now closing file...
The sum of the numbers is: 40

So it looks like atoi has worked. Sometimes you can compile without including stdlib.h but your
compiler may display a warning - MSVC++ did in my case.

fread()
The last reading function reads the entire text file. The third argument in the number of elements to
fread takes four arguments: read. This only has an effect if you passed a char
The first is a char * - this could be an actual char array as opposed to a char pointer.
pointer or a char array. There are differences The last argument is the FILE pointer.
between the two, as we'll see later. fread returns the number of characters read if you
The second argument is the size of char, i.e. 1. passed it a char array.

#include <stdio.h>

int main() {
FILE *file;
char c[30]; /* make sure it is large enough to hold all the data! */
char *d;
int n;

file = fopen("numbers.txt", "r");

if(file==NULL) {
printf("Error: can't open file.\n");
return 1;
}
else {
printf("File opened successfully.\n");

n = fread(c, 1, 10, file); /* passing a char array, reading 10 characters */


c[n] = '\0'; /* a char array is only a string if it has the */
/* null character at the end */
printf("%s\n", c); /* print out the string */
printf("Characters read: %d\n\n", n);

fclose(file); /* to read the file from the beginning, */


/* we need to close and reopen the file */
file = fopen("numbers.txt", "r");

n = fread(d, 1, 10, file);


/* passing a char pointer this time - 10 is irrelevant */
printf("%s\n", d);
printf("Characters read: %d\n\n", n);

fclose(file);
return 0;
}
}

Output:
File opened successfully.
111
222
33
Characters read: 10

111
222
333

444
5ive
Characters read: 10

I've explained most of the statements in the comments (that's what comments are there for!).
Passing a char pointer reads in the entire text file, as demonstrated. Note that the number fread returns
in the char pointer case is clearly incorrect.
An important line is: c[n] = '\0'; Previously, I put 10 instead of n (n is the number of characters read).
The problem with this was if the text file contained less than 10 characters, the program would put the
null character at a point past the end of the file.
There are several things you could try with this program:
Read 25 characters instead of 10: n = fread(c, 1, 25, file);
Not bother adding a null character by removing: c[n] = '\0';
Not bother closing and reopening the file by removing the fclose and fopen after printing the char array.
File Input and Output 3
rewind()
Recall from the last section that I had to close the existing file and reopening it so that I can read from the
beginning again. Instead of using two separate function calls, fclose and fopen, I could've simply called
rewind and passed it the file pointer. This is demonstrated in the next example.

fputc()
Here is the first file writing function I'd like to fputc returns the ASCII code of the character written
introduce. As its name suggests, we can write to a to file if it was successful, else EOF is returned.
file one character at a time. This example writes inputted text to a file it creates,
fputc takes two arguments: the first being an int called "sentence.txt", then displays the entered text
(you can pass it the character you'd like to write to by reading from it:
the file). The second is the FILE pointer.

#include <stdio.h>

int main() {
FILE *file;
char sentence[50];
int i;

file = fopen("sentence.txt", "w+");


/* we create a file for reading and writing */

if(file==NULL) {
printf("Error: can't create file.\n");
return 1;
}
else {
printf("File created successfully.\n");

printf("Enter a sentence less than 50 characters: ");


gets(sentence);

for(i=0 ; sentence[i] ; i++) {


fputc(sentence[i], file);
}

rewind(file); /* reset the file pointer's position */

printf("Contents of the file: \n\n");

while(!feof(file)) {
printf("%c", fgetc(file));
}

printf("\n");
fclose(file);
return 0;
}
}

Output depends on what you entered.


First of all, I stored the inputted sentence in a char array, since we're writing to a file one character at a
time it'd be useful to detect for the null character. Recall that the null character, \0, returns 0, so putting
sentence[i] in the condition part of the for loop iterates until the null character is met.
Then we call rewind, which takes the file pointer to the beginning of the file, so we can read from it.
In the while loop we print the contents a character at a time, until we reach the end of the file -
determined by using the feof function.
This next example opens a file called input.txt which has some random text (less than 200 characters),
stores each character in an array, then spits them back out into another file called "output.txt" in reverse
order:
#include <stdio.h>

int main() {
char c; /* declare a char variable */
char name[200]; /* Initialise array of total 200 for characters */
FILE *f_input, *f_output; /* declare FILE pointers */
int counter = 0; /* Initialise variable for counter to zero */

f_input = fopen("input.txt", "r"); /* open a text file for reading */

if(f_input==NULL) {
printf("Error: can't open file.\n");
return 1;
}
else {
while(1) { /* loop continuously */
c = fgetc(f_input); /* fetch the next character */
if(c==EOF) { /* if end of file reached, break out of loop */
break;
}
else if (counter<200) { /* else put character into array */
name[counter] = c;
counter++; /* increment the counter */
}
else {
break;
}
}

fclose(f_input); /* close input file */

f_output = fopen("output.txt", "w"); /* create a text file for writing */

if(f_output==NULL) {
printf("Error: can't create file.\n");
return 1;
}
else {
counter--; /* we went one too step far */
while(counter >= 0) { /* loop while counter's above zero */
fputc(name[counter], f_output); /* write character into output file */
counter--; /* decrease counter */
}

fclose(f_output); /* close output file */


printf("All done!\n");
return 0;
}
}
}

fputs()
This function is the opposite to fgets in the way fputs requires two arguments: a char * for the
that it writes a line into a file. string you'd like to write, and a FILE pointer. It
returns 0 only if the string is successfully written.

#include <stdio.h>

int main() {
FILE *file;
char *sentence;

file = fopen("sentence2.txt", "a+"); /* open or create a file for appending */

if(file==NULL) {
printf("Error: can't create file.\n");
return 1;
}
else {
printf("File created successfully.\n");

printf("Enter a sentence: ");


gets(sentence);

fputs(sentence, file);
fputs("\n", file);

rewind(file);

printf("Contents of the file: \n\n");

/*while(fgets(sentence, 10, file)!=NULL) {


printf("%s", sentence);
}*/

while(!feof(file)) {
printf("%s", fgets(sentence, 10, file));
}

printf("\n");
fclose(file);
return 0;
}
}

Output depends on what you entered.


This example demonstrates how to append a string to a file. After entering a sentence, we use fputs to
add the sentence to the end of the text file (appending means "adding to the end"). We use another fputs
to append the newline character immediately afterwards - this isn't necessary but it does make the text
file look neater :)
Then to read the file from the beginning, use the rewind function.
The while loop simply prints out all the lines of the text file, but if you run the example on your machine,
you might get (null) displayed as the last line. This is because we reach the end of the file before the
while loop checks the !feof(file) condition. I personally prefer the check to see if fgets returns a NULL
pointer - see the commented while loop.

File Input and Output 4


fwrite()
This function has the same four arguments to Finally, the last argument is the FILE pointer to the
fread: file to write to.
The first is a char * variable and is what you want This example is saved as file.c - it opens file.c for
to write into a file. reading, and copies the content into file2.c
The second is the size of char, i.e. 1. Afterwards, it'll open file2.c and display the source
The third is the number of characters to write - this code on the screen, including the comments!
does come into effect when passing a char * as Notice I used two FILE pointers - one for the reading,
opposed to a char array. the other for the writing.
#include <stdio.h>

int main() {
FILE *sourceFile;
FILE *destinationFile;
char *buffer;
int n;

sourceFile = fopen("file.c", "r");


destinationFile = fopen("file2.c", "w");

if(sourceFile==NULL) {
printf("Error: can't access file.c.\n");
return 1;
}
else if(destinationFile==NULL) {
printf("Error: can't create file for writing.\n");
return 1;
}
else {
n = fread(buffer, 1, 1000, sourceFile); /* grab all the text */
fwrite(buffer, 1, n, destinationFile); /* put it in file2.c */
fclose(sourceFile);
fclose(destinationFile);

destinationFile = fopen("file2.c", "r");


n = fread(buffer, 1, 1000, destinationFile); /* read file2.c */
printf("%s", buffer); /* display it all */

fclose(destinationFile);
return 0;
}
}

Output is the source code above.


One important thing when making a direct copy from one file to another is to pass in a big enough number
in fread so that all the characters are read. Then assign the return value of fread into n so that we know
how many characters to write when calling fwrite.

fscanf()
Here's a familiar sounding function. scanf is really I created a text file called fscanf.txt in Notepad
fscanf, but with the stream set to stdin. with this content:
You can pass a FILE pointer as the first argument of 0 1 2 3 4
5 6 7 8 9
fscanf. The second argument is like the first 10 11 12 13
argument of scanf i.e. a string containing format I've put tabs in the last line.
specifiers. Then follows a list variable addresses so Remember how scanf stops reading input when it
that you can store the inputted data. See the scanf encounters a space, line break or tab character?
section if you want to recap before moving on. fscanf is just the same. So if all goes to plan, this
What's good about fscanf is that if you separate example should open the file, read all the numbers
your numbers, say, in your text file (as opposed to and print them out:
using line breaks all the time), and you can extract
them and store them in an array, for example.
#include <stdio.h>

int main() {
FILE *file;
int numbers[30]; /* make sure it is large enough to hold all the data! */
int i,j;

file = fopen("fscanf.txt", "r");

if(file==NULL) {
printf("Error: can't open file.\n");
return 1;
}
else {
printf("File opened successfully.\n");

i = 0 ;

while(!feof(file)) { /* loop through and store the numbers into the array */
fscanf(file, "%d", &numbers[i]);
i++;
}

printf("Number of numbers read: %d\n\n", i);


printf("The numbers are:\n");

for(j=0 ; j<i ; j++) { /* now print them out 1 by 1 */


printf("%d\n", numbers[j]);
}
fclose(file);
return 0;
}
}

Output:
File opened successfully.
Number of numbers read: 14

The numbers are:


0
1
2
3
4
5
6
7
8
9
10
11
12
13

I find fscanf useful for reading in numbers - I tend to use fgets for reading strings.
An an exercise, try reading in floats from a text file as opposed to ints - just remember to change the
data type of your array, as well as all the format specifiers.

fprintf()
Similarly, printf is fprintf but with the stream set fprintf works in exactly the same way as the
to stdout. familiar printf, except for the extra first argument.
Like with fscanf, you can pass a FILE pointer to This example is taken from the structs section, but
fprintf and output to a text file. with file I/O statements added:

#include <stdio.h>

typedef struct robot ROBOT;

struct robot {
char *name;
int energy;
};

int main() {
int i;
FILE *file; /* FILE pointer */
ROBOT robots[3];

file = fopen("robots.txt", "w"); /* create a file for writing */

if(file==NULL) {
printf("An error has occurred.\n");
return 1;
}

robots[0].name = "Lunar Lee";


robots[0].energy = 50;
robots[1].name = "Planetary Pete";
robots[1].energy = 20;
robots[2].name = "Martian Matt";
robots[2].energy = 30;

/* now loop through the robots array and print


the data into a text file pointed to by file */

for(i=0 ; i<3 ; i++) {


fprintf(file, "Robot %d is called %s ", i, robots[i].name);
fprintf(file, "and has %d units of energy.\n", robots[i].energy);
}
/* here is the old loop
for(i=0 ; i<3 ; i++) {
printf("Robot %d is called %s ", i, robots[i].name);
printf("and has %d units of energy.\n", robots[i].energy);
} */

fclose(file); /* now close the file */


return 0;
}

Output (in robots.txt):


Robot 0 is called Lunar Lee and has 50 units of energy.
Robot 1 is called Planetary Pete and has 20 units of energy.
Robot 2 is called Martian Matt and has 30 units of energy.

I personally prefer fprintf than the other file output functions, simply because you're not limited to just
strings.

The C Preprocessor
Introduction
The C preprocessor is a program that is executed You've already seen a directive: #include
before the source code is compiled. This takes the specified file, and pastes its contents
C preprocessor commands are called DIRECTIVES, into the place where you put #include before the
and begin with a pound / hash symbol (#). No white source code is compiled. So when you use printf,
space should appear before the #, and a semi colon stdio.h is required so that the compiler knows what
is NOT required at the end. printf is.

#define
#define allows you to make text substitutions You can call the MACRO DEFINITION anything you
before compiling the program. Here's an example: want, as long as it doesn't contain special characters
#define MAX 10 or spaces and it cannot start with a number. I tend to
Before compilation, if the C preprocessor finds MAX use uppercase and underscore characters. You can
as one word (so words like MAXIMUM will not be define strings as well:
affected), in the source code, it replaces it with the #define NAME "Eddie's Basic Guide to C"
number 10. If MAX was part of a string (for example, - Every time the preprocessor sees NAME it will replace
between the quote marks of printf), the it with "Eddie's Basic Guide to C"
preprocessor will leave it alone.
#include <stdio.h>

#define MIN 0 /* #defines */


#define MAX 10
#define TRUE 1
#define FALSE 0

int main() { /* beginning of program */


int a;
int okay = FALSE; /* the compiler sees this as int okay = 0; */

while(!okay) {
printf("Input an integer between %d and %d: ", MIN, MAX);
scanf("%d", &a);

if(a>MAX) {
printf("\nToo large.\n");
}
else if(a<MIN) {
printf("\nToo small.\n");
}
else {
printf("\nThanks.\n");
okay = TRUE;
}
}
return 0;
}

The program will loop until you enter a number between 0 and 10.
By the time the compiler receives the program, it won't see words like MIN, MAX, TRUE or FALSE in the
source code. Instead, it'll see the numbers 0, 10, 1 and 0 respectively.

#undef and Macro Functions


If you've created a macro definition, you can use For example:
#undef to remove it. This means the preprocessor #define SQR(a) (a*a)
will no longer make anymore text substitutions Now if you write SQR(3) in your program, the
associated with that word. Also, to change a preprocessor will replace it with (3*3) in your
definition, you must use #undef to undefine it, then program, NOT 9.
use #define to redefine it. Be careful with your brackets, as this example
You can use #define to create your own MACRO demonstrates:
FUNCTIONS. These are useful when the function is
relatively small.
#include <stdio.h>

#define MAX(a,b) (a>b ? a : b) /* a "function" */


#define DIFF1 4-7
#define DIFF2 (4-7)
#define NUMBER 10

int main() {
int a=4, b=7;

printf("Out of %d and %d, %d is the bigger number.\n", a, b, MAX(a,b));


printf("DIFF1 = 4-7. DIFF1 times 10 equals %d.\n", DIFF1*10);
printf("DIFF2 = (4-7). DIFF2 times 10 equals %d.\n", DIFF2*10);

printf("I live at number %d.\n", NUMBER);


printf("I'm moving soon...");

#undef NUMBER /* now undefine NUMBER so that we can give it a different value */
#define NUMBER 7

printf(" now I live at number %d.\n", NUMBER);

return 0;
}

Output:
Out of 4 and 7, 7 is the bigger number.
DIFF1 = 4-7. DIFF1 times 10 equals -66.
DIFF2 = (4-7). DIFF2 times 10 equals -30.
I live at number 10.
I'm moving soon... now I live at number 7.

Let's look at the printf statements:


The compiler will see the first one as:
printf("Out of %d and %d, %d is the bigger number.\n", a, b, (a>b ? a : b));
Since we initialized a and b beforehand, it'll work out if a is greater than b, if so, return a from the
expression, else return b.
The compiler will see the next two printfs as:
printf("DIFF1 = 4-7. DIFF1 times 10 equals %d.\n", 4-7*10);
printf("DIFF2 = (4-7). DIFF2 times 10 equals %d.\n", (4-7)*10);
Notice how the preprocessor leaves DIFF1 and DIFF2 alone inside the string of printf. Looking at the
above lines, you can clearly see why the top printf prints out -66, where as the bottom did the obvious
and printed 30 - macro definitions are just text substitutions!
The next printf is seen as : printf("I live at number %d.\n", 10);
After that, NUMBER is undefined, then redefined, so the next printf will look like:
printf(" now I live at number %d.\n", 7);

#ifdef, #ifndef and #endif


When you come to write big programs, sometimes In the case of #ifdef, if the macro definition that
you'll have to go through a process called follows immediately is defined with #define, the
DEBUGGING, which involves reading through your following code from that directive to the #endif
program, and trying to find out what's causing your directive will be considered as part of the program
program to go wrong. and will be compiled.
One common method for debugging is to comment With #ifndef, it's the other way round, i.e. if there
out sections of code to find that "bug". But what if isn't a definition, the code up to the #endif directive
there are comment dotted around your source will be considered as part of the program and will be
code? That's when #ifdef and #ifndef come into compiled.
play. If you try nesting your comments, you're Example:
going to get a compilation error.
#include <stdio.h>

#define WORD1 /* you don't have to put an expression after the defined word */

int main() {
#ifdef WORD1
printf("1: WORD1 is defined so this bit is compiled.\n");
#endif

#ifndef WORD2
printf("2: WORD2 is not defined so this bit is compiled.\n");
#endif

#undef WORD1
#define WORD2

#ifdef WORD1
printf("3: WORD1 is now undefined so this bit is not compiled.\n");
#endif

#ifndef WORD2
printf("4: WORD2 is now defined so this bit is not compiled.\n");
#endif

return 0;
}

Output:
1: WORD1 is defined so this bit is compiled.
2: WORD2 is not defined so this bit is compiled.

#if, #else and #elif


This set of directives allow you perform conditional You can place your condition after the #if or #elif
branching before the program is compiled, to directives - round brackets are optional.
determine which parts to compile - another useful One important thing to remember is that you can't
method of debugging. use any variables declared in main with these
They act just like the C keywords: if, else and directives, because the directives are read by the C
else if respectively. No curly brackets are required, preprocessor - BEFORE main is executed! You can use
but the whole conditional block must be terminated macro definitions however.
by the #endif directive.

#include <stdio.h>
#define DEBUG_MODE 1

int main() {
#if DEBUG_MODE==1
printf("Debug Mode 1\n");
#elif DEBUG_MODE==2
printf("Debug Mode 2\n");
#elif DEBUG_MODE>2
printf("Debug Mode 3\n");
#else
printf("Default Debug Mode\n");
#endif
return 0;
}

Output: Debug Mode 1


If you try running the example without defining DEBUG_MODE you'll get a compilation error.

Memory Allocation
Introduction
Your computer's memory is a resource - it can run The following functions give you the power to
out. The memory usage for program data can dynamically allocate memory for your variables at
increase or decrease as your program runs. RUN-TIME (whilst the program is running). For the
Up until this point, the memory allocation for your past tutorials, memory was allocated when the
program has been handled automatically when program was compiled (i.e. COMPILE-TIME).
compiling. However, sometimes the computer To use the four functions discussed in this section,
doesn't know how much memory to set aside (for you must include the stdlib.h header file.
example, when you have an unsized array).

malloc() and free()


malloc requires one argument - the number of Passing the pointer into free will release the allocated
bytes you want to allocate dynamically. memory - it is good practice to free memory when
If the memory allocation was successful, malloc will you've finished with it.
return a void pointer - you can assign this to a This example will ask you how many integers you'd
pointer variable, which will store the address of the like to store in an array. It'll then allocate the
allocated memory. memory dynamically using malloc and store a certain
If memory allocation failed (for example, if you're number of integers, print them out, then releases the
out of memory), malloc will return a NULL pointer. used memory using free.

#include <stdio.h>
#include <stdlib.h> /* required for the malloc and free functions */

int main() {
int number;
int *ptr;
int i;

printf("How many ints would you like store? ");


scanf("%d", &number);

ptr = malloc(number*sizeof(int)); /* allocate memory */

if(ptr!=NULL) {
for(i=0 ; i<number ; i++) {
*(ptr+i) = i;
}

for(i=number ; i>0 ; i--) {


printf("%d\n", *(ptr+(i-1))); /* print out in reverse order */
}

free(ptr); /* free allocated memory */


return 0;
}
else {
printf("\nMemory allocation failed - not enough memory.\n");
return 1;
}
}

Output if I entered 3:
How many ints would you like store? 3
2
1
0

When I first wrote the example using a Borland compiler, I had to cast the returned pointer like this:
ptr = (int *)malloc(number*sizeof(int));
The above example was tested in MSVC++ but try casting the pointer if your compiler displays an error.

calloc()
calloc is similar to malloc, but the main difference Like malloc, calloc will return a void pointer if the
is that the values stored in the allocated memory memory allocation was successful, else it'll return a
space is zero by default. With malloc, the allocated NULL pointer.
memory could have any value. This example shows you how to call calloc and also
calloc requires two arguments. The first is the how to reference the allocated memory using an array
number of variables you'd like to allocate memory index. The initial value of the allocated memory is
for. The second is the size of each variable. printed out in the for loop.

#include <stdio.h>
#include <stdlib.h> /* required for the malloc, calloc and free functions */

int main() {
float *calloc1, *calloc2, *malloc1, *malloc2;
int i;

calloc1 = calloc(3, sizeof(float)); /* might need to cast */


calloc2 = calloc(3, sizeof(float));
malloc1 = malloc(3 * sizeof(float));
malloc2 = malloc(3 * sizeof(float));

if(calloc1!=NULL && calloc2!=NULL && malloc1!=NULL && malloc2!=NULL) {

for(i=0 ; i<3 ; i++) {


printf("calloc1[%d] holds %05.5f, ", i, calloc1[i]);
printf("malloc1[%d] holds %05.5f\n", i, malloc1[i]);
printf("calloc2[%d] holds %05.5f, ", i, *(calloc2+i));
printf("malloc2[%d] holds %05.5f\n", i, *(malloc2+i));
}

free(calloc1);
free(calloc2);
free(malloc1);
free(malloc2);

return 0;
}
else {
printf("Not enough memory\n");
return 1;
}
}

Output:
calloc1[0] holds 0.00000, malloc1[0] holds -431602080.00000
calloc2[0] holds 0.00000, malloc2[0] holds -431602080.00000
calloc1[1] holds 0.00000, malloc1[1] holds -431602080.00000
calloc2[1] holds 0.00000, malloc2[1] holds -431602080.00000
calloc1[2] holds 0.00000, malloc1[2] holds -431602080.00000
calloc2[2] holds 0.00000, malloc2[2] holds -431602080.00000

On all machines, the calloc1 and calloc2 arrays should hold zeros. Contents of the malloc1 and
malloc2 arrays will vary.
Try changing the data type from float to double - the numbers displayed were too long for me to fit onto
this web page :)

realloc()
Now suppose you've allocated a certain number of Passing zero as the second argument is the
bytes for an array but later find that you want to equivalent of calling free.
add values to it. You could copy everything into a Once again, realloc returns a void pointer if
larger array, which is inefficient, or you can allocate successful, else a NULL pointer is returned.
more bytes using realloc, without losing your data. This example uses calloc to allocate enough memory
realloc takes two arguments. The first is the for an int array of five elements. Then realloc is
pointer referencing the memory. The second is the called to extend the array to hold seven elements.
total number of bytes you want to reallocate.
#include<stdio.h>
#include <stdlib.h>

int main() {
int *ptr;
int i;

ptr = calloc(5, sizeof(int));

if(ptr!=NULL) {
*ptr = 1;
*(ptr+1) = 2;
ptr[2] = 4;
ptr[3] = 8;
ptr[4] = 16;
/* ptr[5] = 32; wouldn't assign anything */

ptr = realloc(ptr, 7*sizeof(int));

if(ptr!=NULL) {
printf("Now allocating more memory... \n");
ptr[5] = 32; /* now it's legal! */
ptr[6] = 64;

for(i=0 ; i<7 ; i++) {


printf("ptr[%d] holds %d\n", i, ptr[i]);
}
realloc(ptr,0); /* same as free(ptr); - just fancier! */
return 0;
}
else {
printf("Not enough memory - realloc failed.\n");
return 1;
}
}
else {
printf("Not enough memory - calloc failed.\n");
return 1;
}
}

Output:
Now allocating more memory...
ptr[0] holds 1
ptr[1] holds 2
ptr[2] holds 4
ptr[3] holds 8
ptr[4] holds 16
ptr[5] holds 32
ptr[6] holds 64

Notice the two different methods I used when initializing the array: ptr[2] = 4; is the equivalent to
*(ptr+2) = 4; (just easier to read!).
Before using realloc, assigning a value to ptr[5] wouldn't cause a compile error. The program would still
run, but ptr[5] wouldn't hold the value you assigned.

strcat and strncat


Introduction
strcat and strncat are library functions that perform string CONCATENATION. This term is used to
describe the combining of strings.
Both these functions require the string.h header file to be included.
The reason why I've left these until now, is because they require you to dynamically allocate memory
before the concatenation of strings. It isn't as easy as:
str = "Hello" + " World";
Yes, it's THAT simple in Java, JavaScript and Flash ActionScript!
Visual Basic is more or less the same, apart from the operator:
str = "Hello" & " World";

strcat()
strcat takes two char * arguments and returns the concatenated string as a char *. Here's a simple use
of strcat:

#include <stdio.h>
#include <string.h>

int main() {
char str1[50] = "Hello ";
char str2[] = "World";

strcat(str1, str2);

printf("str1: %s\n", str1);

return 0;
}

Output:
str1: Hello World
This only works if you've defined the str1 array to be large enough to hold the characters of your string.
If you don't specify a size, the program may crash.
In some cases, you'd probably want to use char * variables.
To perform a successful concatenation without the program crashing or complaining about memory, it's
best to calculate and allocate enough memory to hold the resulting string.
You can do this with either calloc or malloc.
Now, the way I concatenate a string in this example may seem weird at first, but it demonstrates the
difference between calloc and malloc:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char *str1 = "Hello ";
char *str2 = "World";
char *str3;

str3 = (char *)calloc(strlen(str1) + strlen(str2) + 1, sizeof(char));


/* Try: str3 = (char *)malloc((strlen(str1) + strlen(str2) + 1)*sizeof(char)); */

strcat(str3, str1);
strcat(str3, str2);

printf("str3: %s\n", str3);

free(str3);

return 0;
}

With calloc I get:


str3: Hello World
But if I'd used malloc:
str3: ------------²²²²Hello World
Recall that calloc allocates a clean chunk of memory.
Here's a better version of the last example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char *str1 = "Hello ";
char *str2 = "World";
char *str3;

str3 = (char *)malloc((strlen(str1) + strlen(str2) + 1)*sizeof(char));


/* str3 = (char *)calloc(strlen(str1) + strlen(str2) + 1, sizeof(char)); */

strcpy(str3, str1);
strcat(str3, str2);

printf("str3: %s\n", str3);

free(str3);

return 0;
}

The output in both cases is:


str3: Hello World
The amount of memory to allocate is worked out by finding the lengths of str1 and str2 and adding 1 (to
allow for the NULL character).
The difference between the two examples is the strcpy function call in the second example. str1 is
copied into str3, then str2 is concatenated onto the end of str3. After displaying str3, the allocated
memory is freed manually by passing the pointer into the free function.

The C Version of str1 += str2;


In Java, JavaScript and ActionScript, you can concatenate a string onto the end of an existing one by
saying str1 = str1 + str; or even better, str1 += str2;
Unfortunately in C, += is used for numerical values.
If you wanted to achieve the same result using char * variables, you'll have to allocate memory for a
temporary variable, perform the concatenation, allocate more memory for the original variable, copy the
temporary value into it, and free the memory allocated!
Here's one way that you might go about doing this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char *str1 = "Hello ";
char *str2 = "World";
char *str3;

str3 = (char *)calloc(strlen(str1) + strlen(str2) + 1, sizeof(char));

strcpy(str3, str1);
strcat(str3, str2);

printf("str3: %s\n", str3);

str1 = (char *)calloc(strlen(str3) + 1, sizeof(char));

strcpy(str1, str3);

printf("str1: %s\n", str1);

free(str1);
free(str3);
return 0;
}

Output:
str3: Hello World
str1: Hello World

strncat()
This function's almost the same as strcat - it takes a third attribute, which is the number of characters to
concatenate from the source string.
I'll demonstrate it using char * variables first:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char *str1 = "It is ";
char *str2 = "raining sunny snowing foggy";
char *str3;

str3 = (char *)calloc(strlen(str1) + strlen(str2), sizeof(char));

strcpy(str3, str1);
strncat(str3, str2+8, 5);

printf("str3: %s\n", str3);

free(str3);

return 0;
}

Output:
str3: It is sunny
Notice how I referenced the 8th character from the str2 pointer, to access the beginning of "sunny". str2
still points to "raining sunny snowing foggy" though.
You can do a similar thing with char arrays too:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
char str4[] = "The time is ";
char str5[] = "9PM 10AM 6.47";

strncat(str4, str5+4, 4);

printf("str4: %s\n", str4);

return 0;
}

Output:
str4: The time is 10AM

Creating Header Files and


Library Functions
What is a Header File?
Header files contain declarations to functions and variables and have a .h extension. Examples of header
files include stdio.h, string.h and strlib.h.
stdio.h looks horrendous in Notepad, so here is an example of a simple header file:
#ifndef EXAMPLE_H
#define EXAMPLE_H

extern int square(int x);


extern int triangle(int x);
extern double power(int x, int y);
extern double factorial(int x);

extern void print_1D_Array(int *array, int size);


extern void print_2D_Array(int *array, int rows, int cols);
extern void reverse_1D_Array(int *array, int size);

#endif

I called this example.h and will be using it later on by writing #include "example.h" in the source file of
the main program.
The functions are defined in a separate source file, so you'll need to place the extern keyword before the
function declaration.
If the header was included the first time, EXAMPLE_H won't be defined, so the file's contents are copied and
compiled. However, I've defined EXAMPLE_H in the second line so if I accidentally included the header file a
second time, #ifndef EXAMPLE_H isn't true, so the contents of the header file are not copied and compiled
a second time. I ended the header file with #endif.

The Source File


The function definitions lives in a file with a .c extension - THE main FUNCTION DOES NOT GO IN HERE!
You can save the source file with any name - here is what example.c looks like:

#include <stdio.h>

int square(int x) {
return (x * x);
}

int triangle(int x) {
return (x*(x+1)/2);
}

double power(int x, int y) {


double answer = x;
int temp = x;
int power;

for(power=y-1 ; power!=0 ; power--) {


answer*=temp;
}

return answer;
}

double factorial(int x) {
int temp;

for(temp=x-1 ; temp!=0 ; temp--) {


x*=temp;
}

return x;
}

void print_1D_Array(int *array, int size) {


int num = size / sizeof(int);

int i;

for(i=0 ; i<num ; i++) {


printf("%d ", *(array+i));
}
printf("\n\n");
}

void print_2D_Array(int *array, int rows, int cols) {


int i, j;

for(i=0 ; i<rows ; i++) {


for(j=0 ; j<cols ; j++) {
printf("%6d ", *(array+(cols*i)+j));
}
printf("\n");
}
}

void reverse_1D_Array(int *array, int size) {


int num = (size / sizeof(int)) -1;
int temp, i;

for(i=0 ; i<(num/2) ; i++) {


temp = *(array+i);
*(array+i) = *(array+num-i);
*(array+num-i) = temp;
}
}

Don't compile this just yet!


Since I used printf in the source, I had to include stdio.h. Some compilers require you to include
header files more than once if you've used a library function in separate source files.
This is the main program file that used these functions:
#include <stdio.h>
#include "example.h"

int main() {
int x = 5;

int *ptr1, *ptr2;


int array_1D[] = {0,1,2,3,4,5,6,7,8,9};

int size = sizeof(array_1D);

int array_2D[5][4] = { { 0, 1, 2, 3},


{ 4, 5, 6, 7},
{ 8, 9,10,11},
{12,13,14,15},
{16,17,18,19} };

printf("%d squared is %d.\n", x, square(x));


printf("The triangular number of %d is %d.\n", x, triangle(x));
printf("%d to the power of 3 is %.0f.\n", x, power(x,3));
printf("%d to the power of 7 is %.0f.\n", x, power(x,7));
printf("%d factorial is %.0f.\n\n", x, factorial(x));

/* %f is used for displaying floats and doubles.


My version of power() and factorial() return
whole numbers so %.0f is used. */

ptr1 = array_1D;

printf("Let's print a 1D array...\n");


print_1D_Array(ptr1, size);

printf("Now let's reverse it and print it out:\n");


reverse_1D_Array(ptr1, size);
print_1D_Array(ptr1, size);

ptr2 = &array_2D[0][0]; /* point to first element of 2D array */

printf("Let's print a 2D array...\n");


print_2D_Array(ptr2, 5, 4);

return 0;
}

We'll compile this example in the next section.

The Process of Linking


What Does Linking Involve?
Recall that the compiler is a program that translates The way linker works depends on the compiler. I've
source code into machine code. But what if the used three compilers in the past - gcc on a UNIX
program has more than one source file? platform, and Borland C++ and Microsoft Visual C++
The LINKER is a program that is run after on Windows.
compilation. Its job is to piece together various For the demonstrations, I'll assume you've saved the
parts of a program, in order to produce the final files from the previous section: example.h,
executable. example.c and main.c

Linking the gcc Way


Before building the final executable, we must This command produces the executable:
compile all separate source files individually into cc -c example.o main.o -o example
OBJECT files - these are pieces of the final Notice that there isn't a -c flag because we're not
executable (like a jigsaw puzzle). They have a .o actually using the compiler - we're just linking the two
extension in our case. object files to create the output file called example.
Assuming you're in the right directory, these UNIX You can call it what you want - to run the program,
commands will compile example.c and main.c into simply type the name of the output file and press
their individual object files: enter.
cc -c example.c -o example.o However, if you ever change one of the files, you
cc -c main.c -o main.o must recompile to create a new object file. For
The file specified after the -c flag is the source file. example, if I modified main.c and left the other files,
Whatever is after -o is the output. Now that we I'd have to type: cc -c main.c -o main.o
have our object files, we now link them together to then cc main.o example.o -o example before
produce the final product. running my program.

Other Compilers
Most compilers require you to create a new project before writing any code.
When you come to create a project, it's likely that you want to create a blank Win32 Console Application
(or similar).
Then all you need to do is to add your files to the project (usually done via the Project menu), select the
Build option, and compilation and linking should take place. Object files have a .obj extension in most
cases.
If in doubt about linking, consult your compiler's documentation.

Output
The output from the previous example should be:
5 squared is 25.
The triangular number of 5 is 15.
5 to the power of 3 is 125.
5 to the power of 7 is 78125.
5 factorial is 120.

Let's print a 1D array...


0 1 2 3 4 5 6 7 8 9

Now let's reverse it and print it out:


9 8 7 6 4 5 3 2 1 0

Let's print a 2D array...


0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
16 17 18 19

E101 Slide Lectures


CompE101 Syllabus
CompE102 Syllabus
CompE103 Syllabus
CompE104 Syllabus
CompE111 Syllabus
CompE231 Syllabus
CompE236 Syllabus
CompE513 Syllabus
E101 Syllabus
Introduction to C
C in 24 Hours
C in 21 Days
CompE104 Slide Lectures
CompE104 Exercises
CompE101 Lessons
CompE101 Slides
CompE101 Tests
CompE101 Project
Computing Essentials Slides
Outlook Slides
Microsoft Word
Exploring Internet
CompE111 Lessons
CompE111 Slides
CompE111 Tests
CompE111 Project
Computing Essentials Slides
Outlook Slides
Microsoft Word
Exploring Internet
CompE103 Lessons
CompE103 Slides
CompE103 Tests
Computing Essentials Slides
Outlook Slides
Microsoft Word
Exploring Internet
CompE231 Slide Lectures
CompE236 Slide Lectures
Maximum Security
Firewalls
Scanners
Sniffers
Trojans
VirusWorms
Steganography
Crackers
Misc Tools
Home Computer Security
Security Terms
Altavista
Google
Yahoo
Excite
Linux Links
Windows Links

You might also like