My first tutorial was fairly dry and focused mostly on the compilation
process without providing much information about how to actually program. This
tutorial will fill that gap.
Where do we start?
You should have a compiler installed on your computer and know how to use
it. If you do not, then I recommend GCC (or MinGW if using Windows), which is
free and can be run from the command line (which is preferable for this
tutorial). Clang/LLVM is also another option, it is also free. MSVC can also be
invoked from the command line, but I prefer GCC or Clang instead.
Can we start writing code?
Ok. C code is stored in a plain text file. To illustrate this, I recommend
that you start out with just a plain text editor (avoid IDE's) at this point. If
you are using Windows, then notepad is always available. If you are using Linux,
Then you might have a text editor such as Leafpad or gEdit available, or if you
are familiar with the Linux command line, you could also use nano, vi, or sandy.
Start by just creating a blank file. Save it in some directory on your
computer. However, before you actually save it, you should remember that if you
are on Windows, you are probably used to text files using the extension ".txt",
in this case, we do not want to use ".txt", instead, we want to save our source
code file with the extension ".c". So if you name your file something like
"tut_2", then your file's full file name should be "tut_2.c" and not
"tut_2.txt". The reason for this is not because ".c" is a magic extension, it's
essentially just used to help us differentiate between a text file that contains
text and a text file that contains c code. If you wanted to, it is possible to
use the ".txt" extension instead.
Before we start writing a program, we should know what exactly we are
trying to accomplish. Usually, the first program you write just prints out the
string "Hello World", but we already covered that in Tutorial 1. So, instead
of that, we are going to do something better. Let's write a program that
generates a random number and asks the user to guess what it is, giving hints if
the user guesses wrong.
While this is more fun than "Hello World", you may still be disappointed
that we will still be using the command line for this one. Don't worry though,
you will be doing graphical programming soon enough.
This exercise will teach many of the basic C concepts you need to know for
Getting started and defining functions
Start out by defining your main function. We won't write any include
directives yet since we haven't actually decided what functions we will be using
so we don't know what header functions define those functions. Although, we
could guess that we will probably be using the common, standard ones, for this
exercise, let's not make any assumptions just yet.
In C, all function definitions follow the same form. Your main function is no
exception, it is just a normal function, just like any other, it is NOT a magic
function, it just happens to be the function that libc calls once it has
everything set up.
Function definitions begin with the return type. For main, it should be int
(integer), because that is what libc expects it to return. For other functions,
it can be almost anything you want. We will talk more about limitations later.
After the return type comes some whitespace (space, tab, or new-line) which
functions as a sort of separator, and then the name of the function (main).
Finally, you have to specify what arguments will be passed to the function.
This is accomplished with a comma separated list of variable types and variable
names, all within parenthesis. The main function will have two arguments passed
to it, the first is an int, and the second is a 2D array of characters. So your
code defining main should look like this:
int main(int argc, char **argv)
You can see in this example that the first argument is an integer and I have
chosen the name "argc" (argument count) for the variable. The second argument is
named "argv", and is of the type char** (2D array of characters). You can call
your variables whatever you want, but these are the names that are usually used
for the arguments to main.
Generating a Random Number
As you may have guessed, this program will need to generate a random
number. This is actually not as easy as it might sound. Computers can not just
make up a number, they need to have some algorithm to follow to get a number. So
usually instead of random numbers, computers use "psuedo-random numbers", which
are not really random numbers, but to a human being they seem to be random.
There are many classes of psuedo-random number generators, some are
trivial, some are really hard to determine what number will be next
(cryptographic psuedo-random number generators), some try to be fast, some try
to be slow, some try to be even, most try to do more than one thing. In our
case, we don't need anything fancy, just something that looks random to the
user. So we can use the random number generator that is part of the C standard.
This random number generator is part of the standard C library, and defined in
the header file, "stdlib.h".
Now that we know this, we can start writing some code. If you can remember in
the last tutorial we learned about the C preprocessor "#include" directive. We
can use the #include directive to include the contents of stdlib.h into our
source. This will allow the C compiler to understand our calls to the random
number generator functions. This line should look like this:
The function to actually retrieve a random number is defined as:
This might look odd to you if you understand function definitions but not how
the random generator works. The definition shows that it returns and integer,
but takes zero arguments. So, without passing any arguments, how can we tell the
random generator what range of numbers we want? The answer to this question will
be covered later in this tutorial.
Integer Math, Constants, Types, and Storage
Now if we ask the user to guess a random number without any range, it will
take the user quite a long time. So we need to define some kind of range. For
this example, we will use only numbers between 0 and 100.
We already mentioned that the rand() function doesn't allow us to specify
a range when we call it, so how can we get a number within the range we want?
There are actually a few methods to accomplish this. The first and easiest
method involves something you probably learned in elementary school and haven't
used since: Integer Math. If you don't know what I mean, let's look at an
example: 3 / 2 = 1.5, right? This is true only sometimes, it depends on what
kind of numbers the 3 and the 2 are. If they are both integers, then C will do
integer division, and the result will be 1 instead of 1.5. If that doesn't make
sense to you, remember back to elementary school, before you learned fractions,
when you first learned about division. Back then, if you divided 3 into 2, your
answer would have been 1, with a remainder of 1. This is integer division.
Now that we understand integer division, consider this: in the equation
x/y (assuming integer division), what is the maximum possible remainder? What is
the minimum possible remainder?
In case you haven't figured it out, the maximum possible remainder would
be y-1 and the minimum possible remainder would be 0, or in other words, the
range is from 0 to y-1. This is exactly what we want to do, and this is a very
common method to get rand() into the range that we want.
So, in order to implement this in our code, we need to know how to get
a remainder. To do this, we use the "modulo" operation, using the modulo
operator, "%". For example, to get the remainder of 3 / 2, we would write 3%2 in
Using this knowledge, generating a random between 0 and 100 is easy, all
we need to do is generate a random number and take the remainder of the result
over 100. This can be done in one line:
This works for our purpose, but it does have some issues. First of all,
using this method it becomes more likely that the result will be a smaller
number in most cases. However, if the random generator can generate big enough
randoms before the modulo operation, then the increased likelihood of smaller
numbers is very slight. However, in some cases this is still unacceptable since
it reduces randomness. To compensate for this, we can use another method to
transform our random number into a random number within a specific range.
This second method uses regular floating-point division. It also requires
us to know the actual range of the rand() function before we transform the
result into the range we want. I don't know what the exact number is, and it is
possible for different systems to use a different range, so it is impossible to
know on all systems. However, the header defines what is called a "constant",
which is like a variable, except it is handled by the C preprocessor instead of
the C compiler. As a result of this, constants can not be changed after the
application is compiled, they are constant. Constants usually use a name that is
written in all capital letters so that programmers can differentiate between
constants and variables more easily. The constant that tells us the range of
rand() is called RAND_MAX.
It is important to remember that constants are handled by the preprocessor
and not the compiler, a constant is not a variable. Before compilation, the
preprocessor will read your code, find the constants and actually replace those
constants with the number they represent. So if RAND_MAX is defined as 255, then
trying to change RAND_MAX to equal 100 would be the same as writing 255=100,
which simply doesn't make sense.
Now that we know the range of rand() is 0 to RAND_MAX, we can convert the
range into the range that we want. If we use floating point math, we can divide
the generated random by RAND_MAX, which will result in a decimal number between
0 and 1. After that, all we need to do it multiply by 100 to get a number
between 0 and 100.
However, we still didn't learn how to actually do floating-point math.
There is no special way to do floating point math in C, the compiler will just
automatically do floating-point math whenever at least one of the variables is a
floating-point number. rand() returns an integer, and RAND_MAX is an integer as
well, so rand()/RAND_MAX will always equal 0 or 1, never anything in between. In
order to do floating-point division, we need to convert one of these integers
into a floating-point number. One easy way to do this is to create a new
floating-point variable and store the result of rand() in that variable before
dividing by RAND_MAX. We learned how to declare integer variables already, using
"int". To declare a floating-point variable, we can use "float" instead. So
declare a variable called r as a floating-point variable as follows:
float r = rand();
Then, r can be divided by RAND_MAX, and the compiler will do floating-
point division instead since r is a floating-point variable and the result will
be between 0 and 1. It is important that we also store this value in a floating-
point variable as well, otherwise the result will be automatically rounded to an
integer. However, once we have multiplied by 100, we probably want to round to
an integer again, it would be very difficult for the user to guess a floating-
point number between 0 and 100 exactly. We can do this by creating another
integer variable and storing the result there.
A full algorithm to convert the range of rand() into 0 to 100 would
look like this:
float r = rand();
r = r / RAND_MAX;
r = r * 100;
int result = r;
This can be done in one line without intermediate storage, but it would need to
use explicit casts, which we haven't learned yet. It should also be noted that there is a slight difference between the two
methods described. The first method will yeild a number between 0 and 99
inclusive, while the second method could generate a 100 (but its a 1/101 chance).
We have generated a random number, now we need the user to guess what it
So we will need to get input from the user somehow. There are many ways
of doing this, but on the command line it is fairly easy. If you remember last
lesson we learned about printf(), we can use a similar function to get input,
scanf() works like printf() in that it takes a format argument and a list
of variables for each marker in the format. However, scanf has some differences.
For instance, since scanf will be saving data to the variables, we cannot give
variables to scanf(), we need to give scanf() pointers to the variables instead.
On top of that, scanf() also accepts a few formats that printf() doesn't, which
will be useful later for reading long strings, but for now we only need to read
Let's look at and example. We want to read an integer from the command
line and store it in a variable. We can give this variable some meaningful name,
such as input. Command line input is line-buffered, which is
really annoying in my opinion, but it does occasionally make things easier. What
this means for us is that we will not recieve anything until the user presses
enter. So our scanf() call could look like this:
Notice that I passed &input instead of just input. That is because &input is
the pointer to input, meaning that &input is the memory address of input. If we
just passed input then scanf() would know the current value of input, but not
where to store the value that it retrieved from the user.
Next, we need to test if the user entered the correct number, and if not,
if the user's guess was too high or too low. To do this, C has what is called
an if statement. The if statement basically allows you to do something in
some cases, and something different or nothing in other cases. For instance, we
can tell the user that the answer is wrong if the input is not equal to the
random number, and if it is equal, than we can tell the user that it is right.
However, this alone is going to make for an almost impossible game. We
need to allow the user to guess again if the answer is wrong, and continue
guessing until the correct answer is found. To do this, we need to use some kind
of loop. In C (and most languages), loops are like the if statement, except
instead of doing something in one case and something else in another, they do
something again and again and again until the condition changes. For instance,
we can keep asking for more guesses until the user finds the right answer.
There are various types of loops in C, three common types are the while
loop, the do-while loop, and the for loop. Of these, I
personally use the for loop most, and I can't think of a time I ever used a
do-while loop for real-world work. However, the first loop we should learn about
is the while loop, it is simple and understanding it will make understanding the
other types of loops easier.
Think about how you would use "while" as a command in English, for
instance, "While it is hot, wear a coat". If you were to listen to that advise,
you would continually wear a coat if it is hot out, and when it becomes cold,
you will stop wearing a coat. This is exactly how the while loop works. If the
condition is true (it is hot) then you will do the action (wear a coat)
continually until the condition (it is hot) becomes false (it is not hot). In
our case, we want to say something like "While the answer is different than the
generated number, guess again".
Both conditional statements and loops require a "condition" that must be
either true or false. In C, both true and false have a value,
false being 0 and true being anything besides 0, usually 1. This concept is very
important to understand. In human languages, true and false are concepts and not
numbers, but in C, true and false are numbers. This means that mathematical
expressions will either be true or false, which is exactly what your conditions
will be in your loops and conditional statments: expressions. In fact, the
correct term to use for the condition is "expression".
This can be a difficult concept to understand at first. In a human
language, you would say "if x is equal to 10", while in C you would say
"if (x==10)", these look nearly the same, but are processed quite differently.
You may notice that in C, we will use == instead of just = when we
are writing expressions. That is because in C, == is a mathematical
operator, just like + or - or *. Also, remember that we are talking about ==
and not =. If I were to ask you what is 3+2, you could easily answer
assuming you possess even elementary math skills, but in C, I could just as
easily ask what is 3==2? In human language this is a strange question, but to a
computer, it is just as natural. I have even given you enough information to
solve it already. Since I already told you that false is equal to 0 and true is
equal to 1, and 3 is not equal to 2, then you can figure out that 3==2 is equal
Now, of course, it would be silly to actually write "3==2" in your code,
since we know that 3==2 will always be false, instead your expressions will
likely use variables instead. For instance, i==8 will be 1 if i is 8 and
0 if i is anything else. Now if we made a mistake and accidentally wrote
"i=8", then no matter what i was set to before, it would now be equal to
8, which is not what we wanted to do.
In addition to the == operator, there are also inequality operators, such
as < and >.
Now that we know how to use expressions, let's learn how to actually write
conditional statements. The if statement is written in the following form:
Where expression is the expression to be evaluated. The parenthesis
around the expression are required, however, this makes the if statement look
somewhat like a function, do not get confused, if is not a function, it
is a statement. The space between the word "if" and the parenthesis is not
strictly required, but I always add that to differentiate statements from
functions. Also notice the usage of curly brackets. In the last tutorial we saw
how curly brackets mark the beginning and end of a function, but they have other
uses too. More generally, curly brackets mark a block of code. They act
sort of like a partition. In this case, the curly brackets indicate what code
will be executed if the expression evaluates to true. If the
expression evaluates to false, then the entire block of code will be
You may also have noticed that I did not place a semi-colon (;) after the
if statement. That is not a mistake. This is very important. The if statement
does not actually require curly brackets to be placed after it, however, if
are no curly brackets, the if statement will execute only the next line
of code if the expression is true, and skip only one line if it is false.
If you accidentally place a semi-colon after the if statement, you are ending
that line of code. That means if the expression is true, it will do nothing and
then continue, if the expression is false, it will skip nothing and continue.
This means that your if statement will essentially have no effect. So make sure
you are very careful about writing if statements.
while loops are written just like if statements, except with the word,
"while" instead of "if". while works almost exactly like if, except that if the
expression evaluates to true, then the code block is executed and the it starts
over, evaluating the expression again. A while loop takes the following
Inequalities and Comparison
Remember that I told you == is an operator that evaluates to true (1) if
both sides are equal and false (0) if they are not? Remember that I also told
you that there are other operators as well for inequalities? For instance, >
would evaluate to true if the left side is greater than the right side, and 0 if
the right side is greater or if they are equal. There is another important
operator which is !. The ! operator in C means "not". If you are familiar
at all with binary logic, then you can easily understand !. If not, I will
explain. What ! does is convert any true (1) values to false (0) and false to
true. So, !0 equals 1, and !1 equals 0.
In addition to the ! (but related), there is another operated called !=
which means "not equal". This operator evaluates to true if both sides are
different and false if they are equal. It is the exact opposite of ==.
These might seem silly, but if you consider the loop we will need to write
for our program, consider the condition which will cause the guessing to
continue. We want to continue guessing (restart the loop) while the user has not
yet guessed correctly. e.g. while (guess!=random).
Putting it all together
Now finally if you made it here, you have enough knowledge to complete the
entire program. If you feel up to it, try to write it yourself without looking
at the completed code below. Otherwise, look at the code below and take note of
how it utilizes the concepts that we learned in this tutorial.
Completed Program Source
int main(int argc,char **argv)
random = rand() % 100;
while (guess != random)
if (guess > random)
if (guess < random)
Now let's do a quick quiz to see how much you remember.
Answer the following questions:
1. What is 14/3?
2. What type of file is used to store C code?
3. What does a ; do?
4. What is "14 == 14"?
5. What defines a "block" of code?
6. How are constants processed?
7. What is "15 < 50"
8. What does % mean and what does it do?
9. What is 9/2?
10. What is "=" used for?
If you compiled and ran the program we wrote in this tutorial, you may have
noticed that it is far from perfect. Not to worry though, next time we will work
on fixing it up while learning more concepts!