The C programming language was developed at Bell Laboratories in the Early 1970’s. The language was intended to provide a high level framework for data and functions while allowing highly efficient programs. By the 1980s the language had entered widespread usage and was in use for the development of many high level programs. By the 1990s most new software projects were written in C. Some of the advantages of C are listed below.
• Machine Portable, which means that it requires only small changes to run on other computers.
• Very Fast, almost as fast as assembly language.
• Emphasizes structured programming, by focusing on functions and subroutines.
• You may easily customize ’C’ to your own needs.
• Suited to Large and Complex Programs.
• Very Flexible, allows you to create your own functions.
More recently C++ was developed to add object-oriented capabilities to C. In simple terms the object oriented extensions allow data and functions to be combined together. In general the advantages that C++ add over C are those listed below. In general, any C program can be compiled with C++, while C++ programs will often not compile with a C compiler.
• Reusable source code can reduce duplication
• Encapsulation of data and functions reduces errors
• It is easy to interchange software modules
This chapter will act as a basic introduction or review of C and C++ programming. C programming is discussed first to lay the foundations, and this is followed with a discussion of C++ programming extensions. The end of the chapter discusses structured program design techniques. If you are already fluent in C and C++ I suggest you skip this chapter.
C programs are basically simple text programs that follow a general set of rules (syntax). Figure 3.1 shows the classic beginners program that will add two numbers and print the result. The first line in this example is a comment. Comments are between ’/*’ and ’*/’ can stretch over many lines. Comments can also be the end of a line if they follow ’//’. The ’main()’ program declaration indicates where the program starts. The left and right curly brackets ’{’ and ’}’ are used to group together a set of program statements, in this case the program. Notice that the program statements are indented to indicate how they are grouped. This is a very valuable structuring technique that makes the programs much easier to read.
Figure 3.1 - A Program to Add Two Numbers (and results)
The program begins with the definition of three variables, ’x’, ’y’ and ’z’. All three are defined to be ’int’ integers and the value of ’y’ is set to ’2’. The statement is terminated with a semicolon to separate it from the next statement. The next line assigns a value of ’3’ to ’x’. The following line adds the values of ’x’ and ’y’ and assigns the value to ’z’. The last statement in the program, ’printf’, prints the values with a format statement. The first string in the command is a format string. In the string a ’%d’ indicates an integer, and ’\n’ indicates an end of line. The remaining characters in the format string are printed as shown. The format string is followed by the variables in the format string, in the same sequence. The result of the program shown that when it is run it prints ’3 + 2 = 5’.
Some of the general rules that are worth noting are listed below.
• lower/UPPER case is crucial, and can never be ignored.
• Statements can be on one or more lines but must be separated by semi-colons ‘;’.
• Statements consist of one operation, or a set of statements between curly brackets {, }
The data types for C are listed below with typical data sizes. Sometimes these sizes may be larger or smaller. Their behavior of ’char’, ’short’, ’int’ and ’long’ can be modified when preceded with ’unsigned’. For example an integer ’x’ defined with ’int x;’ could have a value from -32768 to 32767, but if defined with ’unsigned int x;’ it can have a value from 0 to 65535.
char (1 byte ascii character),
short (1 byte signed integer),
float (4 byte floating point IEEE standard),
double (8 byte floating point IEEE standard).
Beginners will often write a program in a single ’main’ function. As the program becomes more complex it is useful to break the program into smaller functions. This makes it easier to write and read. Figure 3.2 contains an example program that uses subroutines to perform the same function as the program in Figure 3.1. As before the ’main()’ program function is the starting point for program execution. The subroutine ’add’ is defined after ’main’, so a function prototype is required before. A prototype just indicates the values that are passed, and the function return type. In this example the values 3 and 2 are passed to the ’add’ function. In the add function these values are then put into ’a’ and ’b’. The values are then added and assigned to ’c’. The value of ’c’ is then returned to the main function where it is assigned to ’z’.
Figure 3.2 - Program to add numbers with a function:
Every variable has a scope. This determines which functions are able to use that variable. If a variable is global, then it may be used by any function. These can be modified by the addition of static, extern and auto. If a variable is defined in a function, then it will be local to that function, and is not used by any other function. If the variable needs to be initialized every time the subroutine is called, this is an auto type. static variables can be used for a variable that must keep the value it had the last time the function was called. Using extern will allow the variable types from other parts of the program to be used in a function.
Figure 3.3 - Program example using global variables:
Other variable types of variables are union, enum and struct. Some basic control flow statements are while(), do-while(), for(), switch(), and if(). A couple of example programs are given below which demonstrate all the ’C’ flow statements.
Figure 3.4 - Program example with a for loop:
Figure 3.5 - Examples of Other Loops
Figure 3.6 - An If-Else Example
Figure 3.7 - A Switch-Case Example
#include <filename.h> will insert the file named filename.h into the program. The *.h extension is used to indicate a header file which contains ‘C’ code to define functions and constants. This almost always includes “stdio.h”. As we saw before, a function must be defined (as with the ‘add’ function). We did not define printf() before we used it, this is normally done by using #include <stdio.h> at the top of your programs. “stdio.h” contains a line which says ‘int printf();’. If we needed to use a math function like y = sin(x) we would have to also use #include <math.h>, or else the compiler would not know what type of value that sin() is supposed to return.
#define CONSTANT TEXT will do a direct replacement of CONSTANT in the program with TEXT, before compilation. #undef CONSTANT will undefine the CONSTANT.
Figure 3.8 - A More Complex Example
#fictive, #finder, #if, #else and #else can be used to conditionally include parts of a program. This is used for including and eliminating debugging lines in a program. Statements such as #define, #include, #fictive, #finder, #if, #else, /* and */ are all handled by the Preprocessor, before the compiler touches the program. Matrices are defined as shown in the example. In ‘C’ there are no limits to the matrix size, or dimensions. Arrays may be any data type. Strings are stored as arrays of characters.
Figure 3.9 - Printing ASCII Values
Pointers are a very unique feature of ‘C’. First recall that each variable uses a real location in memory. The computer remembers where the location of that variable is, this memory of location is called a pointer. This pointer is always hidden from the programmer, and uses it only in the background. In ‘C’, the pointer to a variable may be used. We may use some of the operations of ‘C’ to get the variable that the pointer, points to. This allows us to deal with variables in a very powerful way.
Figure 3.10 - A Sample Program to Get a String
Classes are the core concept behind object oriented programing. They basically allow data and functions to be grouped together into a complex data type. The example code below shows a class definition, and a program that uses it.
Figure 3.11 - A Simple Class Definition
The class is defined to have a public integer called’value’ and a public function called ’result’. The function ’result’ is defined separately outside of the class definition. In the ’main’ program the class has two instances ’A’ and ’B’. The ’value’ values in the classes are set, and then the result function is then called.
A more sophisticated example of a class definition follows. The program shown does exactly the same as the last program, but with some useful differences. This class now includes a constructor function ’bill’. This function is automatically called when a new instance of ’bill’ is created. In the main program the instances are not created initially, but pointers ’*A’ and ’*B’ are created. These are then assigned instances with the calls to ’new bill()’. At this point the constructor functions are called. Finally, when the instances are used, because they are pointers, the ’->’ are used instead of ’.’.
Figure 3.12 - Another Class Example
A ‘C’ compiler has three basic components: Preprocessor, First and Second Pass Compiler, and Linker.
Figure 3.13 - How Programs Are Compiled
• A key to well designed and understandable programs.
• Use indents, spaces and blank lines, to make the program look less cluttered, and give it a block style.
• Comments are essential to clarify various program parts.
• Descriptive variable names, and defined constants make the purpose of the variable obvious.
• All declarations for the program should be made at the top of the program listing.
Figure 3.14 - Program Structure Examples
The basic C compiler is called ’gcc’, or ’g++’ for C++. These can be put on a command line. For example ’gcc bob.c -o bob’ will compile a C program in the file ’bob.c’, and store the result in a program file ’bob’.
Function libraries linked in with ’-l___’. For example to use a math function the math library must be included in the compilation line with ’-lm’. The debugger can be used if ’-g’ is included in the compilation line. For example, if a program was compiled with ’gcc -g bob.c -o bob’, it could be run in the debugger with ’xxgdb bob’. This then allows you to step through the program line by line, set break points, see where it crashed, or print data values. The compiler can be set to be extra picky (which also helps find errors) when compiled with the flag ’-Wall’
Programmers quickly tire of constantly typing commands to compile programs. To help with this problem, the make utility was developed. A programmer will create a ’makefile’ to describe how a program is to be compiled. This file can be called ’makefile’ or ’Makefile’ by default. The contents then describe when a file should be compiled.
The sample makefile below shows a simple makefile. The lines beginning with ’#’ are comments. The line containing the ’all:’ indicates the main program(s) to make. In this example the only program to make is ’bob’, notice that a later line starts with ’bob:’. The next three lines define variables that can be reused. Later in this example the ’$(CC)’ will be replaced with ’gcc’, the ’$(CFLAGS)’ with ’-Wall -g’, and so on. To make the required program ’bob’ both ’bob.c’ and ’bill.o’ are needed. When run the make tool will check to see if the files on the disk have been updated and things need to be recompiled. Only if the program files have changed will the compiler be run, otherwise the compilation will not be done because it is not necessary. If it is necessary it will execute the commands on the following lines.
Figure 3.15 - A Sample Makefile
Initially creating a makefile seems to be alot of effort, but if you run the compiler 10 times you will save enough time to make it worth while. It also makes it easier for others to compile the programs later.
A program should be broken into fundamental parts (using functions for each part) and then assembled using functions. Each function consists of programs written using the previous simpler functions.
Figure 3.16 - Defining Program Structure By Function
• A Clear division should be maintained between program levels.
• Never use goto’s, they are a major source of logic errors. Functions are much easier to use, once written.
• Try to isolate machine specific commands (like graphics) into a few functions.
• A top-down design allows modules to be tested as they are completed. It is much easier to find an error in a few lines of code, than in a complete program.
• When programs are complete, errors tend to be associated with modules, and are thus much easier to locate.
• Updates to programs are much easier, when we only need to change one function.
• It is just as easy to change the overall flow of a program, as it is to change a function.
Application of ‘C’ to a CAD Program
1. Define Objectives - Make a written description of what the program is expected to do.
2. Define Problem - Write out the relevant theory. This description should include variables, calculations and figures, which are necessary for a complete solution to the problem. From this we make a list of required data (inputs) and necessary results (output).
3. Design User Interface - The layout of the screen(s) must be done on paper. The method of data entry must also be considered. User options and help are also considered here. (There are numerous factors to be considered at this stage, as outlined in the course notes.)
4. Write Flow Program - This is the main code that decides when general operations occur. This is the most abstract part of the program, and is written calling dummy ‘program stubs’.
5. Expand Program - The dummy ‘stubs’ are now individually written as functions. These functions will call another set of dummy ‘program stubs’. This continues until all of the stubs are completed. After the completion of any new function, the program is compiled, tested and debugged.
6. Testing and Debugging- The program operation is tested, and checked to make sure that it meets the objectives. If any bugs are encountered, then the program is revised, and then retested.
7. Document - At this stage, the operation of the program is formally described. For Programmers, a top-down diagram can be drawn, and a written description of functions should also be given.
Golden Rule: If you are unsure how to proceed when writing a program, then work out the problem on paper, before you commit yourself to your programmed solution.
Note: Always consider the basic elements of Software Engineering, as outlined in these course notes.
• The program is expected to aid the design of beams by taking basic information about beam geometry and material, and then providing immediate feedback. The beam will be simply supported, and be under a single point load. The program should also provide a printed report on the beam.
• The basic theory for beam design is available in any good mechanical design textbook. In this example it will not be given.
• The inputs were determined to be few in number: Beam Type, Beam Material, Beam Thickness, Beam Width, Beam Height, Beam Length, Load Position, Load Force.
• The possible outputs are Cross Section Area, Weight, Axial Stiffness, Bending Stiffness, and Beam Deflection, a visual display of Beam Geometry, a display of Beam Deflection.
• The small number of inputs and outputs could all be displayed, and updated, on a single screen.
• The left side of the screen was for inputs, the right side for outputs.
• The screen is divided into regions for input(2), input display and prompts(1), Beam Cross section(3), Numerical Results(4), and Beam Deflection(5).
• Current Inputs were indicated by placing a box around the item on the display(1).
• In a separate Prompt Box(2), this input could be made.
• The cursor keys could be used to cursor the input selector up or down.
• Keys required: UP/DOWN Cursors, F1, F2, F4, numbers from ‘0’ to ‘9’, ‘.’, ‘-’, and <RETURN>. In the spirit of robustness it was decided to screen all other keys.
• Equations, calculations, material types, and other relevant information were obtained from a text.
• Proper textual descriptions were used to ensure clarity for the user.
• For a printed report, screen information would be printed to a printer, with the prompt area replaced with the date and time.
• A special set of help information was needed. It was decided to ensure that the screen always displays all information necessary(2).
• The routines were written in a top down fashion, in a time of about 30 hours. These routines are listed below.
• Condition and error flags were used to skip unnecessary operations, and thus speed up response. A response of more than 0.5 seconds will result in loss of attention by the user.
• The testing and debugging was very fast, with only realignment of graphics being required. This took a couple of hours.
• The documentation included an Executive Summary of what the Program does.
• The Objectives of the program were described.
• The theory for beam design was given for the reference of any program user, who wanted to verify the theory, and possible use it.
• A manual was given which described key layouts, screen layout, basic sequence of operations, inputs and outputs.
• Program Specifications were also given.
• A walk through manual was given. This allowed the user to follow an example which displayed all aspects of the program.
1. What are the basic components of a ‘C’ compiler, and what do they do?
2. You have been asked to design a CAD program which will choose a bolt and a nut to hold two pieces of sheet metal together. Each piece of sheet metal will have a hole drilled in it that is the size of the screw. You are required to consider that the two pieces are experiencing a single force. State your assumptions about the problem, then describe how you would produce this program with a Top Down design.
3. What are some reasons for using ‘C’ as a programming language?
4. Describe some of the reasons for Using Top-Down Design, and how to do it.
To practice programming in ‘C’.
C programming is an essential tool for developing automated systems. It can be used to develop customized applications for communication and data handling.
1. Start up the linux machine, and get X-windows running.
2. Create a new directory with ‘mkdir src’, and then enter the directory with ‘cd src’.
3. Use the ‘kedit test.c &’ text editor to enter the program below.
4. Compile the program with ‘cc test.c -o test’. Run the program with ‘./test’.
5. Use ‘kedit Makefile &’ to enter the makefile below.
6. Compile the program with ‘make’. Run the program with ‘./test’.
7. Modify the program to only print every second number.
8. Write a number guessing game that will randomly pick a number between 1 and 100. The user can then guess the number, and the computer will give clues ‘high’ or ‘low’ until the value is guessed. The program will then quit. Use a top-down programming approach.
9. Enter and compile the program below with the expanded makefile. This program will allow a user to enter their name, and output an HTML file that can then be viewed with a browser.
10. Write a program that will allow a user to enter their name. The program will then count the number of letters in their name.