C Info

(Quick Reference)


Introduction


C Standard Library

References:


The Program Development Cycle

The Program Development Cycle for an application program written in C is summarized below :

1. Creating a program - Use a text editor to create or modify the source program. To identify your program as a C program, UNIX expects you to store your program in a file whose name ends in .c

(Remark: You can use any available editor. For example:  Emacs, Xemacs, pico or vi.).

2. Compiling the Program - As follows find four ways to achieve this, though the three first eventually rely on the compiler (called cc on our system), and the last one rely on another compiler. Just choose one of them.

a) Using C Compiler  < cc > - This is the simplest method. Just type:

> cc [-options] filename.c     (To check all options type man cc)

This will try to compile filename.c, and, if successful, will produce a runnable file called a.out. If you want to give the runnable file a better name you can type:

> cc filename.c -o filename

This will compile filename.c, creating runnable file filename. (It is better keep the same name for the source and the runnable programs.)

b) Using a Program Builder < make > - UNIX also includes a very useful program called make. Make allows very complicated programs to be compiled quickly, by reference to a configuration file (usually called Makefile). If your C program is a single file, you can usually use make by simply typing:

> make [-options] filename         (To check all options type man make).

This will compile filename.c and put the executable code in filename.

c) Using Improved Type Checking < lint > - The checker called lint will not generate any runnable code. You can use it, typing:

> lint [-options] filename.c   (To check all options type man lint).

Lint is very good at detecting errors which cause programs to crash at run time. A disadvantage of lint is the fact that lint generally produces a long list of messages about minor problems with the program.  Experience will teach you how to distinguish the important messages from those which can be ignored.

Comments:

The order of the options may be changed. You could type: cc -o filename filename.c.

Care about the options

Use the extension .out to name your runnable (or executable) files. It will help you to distinguish your files

d) Using the GNU Compiler < gcc > - GCC is a free compiler collection for C, C++, Fortran, Objective C and other languages. It is also available in our server. GCC works very similar than CC.

> gcc [-options] filename.c     (To check all options type man gcc).

3.  Running the progam - To run a program under UNIX you simply type a.out or , in case you gave a better name, just type the filename.

>a.out             (If you did not give a better name.)
 OR
> filename.out  (Use the same extension you choose during the compilation step. In our case .out.
                         If you did not choose any extension, just type filename)

You will see your prompt again after the program is done. If logical or run-time errors are encountered when the program is executed, it will be necessary to return to step 1, correct the errors and repeat steps 2 and 3.


Example: A simple program.

1. Creating a program.
>pico hello.c and type the following code:

#include <stdio.h>

main()
{
        printf("Hello World !! This is a C program !! \n");
}
 

2.  Compiling the Program, using C Compiler cc.
>cc hello.c -o hello.out

3.  Running the progam. - To run a program under UNIX you simply type in the filename.
>hello.out

The program will print the message and you will see your prompt again after the program is done.
 

Hello World !! This is a C program !!
>


[back]


C - Quick Reference

Structure of a C Program

  • Every C program contains a function called main, and must appear once, and only once in every C program. The function main is the start point of the program, but it does not have to be the first statement in the program. Because main is a function is must be followed by a pair of parentheses - main().
  • Normally the first line is #include <stdio.h>. It allows the program to interact with the screen, keyboard and file system of your computer. You will find it at almost every C program. It is a preprocessor directive.
  • The curly brackets, or braces, show the start and the end of the function main().
    /* 
        This is a comment.
    */
    #include <stdio.h>
    main()
    {
      ....;
    }

    Separating Statement

  • The semicolon (;) is used as a statement separator. It signals to the compiler that a statement is complete.
    Grouping Statements
  • Curly brackets, or braces, ({ and }) are used to group statements together as in a function, or in the body of a loop or selection. It is known as a compound statement or a block.
    Comments
  • Explanations about a program's operation are called comments. C Language uses the slash star combination as comments delimiters, (/* and */).
    Keywords
  • There are some words reserved by the C Language and they are defined as keywords.
  • They have a predefined meaning and can be used only for their intended purpose.
  • They can not be arbitrarily redefined by the programmer.
  • They are always written in lower case.
  • In ANSI/ISO C Language, there are 32 keywords. A complete list follows:
    auto break case char const continue default do
    double else enum extern float for goto if
    int long register return short signed sizeof static
    struct switch typedef union unsigned void volatile while
  • In addition to this list of keywords, your compiler may define a few more. For further information, check the documentation of your compiler.
    Identifiers
  • An identifier is a name that is given to some program element, such as a constant, a variable, a function, a data definition, etc.
  • C is case sensitive, that is, a lower case letter and it's upper case are different. Most C programs are in lower case letters. Usually upper cases are found in preprocessor definitions, constants or inside quotes as parts of character strings.
  • They consist of letters, digits and underscore ( _ ) characters, in any order, except that the first character must be a letter or an underscore. Since most compiler writers use the underscore as the first character for variable names internal to the system, it is not recommended to use underscore to begin an identifier to avoid the possibility of a name clash.
  • They should contain enough characters so that its meaning is readily apparent (mnemonic). On the other hand, an excessive number of characters should be avoided. The Common C considers significant only the first 8 characters of an identifier. Most modern ones do not apply this limit though. The ANSI C considers the first 31 characters. To be sure about this matter, check the documentation of your compiler.
  • Keywords, or reserved words, can not be used as identifiers.
  • The following names are examples of valid identifiers:
      abc         total           counter       factorial       power 
      sum        x1              x2              in_file          out_file
  • The following names are examples of not valid identifiers for the reasons stated.
    c-max 
    4thValue 
    while 
    last word
    Characters other than letters and digits are not allowed.
    The first character must be a letter.
    while is a reserved word. (See Appendix A).
    Blank spaces are not allowed (a blank space is a character).

     Data Types

  •  C Language provides various data types. The most common are:
    - int    - store integers – the positive and negative counting numbers.
                (e.g. -234,-1,0,1,234).
    - float - store floating points numbers - i.e. including decimal points, or are expressed as powers of 10.
                (e.g. -3.5, 0.0, 1E-02, 4.5E02, 6.02e+23).
    - char - store a single byte of memory, enough to hold any of the characters - letters, punctuation marks, digit and
                special characters - that appear on the character set.
                (e.g. ‘a’,’$’,’3’).
               Special characters are represented by special patterns. A backslash leading a (sequence of) character(s).
               A list of them follows:
    C code Meaning
    \b
    \f 
    \n
    \r
    \t
    \\
    \' 
    \" 
    \0
    Backspace
    Form Feed
    Newline (linefeed + carriage return)
    Carriage Return
    Tab
    Backslash
    Single quote
    Double Quote
    NULL
  • They are also several variants on these types. A list follows:
    - short - An integer, possibly of reduced range.
    - long  - An integer, possibly of increased range.
    - unsigned  - An integer with no negative range, the spare capacity being used to increase the positive range.
    - unsigned long  - Like unsigned, possibly of increased range.
    - double - A double precision floating point number.
  • All of the integer types plus the char are called the integral types. Float and double are called the real types.
    Constants
  • A C constant is usually just the written version of a number. (e.g. 1, 0, 9.734, 12.3e4). It is possible to specify our constants in octal or hexadecimal, or force them to be treated as long integers.
  • Octal constants are written with a leading 0 (zero). e.g.  023.
  • Hexadecimal constants are written with a leading 0x (zero and x). e.g. 0x123abc.
  • Long constants are written with a trailing L. e.g. 450L.
  • Character constants are usually just the character enclosed in single quotes; 'a', 'b', 'c'. Excepted those special characters, represented by a sequence of characters leaded by a backslash. (e.g. '\n', '\\').
  • String constants are more convenient than character constants. A string constant is enclosed by double quotes, e.g. "This is a string". The string is actually stored as an array of characters. The null character '\0' is automatically placed at the end of such a string to act as a string terminator.
  • Remember that a character is a different type to a single character string.
    Symbolic Constants
  • Symbolic constants are conventionally written in upper case so they can be distinguished from variables names.
  • There is no semicolon at the end of a #define statement.
  • Use meaningful names to symbolic constants in order to let programs more readable.
  • The syntax is:
    #define <name> <replacement text/value>
  • For example:
    #define city "Macau"
    #define tax 1.5
    #define step 20

    Variables

  • In C, a variable must be declared before it can be used. Conventionally, variables names are written in lower case.
  • A variable declaration begins with the type, followed by the name (see Identifiers) of one or more variables. For example,
    int a, x, counter;
    char letter;
    float average;
  • A variable can also be initialized when it is declared. Just add an equals and the value after the declaration. For example:
    int counter=1; 
  • It is equivalent to:
    int counter; 
    counter = 1;
  • Variable declarations can be spread out, allowing space for comments. For example:
    int total;            /* Total of salaries           */
    int marks[10]    /* Series of input marks  */
    char letter;        /* Letter grade                */
    float average;    /* Average of sales          */
  • Variables can be declared at the beginning of any block of code, but most are found at the beginning of each function.
    Scope of Variables
  • Global Variables
    - They are available to all functions, but excessive use of them is not recommended in order to avoid poor program structure.
    - They are located outside any of the program's functions. Usually at the beginning of the program file, but after preprocessor directives.
    - They do not need to be declared again in the body of the functions which access them.
  • Local variables
    - They are declared within the body of a function, and can only be used within that function.
    - Most local variables are created when the function is called, and are destroyed on return from that function.
    - Data can be passed between functions as arguments.
    - Local variables takes precedence over a like-named global variable.
    Class of Variables
  • External Variables
    - Where a global variable is declared in one file, but used by functions from another, then the variable is called an external variable in these functions, and must be declared as such.
    - The declaration must be preceded by the word extern. Compare the following example:
    #include <stdio.h>
    int a = 123;       /* global variable */
    main()
    {
      printf ("%d\n%d\n",a,b);
    }
    int b = 456;      /* global variable */
    #include <stdio.h>
    int a = 123;       /* global variable */
    main()
    {
       extern int a,b;
       printf ("%d\n%d\n",a,b);
    }
    int b = 456;       /* global variable */
    >cc test.c
    >"test.c", line 7: undefined symbol: b
    cc: acomp failed for test.c
    >
    >
    > cc test.c
    >a.out
    123
    456
    >

    - Global and external variables can be of any legal type. They can be initialized, but the initialization takes place when the program starts up, before entry to the main function.
    - It is also recommended to avoid using external variables.

  • Static Variables
    - Like local variables, static variables can only be accessed from the function in which they were declared.
    - Instead of destroying their values on exit from the function, static variables preserve their values, and make them available again when the function is next called.
    - Static variables are declared as local variables, but the declaration is preceded by the word static.
    - Static variables can be initialized as normal, the initialization is performed once only, when the program starts up. For example:
    {
    static int a;
    static sum=0;
    float pi=3.14;
    }
  • Automatic Variables
    - By default, if a variable does not have a class, the compiler will assume as automatic variable.
    - Like local variables, automatic variables can only be accessed from the function in which they were declared.
    - The declaration must be preceded by the word auto, but nowadays they seldom appear in C programs.
  • Register Variables
    - They are used as automatic variables. It is not recommended because they are confuse and do not give any advantage.
    - The purpose is to store values direct in the registers and not in the memory of the computer. But, it does not work as planned. In some machines, it can not be implemented and the compiler and the language have problems to manage them.
    Arrays
  • An array is a collection of variables of the same type.
  • Within an array, elements are identified by an integer index. The index begins at zero and is always written inside square brackets.
  • Arrays can have one or more dimensions. Each index has its own set of square brackets. For example:
    int numbers[20];                      /* this is a single-dimension array */
    int numbers_2d[20][5];             /* this is a two-dimension array    */
    int numbers_3d[20][5][3];         /* this is a three-dimension array */
  • Where an array is declared in the main function it will usually have details of dimensions included.
  • When passed as an argument to a function, the receiving function need not know the size of the array. So for example if we have a function which sorts a list (represented by an array) then the function will be able to sort lists of different sizes. The drawback is that the function is unable to determine what size the list is, so this information will have to be passed as an additional argument. As an example, here is a simple function to add up all of the integers in a single dimensioned array.
    int add_array(int array[], int size)
    {       int i;
            int total = 0;

            for(i = 0; i < size; i++)
                    total += array[i];

            return(total);
    }

    Strings

  • A string is a group of char type data - letters, digits or special characters - terminated by a null character.
  • A string is simply a special case of an array, a series of char type data.
    Operators and Expressions
  • Arithmetic operators
    - The most common arithmetic operators:
    +
    -
    *
    /
    %
    Addiction
    Subtraction
    Multiplication
    Division
    Modulo Reduction (Remainder from Integer Division)

    - The operators *, / and % will be performed before + or - in any expression.
    - Parentheses or brackets change the order of evaluation, because a sub-expression within parentheses gets evaluated before the rest of the expression. In nested expression, calculations are done from the inside out.
    - Where division is performed between two integers, the result will be an integer, with remainder discarded.
    - Modulo reduction works with integers.
    - Division by zero, will cause an error, usually causing the program to crash.
    - Examples of arithmetic expressions used within assignment statements:

    sum=sum + number;
    counter=counter + 1;
    area = pi * radius * radius;

    - C has some operators which allow abbreviation of certain types of arithmetic assignment statements.

    Operator Shorthand Equivalent to 
    Increment 
    Decrement
    ++i;  or   i++;
    --i;    or   i--;
    i = i + 1;
    i = i - 1;

    - These operations are usually very efficient and they can be combined with another expression.
    - Care about where the operator occurs. These can cause confusion if you try to do too many things on one command line. Restrict the use of the increment and the decrement operators to ensure that your programs stay readable. As follows some examples:

    Expression Equivalent to
    a = b * c++; a = b * c;
    c = c + 1;
    a = b * ++c ; c = c + 1;
    a = b * c;

    Another shorthand notation is listed below:

    Expression Equivalent to
    a += 10
    a -= 10
    a*= 10
    a /= 10
    a = a + 10
    a = a - 10
    a = a * 10
    a = a / 10
  • Relational and Logical Operators
    - C Language has no special type to represent logical or Boolean values.
    - The Relational and Logical Operators are used to compare two numeric values and produce a logical result.
    - As follows, a list with those operators:
    Relational Operators Meaning
    >
    >=
    <
    <=
    ==
    !=
    greater than
    greater than or equal
    less than
    less than or equal 
    equal 
    not equal
    Logical Operators Meaning
    &&
    ||
    !
    AND
    OR
    NOT
  • Bitwise Operators
    - C Language provides six operators for bit manipulation.
    - These operators may only be applied to integral types, that is: char, short, int, and long, whether signed or unsigned.
    - As follows, a list with these operators:
    Bitwise Operators Meaning
    &
    |
    ^
    <<
    >>
    ~
    bitwise AND
    bitwise inclusive OR
    bitwise exclusive OR
    left shift
    right shift
    one's complement (unary)
  • Precedence and Associativity of Operators
    - The following table summarizes the rules for precedence and associativity of all operators. Operators on the same line have the same precedence; rows are in order of decreasing precedence.

    Operators

    Associativity

    ( )   [ ]   ->    .
    !   ~  ++   --   +   -   *   (type)  sizeof
    *   /   %
    +   -
    <<   >>
    <   <=   >   >=
    ==   !=
    &
    ^
    |
    &&
    ||
    ?:
    =   +=   -=   /=   %=   ^=   |=   <<=   >>=
    .
    left to right
    right to left
    left to right
    left to right
    left to right
    left to right
    left to right
    left to right
    left to right
    left to right
    left to right
    left to right
    right to left
    right to left
    left to right

    Conditional Expressions

  •  Conditional expressions are written with the ternary operator (?:).
  •  The expression expr1 is evaluated first. If it is non-zero (true), then the expression expr2 is evaluated, and that value is the value of the conditional expression. Otherwise expr3 is evaluated, and that is the value. Only one of expr2 and expr3 is evaluated.
  • The syntax is:
    expr1 ? expr2 : expr3
  • For example: (The three forms are equivalent.)
    largest = (a > b) ? a : b; 

     

    z = max(a,b);

     

    if (a>b) 
        z=a;
    else
        z=b;
  • It could be used wherever any other expression can be. For example:
    printf ("You have %d  items%s.\n", n, n==1 ? "" : "s");

    Assignment Statement

  •  It is the most frequently used statement in programming.
  •  The assignment operator (=) changes the value of a variable within a program – to initialize, or to alter its current value.
  •  A variable must be initialized, or given a starting value, before it can appear in an expression. The variable is undefined until it is initialized. The syntax is:
    Variable identifier = the value represented by an expression
  • For example:
    age = 18 ;
    firstletter = ‘A’ ;
    sum=0;
    area = radius*radius*pi ;
    a=b+1;

    Type conversion
    - You can mix the types of values in your arithmetic expressions. char types will be treated as int. Otherwise where types of different size are involved, the result will usually be of the larger size, so a float and a double would produce a double result. Where integer and real types meet, the result will be a double.
    - There is usually no trouble in assigning a value to a variable of different type. The value will be preserved as expected except where;

    - Values passed as function arguments must be of the correct type. The function has no way of determining the type passed to it, so automatic conversion cannot take place. This can lead to corrupt results. The solution is to use a method called casting which temporarily disguises a value as a different type.

    Example: The function sqrt finds the square root of a double. 

    int i = 256;
    int root
    root = sqrt( (double) i);

    Explanation:
    The cast is made by putting the bracketed name of the required type just before the value. (double) in this
    example. The result of sqrt( (double) i); is also a double, but this is automatically converted to an int on
    assignment to root.

    Control Structures

  • Statements and Blocks
    - Use semicolon (;) to terminate a statement and braces ({ and }) to group statements.
  • If-Else Statement
    - The if-else is a selection statement. It is used to express decisions.
    - Multi-way decision can represented by a sequence of if-else statements. (See example 3)
    - The syntax is:
    if (expression)
        statement_1;                  /* if expression is true perform statement_1 */
    else
        statement_2;                  /* if expression is false perform statement_2 */
  • For example:
    if (a > b)
        max = a;
    else
        max = b;
    if (counter <=10) {
        sum += counter;
        counter ++;
    }
    if (a > b)  {
         max = a;
         min = b;
        }
    else {
         max = b;
         min = a;
        }
    if (result >= 90)
            printf("Grade A\n");
    else if (result >= 70)
            printf("Grade B\n");
    else if (result >= 50)
            printf("Grade C\n");
    else
            printf("Failed\n");
  • Switch Statement
    - This is another form of the multi-way decision. It tests whether an expression matches one of a number of constant integer values, and branches accordingly.
    - The syntax is:
    switch (expression) {
        case constant_expression : statements
        case constant_expression : statements
        ...
        default: statements                                           /* default is an optional */
        } 
  • For example:
    switch(number) {
            case 0:
                    printf("Zero\n");
                    break;                     /* the break statements causes an immediate exit from the switch   */
           case 1:                              /* case serves just as labels, without the break, the execution will    */
                    printf("One\n");         /* falls through to the next unless you take explicit action to escape*/
                    break;
           case 2:
                    printf("Two\n");
                    break;
           case 3:   case 4:               /* No break statement, the execution continue on allowing the    */
           case 5:                             /*    same action for case 5.                                                         */
                    printf("Several\n");
                    break;
            default :
                    printf("Many\n");
                    break;
            }
  • While Statement
    - The while loop keeps repeating an action until an associated test returns false. This is useful where the programmer does not know in advance how many times the loop will be traversed.
    - The syntax is:
    while (expression
             statement;
  • For example:
    while (i < 10)
        printf("%d\n",i++);
    printf("We are out of the loop".\n"); 
    while (i < 10) {
        printf("%d\n",i++);
        printf("We are in the loop".\n");
    }
  • Do-While Statement
    - The do while loops is similar, but the test occurs after the loop body is executed. The loop will always run at least once.
    - The syntax is:
    do
        statement
    while (expression);
  • For example:
    do 
       printf("%d\n",i++);
    while (i < 10);
    printf("We are out of the loop".\n");
    do {
        printf("%d\n",i++);
        printf("We are in the loop".\n");
    }  while (i < 10);
  • For Statement
    - The for loop is frequently used, usually where the loop will be traversed a fixed number of times. It is very flexible, and novice programmers should take care not to abuse the power it offers.
    - Commonly expression1 is the initial value of the loop variable; expression2 is a test, when it becomes true the loop stops; and expression3 is the increment of the loop counter.
    - But, any of the three parts can be omitted, although the semicolons must remain. In this case, in order to avoid an infinite loop, the programmer must break by other means, such as a break or return.
    - The syntax is:
    for (expression1;expression2;expression3)
           statement
  • For example:
    for (i=1; i <10; i++)
       printf("%d\n",i++);
    printf("We are out of the loop".\n");
    for (i=1; i <10; i++) {
       printf("%d\n",i++);
       printf("We are in the loop".\n");
    }
  • Break Statement
    - It is used to exit from a loop or a switch, control passing to the first statement beyond the loop or a switch.
  • For example:
    int i=0;
    while (++i <=9) {
       if (i==5)
           break;
           printf("%d\n",i);
    }
    The output will be:
    1
    2
    3
    4
    >
  • Continue Statement
    - It only works within loops where its effect is to force an immediate jump to the loop control statement.

    - Like a break, continue should be protected by an if statement. It is not recommended to use it. For example:

    int i=0;
    while (++i <=5) {
       if (i==3)
           continue;
           printf("%d\n",i);
    }
    The output will be:
    1
    2
    4
    5
    >
  • Goto Statement
    - C has a goto statement which permits unstructured jumps to be made. Its use is not recommended.
    Basic I/O
  • UNIX supplies a header for performing input and output to files or the terminal.
  • All headers of the standard library, are listed in C Standard Library.
  • To use them, your program must include the name of the header, near the start of the program file. For example:
    #include <stdio.h>    /* Standard Input and Output Library Functions */
  • If you do not do this, the compiler may complain about undefined functions or datatypes.
  • Getchar reads the next input character from a text stream and returns that as its value. The characters come from the keyboard.That is, after c = getchar(), the variable c contains the next character of input.
  • Putchar puts its character argument on the standard output (usually the screen).
  • Examples: Write a program that copies its input to its output one character at a time. Compare both ways to write it.
    #include <stdio.h>
    main()
    {
             int ch;
             ch=getchar();
             while (ch != EOF)  {
                       putchar(ch);
                       ch = getchar();
             }
    }
    #include <stdio.h>
    main()
    {
             int ch;
             while (( ch=getchar() ) != EOF ) 
                       putchar(ch);
    }
     

     

    Comments: 
    - EOF can be generated by typing Ctrl - d
    - Use Ctrl - c to stop the execution of the program.
    Comments: 
    - EOF can be generated by typing Ctrl - d
    - Use Ctrl - c to stop the execution of the program.
  • The following example program converts any typed input into capital letters.
    #include <ctype.h>        /* For definition of toupper - a function to convert lower case to upper case*/
    #include <stdio.h>         /* For definition of getchar, putchar, EOF */
    main()
    {
             int ch;
             while ((ch=getchar()) != EOF) 
                       putchar(toupper(ch));
    }
    Comments: 
    - EOF can be generated by typing Ctrl - d
    - Use Ctrl - c to stop the execution of the program.
  • Scanf  allows formatted reading of data from the keyboard. It has a control string, followed by the list of items to be read.
  • However scanf wants to know the address of the items to be read, since it is a function which will change that value. Therefore the names of variables are preceeded by the & sign.
  • Character strings are an exception to this. Since a string is already a character pointer, we give the names of string variables unmodified by a leading &.
  • Type man scanf for details of all options on your system. As follows a summary of them.
    Format specifiers Meaning
    %d 
    %ld
    %c 
    %s 
    %u
    %f 
    %e 
    %g 
    %o 
    %x 
    %%
    read an int argument in decimal
    read a long int argument in decimal
    read a character
    read a string
    read an unsigned decimal integer
    read a float or double argument
    same as %f, but use exponential notation
    use %e or %f, whichever is better
    read an int argument in octal (base 8)
    read an int argument in hexadecimal (base 16)
    read a literal %, no assignment is made.
  • For example:
  • To read an integer value, just type:
         int n;
         scanf("%d", &n);
  • To read input lines that contains dates of the form:  01 Jan 2001, type:
            int day, year;
            char month[12]
            scanf("%d %s %d", &day, month, &year); 
  • To read input lines that contains dates of the form:  31/01/2001, type: 
            int day, month, year;
            scanf("%d/%d/%d", &day, &month, &year); 
  • Comment:
  • The arguments of scanf must be pointers. You must use the symbol & before the variable name.
  • By far the most common error is writing
                     scanf("%d", n); 
       instead of 
                     scanf("%d", &n);
  • This error is not generally detected at compile time.
  • Printf's name comes from print formatted. Its arguments are, in order; a control string, which controls what gets printed, followed by a list of values to be substituted for entries in the control string.
  • Type man scanf for details of all options on your system. As follows a summary of them.
    Format specifiers Meaning
    %d, %i 
    %ld
    %c 
    %s 
    %u
    %f 
    %e 
    %g 
    %o 
    %x, %X 
    %%
    print an int argument in decimal
    print a long int argument in decimal
    print a character
    print a string
    print an unsigned int decimal number
    print a float or double argument
    same as %f, but use exponential notation
    use %e or %f, whichever is better
    print an int argument in octal (base 8)
    print an int argument in hexadecimal (base 16)
    no argument is converted, print a single %
  • For example:
  • Suppose s is the string "hello,  world"
    printf("%s\n",s);
    printf("%10s\n", s);
    printf("%.10s\n",s);
    printf("%-10s\n",s);
    printf("%.15s\n",s);
    printf("%-15s\n",s);       /* - means right justified */
    printf("%15.10s\n",s);
    printf("%-15.10s\n",s);
  • The output 
    :hello, world:
    :hello, world:
    :hello, wor:
    :hello, world:
    :hello, world:
    :hello, world:
    :     hello, wor:
    :hello, wor:
  • Suppose float f=1234.1234 and int n=12345678;
    printf("%f\n",f);         /* by default, 6 decimal places */ 
    printf("%d\n",n);
    printf("%8.2f\n",f);     /*8 spaces wide with 2 decimal places */ 
    printf("%8.2f\n",n); 
    printf("%6.4f\n",f);    /*6 spaces wide with 4 decimal places */
    printf("%6d\n",n);
    printf("%12.6f\n",f);
    printf("%d\n",f);

  • :1234.123413:
    :12345678:
    :1234.12:
    :    0.00:
    :1234.1234:
    :12345678:
    : 1234.123413:
    :1083394174:
    Comments:
  • The colons around each output is only to show its extent.
  • Notice the red output, the types are wrong, then the values are not the required ones.
  • By default, the number of decimal places is 6. Our four decimal places number will be complemented by the computer.
  • gets reads a whole line of input into a string until a newline or EOF is encountered. It is critical to ensure that the string is large enough to hold any expected input lines. When all input is finished, NULL as defined in stdio.h is returned.
  • puts writes a string to the output, and follows it with a newline character.
  • For example:  A program which uses gets and puts to double space typed input.
    #include <stdio.h>
    main()
    {       char line[256]; /* Define string sufficiently large to 
                                store a line of input */

            while(gets(line) != NULL)   /* Read line        */
            {        puts(line);        /* Print line       */
                     printf("\n");      /* Print blank line */
            }
    }

  • Note that putchar, printf and puts can be freely used together. So can getchar, scanf and gets.
    Functions
  • Almost all programming languages have some equivalent of the function. There are many alternative names such as subroutine or procedure. For example, in Pascal and Modula-2 we have functions and procedures.
  • C assumes that every function will return a value. If the programmer wants a return value, this is achieved using the return statement. If no return value is required, none should be used when calling the function.
  • Even the main() function may return a value to its caller, which is in effect the environment in which the program was executed. Typically, a return value of zero implies normal termination; non-zero values signal unusual or erroneous termination condition.
  • The syntax form is:
    return-type  <function-name> (argument declarations)
  • The function prototype declaration is found just before the main(). It has to to agree with the definition and uses of the function. Parameters names need not to agree and they are optional in a function prototype. For example:
    #include <stdio.h>
    int example(int a, int b);  /*function prototype declaration*/
    main( )
    {
       ...
    }
    example(int x, int y)
    {
      ...
      return value;
    }
    #include <stdio.h>
    int example(int , int);  /*function prototype declaration*/
    main( )
    {
       ...
    }
    example(int x, int y)
    {
      ...
      return value;
    }
  • Here is a function which raises a double to the power of an unsigned, and returns the result.
    double power(double val, unsigned pow)
    {       double ret_val = 1.0;
            unsigned i;

            for(i = 0; i < pow; i++)
                    ret_val *= val;

            return(ret_val);
    }

  • The example function can be called by a line in another function which looks like this
    result = power(val, pow); /*This calls the function power assigning the return value to variable result. */
    or
    printf("%f", power(val,pow)); /* This prints the function power. */
  • The definition uses type void which is optional. It shows that no return value is used. Otherwise the function is much the same, except that there is no return statement.
  • Some void type functions might use return, but only to force an early exit from the function, and not to return any value. This is rather like using break to jump out of a loop.
  • The word void is used when a function does not return a value. Just type it, instead of the return-type.
    void <function-name> (<argument declarations>)

    Scope of Function Variables

  • Local variables are declared within a function. They only exist during the execution of the function.
  • Static variables are slightly different, they retain the last value and the value becomes available when the function is called again.
  • Variable declared within the calling function can not be accessed by the called function unless they are passed as arguments. Values  passed as arguments are also treated like local variables.
  • Global variables could also be used. Their values are retained, and is available to any other function which access them.
    Modifying Function Arguments
  • In C, the values of arguments can not be changed by direct manipulation. But, there is a way to change the values of variables declared outside the function. It is done by passing the addresses - or pointers - of variables to the function. (See an example in Pointers).
    Recursive Functions
  • A recursive function is one which calls itself. Recursive functions are useful in evaluating certain types of mathematical function. You may also encounter certain dynamic data structures such as linked lists or binary trees. Recursion is a very useful way of creating and accessing these structures.
  • A simple exponentiation function example
    int powers(int base , int exp)
    {
      if (exp == 0)        /*powers(base, 0) =1*/
         return(1);
      else
         return(powers(base, exp - 1) * base);
    }
  • Notice that each of these definitions incorporate a test. 
  • Where an input value gives a trivial result, it is returned directly, otherwise the function calls itself, passing a changed version of the input values. 
  • Care must be taken to define functions which will not call themselves indefinitely, otherwise your program will never finish.
  • If such a function is to be called many times, it is likely to have an adverse effect on program performance. 
  • Recursion could be the simplest solution in some cases. However there is always an alternative iterative solution available too. This will involve the use of a loop structure such as for, while or do-while structures.
    The C Preprocessor
  • C provides certain languages facilities by means of a preprocessor, which is conceptually a separate first step in compilation.
  • There are several features such as #include, #define, #if and others. This reference will discuss only #include and #define.
    #include
     
     

     

    #include "filename

    or

    #include <filename>
     

  • Any source line of the besides form is replaced by the contents of the filename
  • If the filename is quoted, searching for the file begins where the source program was found.
  • If the name is enclosed in < and >, searching follows as inplementation-defined rule to find the file.
  • #define #define name  replacement-text It calls for a macro substitution of the simplest kind. The name will be replaced by the replacement-text.
    #ifdef
    #ifndef
    #ifdef name
    #ifndef name
    They test whether a name is defined.
  • As follows, some examples:
    #include <stdio.h> <stdio.h> is a header and headers are implementation-dependent accessed.
    #include "myfile.h" "myfile.h" is a file.
    #define Maxlength 1000 Constant declaration
    #define max(a,b)  ((a) > (b) ? (a) : (b)) It is a macro called max. 
    So max(a,b) will be substituted by the expression ((a) > (b) ? (a) : (b)). 
    Parameters will be replaced by arguments.

    Pointers in C

  • The unary symbol & gives the address of an object, it is the referencing operator.
  • When applied to a pointer, the unary symbol * is the indirection or de-referencing operator.
  • This symbol accesses the object the pointer points to.
  • Take care not to confuse the many uses of the * sign; Multiplication, pointer declaration and pointer de-referencing.
  • For example:
    int a = 10, b = 20, c[100];
    int *p;                 /* p is a pointer to int */

    p = &a          /* p now points to a - or p is referencing a - or the address of a is assigned to the variable p. */
    b = *p;          /* b is now 10 - or b is de-referencing p */
    *p = 0;          /* a is now 0 */
    p = &c[0];     /* p now points to c[0] */
     

  • If p points to the integer a, then *p can occur in any context where a could, so
    *p = *p + 1;   /* increments *p by 1 */
    b = *p + 1      /* whatever p points at, adds 1, and assigns the result to b */
    *p+=1           /* increments what p points to */
    ++*p             /* same as before */
    (*p)++          /* remember that ++ and * associate right to left, then the parentheses are necessary */
     
  • Pointers and Arrays
    int a[10];
    int x,y ;
    int *pa;

    pa=&a[0];         /* pa points to a[0] - or pa contains the address of a[0] */
    x = *pa;            /* the contents of a[0] into x */
    y = *(pa+1)       /* if pa points to a[0], *(pa+1) refers a[1] */

  • If you wish to use arguments to modify the value of variables from a function, these arguments must be passed as pointers, and de-referenced within the function.
  • Where the value of an argument isn't modified, the value can be passed without any worries about pointers.
  • Compare the following examples:
    swap(a,b);  /* this is just the call */

    void swap(int x, int y)   /* this is the function definition */

       int temp;

       temp = x;
       x = y ;
       y = temp;
    }

    swap(&a&,b);  /*this is just the call */

    void swap(int *px, int *py) /* this is the function definition */

       int temp;

       temp = *px;
       *px =*py ; 
       *py = temp;
    }

    The arguments here will not be affected by the function swap.  The arguments here will be affected by the function swap.
  • Structures
  • A structure is a collection of variables under a single name.
  • These variables can be of different types, and each has a name which is used to select it from the structure.
  • A structure allows to make groups of several pieces of related information together.
  • A structure can be defined as a new named type, thus extending the number of available types, such as int, arrays or even structures.
  • A structure type is usually defined near to the start of the program, just after the #define and #include statements in a file.
  • It could be declared just by using the keyword struct or by using a typedef statement - typedef defines and names a new type, allowing its use throughout the program.
  • Here is an example with both ways.
    struct student {
             char name[30];
             char faculty[50]
             char major [100];
             int age;
             int year;
    };
    typedef struct {
             char name[30];
             char faculty[50]
             char major [100];
             int age;
             int year;
      } student;
  • Declarations of variables of type student, are similar to declarations of int or float variables. For example: student abc;
    - The variable name is abc, it has members called name, faculty, major, age and year.
  • Accessing members of a structure:
    student abc;

    abc.age = 18;  /* It will assign value 18 to member age in the variable abc */

    If we have a pointer to a structure:

    struct point {
            int x;
            int y
    };
    struct point *p;  /* p is a pointer to a structure of type struct point */

    Then *p is the structure and the members are (*p).x and (*p).y, or  just p->x and p->y.

    Remember that *p.x is the same as *(p.x) !!!

  • C File Handling - File Pointers
  • C communicates with files using a new datatype called a file pointer. This type is defined within stdio.h, and written as FILE *. A file pointer called output_file is declared in a statement like
    FILE *output_file;
  • Your program must open a file before it can access it. This is done using the fopen function, which returns the required file pointer. If the file cannot be opened for any reason then the value NULL will be returned. You will usually use fopen as follows
    if ((output_file = fopen("output_file", "w")) == NULL)
               fprintf(stderr, "Cannot open %s\n", "output_file");
  • fopen takes two arguments, both are strings, the first is the name of the file to be opened, the second is
    an access character, which is usually one of:
    r – open file for reading
    w – create file for writing
    a – open file for appending
  • Standard file pointers in UNIX
  • UNIX systems provide three file descriptors which are automatically open to all C programs. These are
    stdin – The standard Input. The keyboard or a redirected input file.
    stdout – The standard  Output. The screen or a redirected output file.
    stderr –The standard Error. This is the screen, even when the output is redirect.
                 This is the conventional place to put any error message.
  • Since these files are already open, there is no need to use fopen on them.
  • The fclose command can be used to disconnect a file pointer from a file. This is usually done so that the pointer can be used to access a different file. Systems have a limit on the number of files which can be open simultaneously, so it is a good idea to close a file when you have finished using it. This would be done using a statement like
    fclose(output_file);
  • If files are still open when a program exits, the system will close them for you. However it is usually better to close the files properly.
  • Reading and writing files - functions fprintf and fscanf a commonly used to access files.
     int fprintf(FILE *stream, char *format, args..)
     int fscanf(FILE *stream, char *format, args..)
  • These are similar to printf and scanf except that data is read from the stream that must have been opened with fopen().
  • The stream pointer is automatically incremented with ALL file read/write functions. We do not have to worry about doing this.
    char *string[80]
    FILE *stream, *fopen();

    if ( (stream = fopen(...)) != NULL)
              fscanf(stream,``%s'', string);

  • Other functions for files:
    int getc(FILE *stream), int fgetc(FILE *stream)
    int putc(char ch, FILE *s), int fputc(char ch, FILE *s)
  • These are like getchar, putchar - getc is defined as preprocessor MACRO in stdio.h. fgetc is a C library function. Both achieve the same result!!
    fflush(FILE *stream) -- flushes a stream.
    fclose(FILE *stream) -- closes a stream.
  • We can access predefined streams with fprintf etc.
    fprintf(stderr,``Cannot Compute!!n'');
    fscanf(stdin,``%s'',string);