C Programming

Streaming Video Lectures On-Demand 

Colin Archibald, Ph.D.
Valencia Community College
Orlando, FL 32811


This is a complete course in the C language.  It uses the the free programming tools from Microsoft - Visual C++ Express. 
It is intended for students who have some background in computer programming.  Beginners are referred to the video lecture course Computer Programming Concepts

Students completing this course will have a solid understanding of the C language, including data types, control structures, operators, arrays, pointers, strings, structs, and file I/O. 

Please send feedback to:  ColinArchibald@acm.org

These videos have moved to YouTube.  
Updates will only be posted there.  Here is a link to the PlayList:

https://www.youtube.com/playlist?list=PL16462912149C15F6





 
Power Point slides that are used in these
     Video Lectures are available here: 

Download PowerPoint Slides
 
  • nSyntax – rules for writing a computer program in a particular language.
  • nErrors in Syntax are called compile-time errors because they are reported by the compiler.
  • nOutput – information that originates in the program and is output to a screen, or a file.
  • nYou must get a simple program to run at this point – all subsequent segments depend on your ability to experiment with the concepts that are introduced.
 
  • Variables and data types 
  • Variable naming rules and conventions
  • Assignment and arithmetic operators, including modulus
  • Integer division – operators also have a data type
 
  • The char data type can be used for small numbers, or the ASCII code of a character

  • The sizeof operator can be used to determine the size of a variable, or a data type.

  • The choice of a data type depends on whether you need character, real or integer data and how large the values might be that you are computing with.


  • The unsigned modifier allows you to use an integer data type for positive values only. 

  • Mixed data type expressions, including cast operators, apply to these new data types in the same way as with int and double.

  • There are different versions of C that have other data types.  C99 is the most recent standard.

  • Operators and literals have a data type.  Operators work on operands of the same type.  

  • The data type of the operators is determined at the time the operator is to be executed


  • The type of the operator is determined by the type of the operands


  • C will promote, to avoid losing data, programmers should demote explicitly


  • Type casting is used to temporarily change the type of a value for the purpose of evaluating an expression
 
  • Output information going from the program to the user

  • Input information going from the user to the program

  • printf and scanf

  • Escape characters are used to control the position of the output cursor, and to output some special characters

  • % sequences, correspond to the variables that are being input or output, and can be modified for formatting the output. 
  • You can specify the data type of the input, and the type and format of the output.

  • Use the documentation for your compiler – search for "Format Specification Fields."

  • Don’t forget the & on the variable name for input!

  • A "Prompt" is a message that tells the user what the program is expecting them to enter.
 
  • Selection – execute lines of code based on a condition
     
  • Relational operators are used to compare two things with a result of TRUE or FALSE
     
  • if statements are used to change the flow of control, the lines of code that will execute
     
  • if statements may have an associated else
     
  • if and else control one statement or one "compound statement" {  }

  • A switch can be used to selectively execute some statements based on the value of a variable, or expression. 

  • The break; statement prevents the execution  from 'bleeding' into the next case.

  • The default case is optional, and if present is executed if none of the other cases match.


  • The cases must all be unique, and constant.


  • Switch cannot be used to compare doubles, or to express a range of values – sometimes you need to use multiple if-else statements.
 
  • There are three logical operators:
     And   &&                        Or    ||                       Not   !
       
  • Can be used to express more interesting conditions

  • Precedence Not, And, Or

  • True and False are numeric in C. 

    Zero is False, Non-zero is True

  • Short-circuit behavior && ||
  • No short-circuit  &  |
  • New Operator: compound Assignment  +=

    a = a + b;   a += b;   often used for accumulators
  • New Operator:  increment ++  decrement --
  • Pre, and post increment and decrement

  • ++ and -- break the usual rules of precedence.
  • Sequence, Selection, Repetition (looping)

  • Counter and Sentinel controlled loops

           1. Start   2. Stop    3. Get there

  • Counter variables, Accumulator variables

  • Use a test case, and step through the code in the debugger to see its behavior

  • while
  • Pre-test loop
  • Often used for sentinel controlled loops

  • do-while
  • Post-test loop - generally frowned upon, but may be useful in some circumstances – when you learn the status of the stop condition inside the body of the loop.

  • for
  • Used for counter controlled loops.  Very commonly used.
 
  • #define is used to create named constants – these are not variables.
  • Always have some test cases that demonstrate the expected result for the problem you are solving.
  • Develop the solutions progressively.
  • Compile frequently – isolate compiler errors.
  • Use the debugger to find logic errors – the program cannot hide anything from you.
  • Use for loops for counter controlled loops.
  • Use short-cut operators where possible.
  • Choose variable names carefully.
  • srand, and rand are function in the stdlib that generate random numbers.
 
  • The indexes of an array start with 0 (zero).
  • Eg. an array with 10 elements has indexes 0 – 9
  • A one-dimensional array is sometimes called a "List"
  • A 2-D array is a "Table"
  • Arrays can be of any data type – elements are used as if they are simple variables of that type
  • A defined constant can be used to make your program easier to modify / maintain.
      for ( i = 0; i < SIZE; i++) {     // loop to each element
  array[
i] = …
 
 
  • Programming with arrays is easier if you use a picture to help you think about the data, and the loops that access the elements of the array.

  • Program progressively.  Compile and run the code often.
  • Always have at least one good test case that is the target result.

  • Good variable names are more important when the problems become more complex.
 
  • Hierarchy charts are used to organize anything complex including C programs

  • There are many functions already defined for you, eg. scanf, printf.

  • We define functions to 'divide and conquer' – solve more complex problems.

  • Define functions that achieve 1 (one) well define objective – name the function carefully

  • General form for defining a function:

      returnDatatype functionName( type parameter, type parameter) {     
       
    body of function
    }


  • General form for calling a function:

     resultReturned = functionName( argument, argument ); 

 

 
  • Determining how to break the problem into functions - can take practice.

  • Functions should do only one thing – and should have some documentation that describes what it does.

  • Work progressively: solve small problems - and only move on when those are correct.

  • Decide what information needs to be passed into the function and what information needs to be passed back to the caller also requires practice.   "coupling"

  • Functions should be created so that they can be re-used in other applications. 

  • The syntax for passing arrays to functions is tricky.  Until you have practiced this several times, keep a working example nearby for reference.
 
  • There are many well known algorithms that solve common problems.  We looked at the bubble sort, and the binary search
  • Nested Loops.  Write pseudocode to help with a solid understanding.
  • Some programmers use psuedocode as an intermediate step between understanding the problem, and writing the code.
  • It takes some practice to get used to nested loops that use arrays.
     
  • Use a picture of the arrays.  Walk through code using a pencil.
  • Bubble sort is only one algorithm that can be used for sorting. (There are many: selection sort, insertion sort, quick sort, etc.)

  • A binary search is much more efficient than a linear search, but the data must be sorted for a binary search to work.  There is a relationship between sorting and searching algorithms.
 
  • A pointer is the address of a byte in RAM

  • A pointer, address, and reference are the same thing

  • &  is the "address of" operator.  Use it to get the address of a variable
  • int*  is a new data type that can hold the address of an int
  • double*, char*, float*, long long*  are all data types that can hold addresses
  • * is the dereference, or indirection, operator. 
  • The * operator is not the same as the one in the data type, but they are related because you use the * operator on pointer types.

  • When you dereference a pointer, you use the piece of memory that is pointed at by that pointer

 

A.  Using the return statement is information coming OUT of the function.


B.  Pass by value is information going only IN to the function.


C.  Pass by reference is information going IN and coming OUT of the function.

  • Pointers are useful.

  • scanf("%i", &a);  // pass the address of a to scanf
     
  • A function can pass information back to the caller by using an address

  • The caller passes the address of a variable to the function

  • The function uses a pointer data type for the parameter, so that it can receive the address from the caller

  • A pointer, address and reference are the same thing

  • When you dereference a pointer, you use the piece of memory that is pointed at by that pointer
 
  • Watch what is going on in the debugger.

  • Draw a picture of the data.

  • Make some comments in the code regarding the information going in to and coming out of the function.

  • Make the functions achieve only one goal.  If there are more than 5 parameters, the function might be too complex.

 

 
  • The name of the array contains a pointer to the first element in the array.

  • Array elements are stored contiguously in memory.
  • Arrays can be manipulated using subscript syntax, or pointer-offset syntax.
  • Pointer arithmetic - add 1 to a double pointer increases the address by 8.
  • Be very careful about going past the end of an array.
 
  • A string is an array of char's terminated with a null character.

  • Using "  " in the syntax of C results in a literal of data type char*
  • Using "  " automatically adds the null character, so this char* is a string
  • Functions that process strings, look for the null character.  If there is no null character present, the function will keep looking at bytes beyond the end of the array.
  • String.h contains the prototypes for many standard functions that can be used to manipulate strings.
 
  • Draw pictures of the data so you can refer back to them when programming
  • You can't work with data if you don't know what it looks like!

  • Work progressively.  Get small things working and put them together.
     
  • Use the debugger all the time when using arrays and pointers
 
  • User Defined Types (UDT) in C are created with the keyword 'struct'
  • There are different ways to create a struct, and it's easy to confuse them.

  • Create new types so that the code can express the solution to the problem in the same terms the problem is described.

  • Adopt a convention for capitalization

  • This is the basis for object-oriented programming, but it is not considered object oriented. 
  • The "things" that are created, are sometimes called "objects,"  but OO languages have the capability to add executable code to the data types. 
 
  • Structs are passed by value unless a pointer is used to pass them by ref

  • Anything passed by value – there is a copy of the data used by the function

  • It is often better to pass structs by ref even if the data is not going to be changed – the size of the pointer is 4 bytes, the data can be quite large

  • Use the keyword const to prevent programmers from changing the data in a struct inappropriately.

  • A pointer to a struct can use the -> operator to access the component parts of the struct.  The -> operator is a shortcut for the more awkward (*p).part syntax
  • Structs can be composed of other structs to make more interesting data structures

  • sizeof can be used to count the number of bytes in a struct.
 
  • Structs are used to represent one "thing"

  • Multiple instances of a struct can be stored in an array and manipulated similarly to arrays of primitive data types.

  • A common error is to attempt to move an array of characters (string) with the assignment operator.

  • Draw pictures of the data that is being manipulated.
 
  • Memory for variables is allocated from either the stack or the heap.
  • The stack is also called the "call stack" – each function's local variables are available during the execution of the lines of code in that function.

  • Memory for local variables is automatically returned to the free space within the stack when the functions end.  "Automatic" variables.
  • Stack size can be set in the IDE.  If it is set too small, the program can end with a "stack overflow" error.
 
  • Dynamic memory allocation can be done one object at a time, or for an entire array of structs.

  • Choosing how to do the memory management depends on the nature of the application.

  • Some applications need to grow and shrink their memory usage continually, while some have relatively static memory requirements.

  • Draw pictures of the data! 
 
  • Files can be thought of as a sequence of bytes on an external storage medium

  • Files can be text or binary

  • Reading text files can be complicated.  Read the descriptions of the format specifiers carefully.  Don't guess!  Incorrect format specifiers will do something, and might appear to work, but the behavior is really indeterminate.
  • It is impossible to read a binary file without knowing what the bytes represent – the data types and their locations in the file.

  • Binary files can be read and written with large blocks of data or a byte at a time using fread and fwrite

  • You can mix binary and text file access, but it shouldn't be done.  The behavior is indeterminate, and tends to result in guessing what the code will do, and then changing it – over and over.
 
  • Don't mix the use of functions intended for Text and Binary files.
  • Keep a reference for the description of the format specifiers handy!

  • Close the files as soon as you are done with them.

  • Draw pictures of a binary file – use graph paper to help keep track of the bytes.

  • Don't guess!  It will take forever to work with files using trial and error, and the result might not be doing exactly what you expect it to be doing.

Appendix
 
  • How to get a free copy of Visual C++ Express 2010
     
  • Registering your Visual C++
     
  • Testing with Hello World
 

 

  • Decimal number system, base 10

  • Binary number system, base 2

  • A Byte has 8 bits

  • One byte can hold values 0 – 255

  • Bytes can be combined to represent larger values.

  • Converting from decimal to binary, and binary to decimal.

 

 

 

  • Hexadecimal (hex) uses Base 16.

  • Hex is an easier way to represent binary numbers.

  • 4 bits can be represented in one hex place

  • Conversion between binary and hex is very quick.

  • All programmers must know how to represent numbers in binary and hex.