Tutorial On C

In this tutorial, we are going to do recall our C programming skill . We will write some simple C programs and learn how to compile and build them in Sun Solaris computers of our lab. We will use Vi, Emacs or Pico for editing the files. Login to one of the following pcs:

cs1.utdallas.edu

cs2.utdallas.edu

Use PuTTY or Xmanager for logging on as you learnt in Tutorial 1.

Hello World example

In our first example, we have a very simple and short code which prints the traditional "Hello World" string to the terminal. Open your favorite Unix editor (Vi / Emacs / Pico) and type the code:

// hello.c

// Include the stdio.h header file, it has the declaration of printf function which we are going to use
#include <stdio.h>

// The main function
main()
{
        /* Call the function printf to print Hello World
         * The argument to the function is the string to be printed
         * The special sequence "\n" is used to print a new line after the string
         * The 'n' in "\n" stands for new line
         */
        printf("Hello World!\n");
}

Everything on the right of a "//" is a single line comment and everything in between a pair of "/*" and "*/" are multi-line comments. Comments are not part of the program.  Save the file as "hello.c" and then from the terminal compile and build it with the following command:

{cs1:~} gcc -o hello hello.c
{cs1:~} ls
-rwx--x--x 1 mfh062000 sn 6480 Oct 20 16:38 hello
-rw-r----- 1 mfh062000 sn 65 Oct 20 15:40 hello.c

We used "gcc" to compile the code. "gcc" stands for GNU C Compiler. The "-o" option determines the name of the output file. The argument following the option is the name of the binary to be produced. After that we provided the name of the source file. As we can see from the output of "ls" a file named "hello" is built with execute permission for all. Now we run it by the following way:

{cs1:~} ./hello
Hello World!
{cs1:~}

Note that a new line is printed after the string. Otherwise, the prompt would appear after the string on the same line like: "Hello World!{cs1:~}"

Finding root of a quadratic equation

This example finds the root of a quadratic equation where the co-efficients are hard-coded. Type the code in the editor and save the file as "quad.c":

// quad.c
#include<stdio.h>
// math.h is needed as it has the declaration of sqrt function which we will use
#include<math.h>

main()
{
        // Declare float type variables, float variables can hold real numbers
        float a,b,c,s,root_1,root_2;
        // Initialize co-efficients
        a=1;b=1;c=-6;
        // Recall that the root equation is x = (+/-) (-b + square_root_of(b^2 - 4ac)) / 2a
        // Calculate the square root term
        // The sqrt function takes a float type variable and return its square root as a float type variable
        // Operator precedence in C is just like mathematics, i.e. in the following line is similar to 's = sqrt((b*b) - (4*a*c))'
        s = sqrt(b*b - 4*a*c);
        // Calculate the roots
        root_1 = (-b + s)/(2 * a);
        root_2 = (-b - s)/(2 * a);
        // Print the roots
        // We put "%f" in the string where we wish to print a float type variable
        // After the string, we put the variables in order which we like them to be printed within the string
        printf("The first root is %f\nThe second root is %f\n", root_1, root_2);
}

Compile and build the code::

{cs1:~} gcc -o quad quad.c -lm

Note the "-lm" option used at the end. We need to link to the math library for the sqrt function. By "-l" option we specify library to link. For linking to math library, we use the library name abbreviation "m", hence it is "-lm". Run the binary:

{cs1:~} ./quad
The first root is 2.000000
The second root is -3.000000

Quadratic solver taking input from keyboard

In this example, we will do the same quadratic equation solution but this time we will take the co-efficients input from the keyboard. Our program will not check for equations with no real roots. Type the code:

// quad2.c

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

main()
{
        float a,b,c,s,root_1,root_2;
        printf("Enter three coeeficients : ");
        // This line takes the input
        // The scanf function is used to take input
        // In a string, put as many "%f" as you want to input real numbers
        // After the string, put the names of the variable where you want to store the values
        // Each variable name will be prefixed by an ampersand '&'
        scanf("%f %f %f",&a,&b,&c);
        s = sqrt(b*b - 4*a*c);
        root_1 = (-b + s)/(2 * a);
        root_2 = (-b - s)/(2 * a);
        printf("The first root is %f\nThe second root is %f\n", root_1, root_2);
}

Save the file as "quad2.c". Compile and run:

{cs1:~} gcc -o quad2 quad2.c -lm
{cs1:~} ./quad2
Enter three coeeficients : 1 2 -8
The first root is 2.000000
The second root is -4.000000

Calculating mean

Now, we will create a program which will, given two numbers, calculate arithmetic mean or geometric mean or harmonic mean based on the choice provided by the user. By this program, we will recall the "if - else" construct. The general syntax of "if - else" construct is:

if ( condition )
{
        Statements1
}
else
{
        Statements2
}

If the condition is true, Statements1 gets executed, otherwise Statement2 is executed.

Type the following code:

// means.c

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

main() {
        float a,b;
        int instr;
        printf("Please enter 2 positive numbers : ");
        scanf("%f %f",&a, &b);
        printf("1 - Arithmetic Mean\n2 - Geometric Mean\n3 - Harmonic Mean\nChoice : ");
        // The user inputs choice number 1 or 2 or 3
        scanf("%d",&instr);
        // Checks whether choice is 1
        if (instr == 1) {
                printf("The arithmetic mean is %f.\n",(a+b)/2);
        }
        // If the choice is not 1 then this block within "else" is executed
        else {
                // Checks whether choice is 2
                if (instr == 2) {
                        printf("The geometric mean is %f.\n",sqrt(a * b));
                }
                // Choice is not 2, so check further
                else {
                        // Checks whether choice is 3
                        if (instr == 3) {
                                printf("The harmonic mean is %f.\n",1/(1/a + 1/b));
                        }
                        // None of the valid choices matched, print an error message
                        else {
                                printf("Not a valid command.\n");
                        }
                }
        }
}

Save the code as "means.c". Compile and run the program:

{cs1:~} gcc -o means means.c -lm
{cs1:~} ./means
Please enter 2 positive numbers : 10 8
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 1
The arithmetic mean is 9.000000.
{cs1:~} ./means
Please enter 2 positive numbers : 10 8
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 2
The geometric mean is 8.944272.
{cs1:~} ./means
Please enter 2 positive numbers : 10 8
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 3
The harmonic mean is 4.444445.
{cs1:~} ./means
Please enter 2 positive numbers : 10 8
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 6
Not a valid command.

Calculating mean, using switch instead of if

While comparing choice variable we were checking equality between the variable instr and values 1, 2 and 3. For this type of scenario, where one variable is checked whether it is equal to some integers, the "switch" construct is more easy to use. The general syntax of "switch" construct is:

switch( N )
{
        case Value1:
                Statements1;
                break;
        case Value2:
                Statements2;
                break;
        ...
        case ValueN:
                StatementsN;
                break;
        default:
                Statements;
}

Here the variable N is checked for equality with Value1, Value2, ... , ValueN. If it is equal to any of those values, corresponding statement in the block gets executed. If none of the matches, then the "default" block gets executed. Note that the "break" at the end of each block is needed.

Type the code:

// means2.c

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

main() {
        float a,b;
        int instr;
        printf("Please enter 2 positive numbers : ");
        scanf("%f %f",&a, &b);
        printf("1 - Arithmetic Mean\n2 - Geometric Mean\n3 - Harmonic Mean\nChoice : ");
        scanf("%d",&instr);
        // Compare instr for equality with 1, 2 and 3
        switch(instr) {
        case 1 : printf("The arithmetic mean is %f.\n",(a+b)/2);
                break;
        case 2 : printf("The geometric mean is %f.\n",sqrt(a * b));
                break;
        case 3 : printf("The harmonic mean is %f.\n",1/(1/a + 1/b));
                break;
        default : printf("Invalid instruction.\n");
        }
}

Save the file as "means2.c". Compile and run:

{cs1:~} gcc -o means2 means2.c -lm
{cs1:~} ./means2
Please enter 2 positive numbers : 5 7
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 1
The arithmetic mean is 6.000000.
{cs1:~} ./means2
Please enter 2 positive numbers : 5 7
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 2
The geometric mean is 5.916080.
{cs1:~} ./means2
Please enter 2 positive numbers : 5 7
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 3
The harmonic mean is 2.916667.
{cs1:~} ./means2
Please enter 2 positive numbers : 5 7
1 - Arithmetic Mean
2 - Geometric Mean
3 - Harmonic Mean
Choice : 9
Invalid instruction.

Simple loop

Looping is mostly done in C programs by "for" loop. The general syntax of a "for" loop is:

for ( Initialization ; Condition; Post-operation )
{
        Statements;
}

Above, we see that a "for" loop has four parts: Initialization, Condition, Statements and Post-operation. At the beginning, the statement (s) in the Initialization part is executed only once. After that, the Condition expression is evaluated, if it results in true, then the Statements in the body of the "for" loop are executed. Then, statement (s) in the Post-operation part gets its turn to run. After this first iteration, the execution goes like this Condition -> Statements -> Post-operation -> Condition ... until the condition becomes false. An example will make it clear:

// simple_loop.c
#include<stdio.h>

main()
{
        int i;

        // The variable i is used to control the number of iteration of the loop here
        // At first, it gets initialized to 1
        // In the condition part, it is checked whether it is less than or equal to 10
        // In the body, there is a simple printf statement which prints the word "Looping" in each iteration
        // The value of i is also being printed to help better understand
        // In the post-operation part, i's value is incremented by 1; "i++" is actually a short-hand notation of i = i + 1
        for(i = 1; i <= 10; i++)
        {
                printf("Looping %d\n", i);
        }
}

Save the file as "simple_loop.c". Compile and run:

{cs1:~/} gcc -o simple_loop simple_loop.c
{cs1:~/} ./simple_loop
Looping 1
Looping 2
Looping 3
Looping 4
Looping 5
Looping 6
Looping 7
Looping 8
Looping 9
Looping 10

Another "for" loop example

This is another example of the for loop. It prints squares and cubes of all numbers from 1 to 20:

// squares_cubes.c
#include<stdio.h>

main()
{
        int i, j, k;

        for(i = 1; i <= 20; i++)
        {
                // Calculate square
                j = i * i;
                // Calculate cube
                k = i * i * i;
                printf("%d %d %d\n", i, j, k);
        }
}

Save the code as "squares_cubes.c". Compile and run:

{cs1:~} gcc -o squares_cubes squares_cubes.c
{cs1:~} ./squares_cubes
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
11 121 1331
12 144 1728
13 169 2197
14 196 2744
15 225 3375
16 256 4096
17 289 4913
18 324 5832
19 361 6859
20 400 8000

While loop

"while" loop is another kind of loop. It has less parts than "for" loop. The general syntax:

while ( Condition )
{
        Statements;
}

In every iteration, the condition is evaluated first, if it is true, the body containing the statements will be executed. The following example illustrates it, it takes input an integer and prints largest power of 2 which is less than that integer:

// power_two.c
#include<stdio.h>
#include<math.h>        // Needed for pow function

main()
{
        int k;
        float n;

        printf("Enter k: ");
        scanf("%d", &k);
        n = 0;
        // Condition will be true until 2 to the power n is not less than k
        // pow function takes two values as arguments
        // It returns the first value raised to the power of second value, i.e. pow(3, 4) = 81
        while(pow(2., n) < k)
                n++;
        printf("Largest power of 2 < %d is %d.\n", k, (int) pow(2., n - 1));
}

Save the file as "power_two.c". Compile and run:

{cs1:~} gcc -o power_two power_two.c -lm
{cs1:~} ./power_two
Enter k: 90
Largest power of 2 < 90 is 64.

The same problem can be solved without using the function "pow":

// power_two2.c
#include<stdio.h>

main()
{
        int k, pow_of_2;

        printf("Enter k: ");
        scanf("%d", &k);
        pow_of_2 = 1;
        while(pow_of_2 < k)
                pow_of_2 = 2 * pow_of_2;
        printf("Largest power of 2 < %d is %d.\n", k, pow_of_2 / 2);
}

Save the file as "power_two2.c". Compile and run:

{cs1:~} gcc -o power_two2 power_two2.c
{cs1:~} ./power_two2
Enter k: 10
Largest power of 2 < 10 is 8.

Do-While loop

"do-while" loop is the third kind of loop in C. The general syntax:

do
{
        Statements;
} while ( Condition );

Here, first, the statements get executed first, then the condition is checked. If it is true, the statements are executed again, otherwise the loop ends. Here is an example, it takes a series of positive real number input and prints out the biggest found:

// do_while.c
#include<stdio.h>

main()
{
        float item, biggest;

        // This variable is used to keep track of the biggest value found, here it is initialized to zero
        biggest = 0;
        do
        {
                printf("Enter a positive number or 0 to quit: ");
                scanf("%f", &item);
                if (item > biggest)
                        biggest = item;
        } while(item != 0);        // Loops until user inputs zero
        printf("Biggest found was %f.\n", biggest);
}

Save the file as "do_while.c". Compile and run:

{cs1:~} gcc -o do_while do_while.c
{cs1:~} ./do_while
Enter a positive number or 0 to quit: 2.6
Enter a positive number or 0 to quit: 9.9
Enter a positive number or 0 to quit: 111.25
Enter a positive number or 0 to quit: 81.4
Enter a positive number or 0 to quit: 1.2
Enter a positive number or 0 to quit: 0
Biggest found was 111.250000.

A Graphical Debugger

A debugger is a very essential utility for programmers. It allows programmers to see what is going on "inside" another program while it executes or what another program was doing at the moment it crashed. Hence, it is extremely useful to find out problems in our codes. Unix has a debugger gdb which runs in command line mode. However, it is a hard task to memorize all its commands. Also, debugging in a terminal is not much easy task. To help out, there is another utility program ddd which runs on top of gdb and gives us a convenient easy to use graphical user interface. If you are interested in it, you can visit an introductory tutorial via the link below:

http://www.gnu.org/software/ddd/manual/html_mono/ddd.html