Chapter 1: Intro
Chapter 2: Overview
Chapter 3: Setup
Chapter 4: Program Structure
Chapter 5: Basic Syntax
Chapter 6: Data Types
The computer is like a train, the tracks the train run on are the program the computer follows. You lay down the tracks to get the train to where you want it to go.
Top-down: Breaks down a large problem into smaller and smaller "chunks", usually into functions and sub-functions, until discrete solvable problems at the lowest layer are resolved. This is like outlining a story.
Bottom-up: Starts with basic building blocks (think Lego) and builds discrete units, resolving the way in which they work together as higher orders emerge from the combined lower basis.
Upsides and downsides to both, best strategy is to combine and use both methods.
Defining and designing the data structures and patterns first often leads to the program design itself, so start with the data. The data is often the most important aspect of a program.
A programming paradigm that makes extensive use of subroutines, block structures, for and while loops.
Emerged in the 1960s after "GoTo Statement Considered Harmful" paper and the introduction of the ALGOL programming language.
Gave rise to:
Procedural programming, which gave rise to:
Example of unstructured vs structured:
10 I=0 20 PRINT "Hello, World!" 30 I=I+1 40 IF I<10 THEN GOTO 20
for(i=0; i < 10; i=i+1) { printf("Hello, world!"); }
There is some difference in the order of operations, but otherwise they do the same thing: print 'Hello, world!' 10 times). In the BASIC example the flow of the code is controlled using the GOTO statements and there is no apparent "structure" to the code, whereas in the C example the print statement is a child of the for statement, giving the program a more tree like structure.
Reading: Chapter 4: Program Structure
Sequence: ordered statements executed in sequence.
Selection: Statements executed dependent on state of the program. (if - else, switch/case)
if
else
switch
case
Iteration: Statements executed until the program reaches a certain state. (while, do-while, for)
while
do
for
Subroutines:
Blocks:
{
}
fi
begin
end
Early exit:
break
continue
return
exit
Flowcharts are a visual representation of program logic. Wikipedia entry on flowcharts They describe what the grammar means in terms of what the computer will do.
Common Symbols: The most common ones and ones you should be aware of are the:
The grammar of a language is the set of rules and structure of a language, and like natural languages (such as English), computer languages also have grammar that needs to be followed.
It is very important to understand the grammar of a computer language. It is the means by which you can "communicate" your intentions to the computer, so if you do not understand or remember the grammar, you cannot communicate to the computer. Your programs will not compile (the phase where the computer attempts to interpret your intentions and transform it into instructions it will follow,) thus you cannot learn to program without first learning the grammar and structure of a programming language.
Fortunately computer grammars tend to be what is called "formal", i.e. they are "well defined", in that they reduce as much as possible ambiguity in meaning of the words and symbols of the grammar and tend to have quite simple and strict rules that once learned can usually be applied quickly to other programming languages that use similar grammars. Computer languages also tend to have very few words and symbols compared with natural languages (a few hundred, compared to 10s of thousands) and you should already be familiar with a number of them from having already learned English and Math.
Like natural languages, computer grammars are "recursive", i.e. the language is defined like a set of fill in the blank ad-libs, such as:
if ( __________ ) _________ expression statement
The above is itself a "statement" (specifically an "if-statement"), which may be inserted in it's entirety where the statement is specified, such that
if (a) s
is valid grammar where a (and b and c below) is an "expression", and 's' is a statement of some sort. The following is also valid grammar:
if (a) if (b) s
where (if (b) s) is a complete if-statement that replaces the s in the first (if (a) s) example. Furthermore:
if (a) if (b) if (c) s
is also valid, and so forth. If we draw {}'s around each "statement" the last example would look like:
{ if (a) { if (b) { if (c) { s } } } }
which is perfectly valid grammar in a C like language.
exp == an expression that evaluates to true or false (i.e. Boolean) stmt == A statement
type var,var,...; type var=exp;
exp;
var = exp;
{ stmt1; ...}
if (exp) stmt
if (exp) stmt1 else stmt2
while (exp) stmt
do { stmt } while (exp);
for(init-exp;test-exp;inc-exp) stmt
init-exp; while(test-exp) { stmt; inc-exp }
break;
continue;
return-type name (variable-declarations) { stmt1; ... }
return exp;
A function is a some operation that may take some input data and process it and output some result based on the input data. An example of a function is addition.
Example Notation (a + b) Infix notation (operator is "in"-between the operands) (+ a b) Prefix notation (Polish Notation) (LISP, C functions.) Operator comes before the operands. (a b +) Postfix notation (Reverse Polish Notation (RPN).) Operator follows the operands.
(a + b)
(+ a b)
(a b +)
The + function requires two (or more in the case of prefix or postfix notation) inputs, which are operated on and the result of adding them together.
In expressions, the inputs are also recursive, for example in the above a or b can be complete sub-expressions (i.e. a could = 5, or a = (x+2), etc.)
a
b
(x+2)
Prefix to infix example: (+ (- a b) c) is the same as (a - b) + c
(+ (- a b) c)
(a - b) + c
which is equivalent to:
add( subtract(a, b), c)
In C function calls are prefix expressions where the operands, enclosed in parenthesis and separated by commas, follow the function name. The operands to a function can be any expression, which may include function calls themselves.
Procedures / sub-routines: A function that may not require any input, nor need to return a value may be created, usually to combine code that needs to be called repeatedly or from different areas of the program. This gives a name to the code and allows you to stop thinking about the code inside of the procedure and just think of its function making the program easier to mentally manage as well as reducing the amount of coding necessary in general.
If you do something in your program more than twice, it is usually a good idea to consider making a function or procedure to do that thing.
In C, the return keyword gives a function it's value, and causes the computer to leave the function immediately as well.
int add(int a, int b) { │ └──────┴───────── Data-type for the inputs, a and b. └──────────────────────── Data-type for the returned value for the function. return a + b; ╘═══╛──────────── The value of this function that is returned. }
For now, we won't be using functions too much, but you will always require at least one function for a C program, and that is the "main" function, which is the starting point to all C programs. Also when you leave the main function (via return), the program will complete. The return type for main is always an integer (int), so when defining main it should look like:
main
int main(void) { ***Your code here*** return 0; }
The number being returned by main is used by the shell to determine if the program was successful or not. Usually we don't care, but here 0 means the program was successful, and any other number from 1 to 255 means it failed in some way (the number usually indicating which way it failed.)
The void parameter to main means we don't need any parameters to main, main can optionally be written like:
int main(int argc, char *argv[]) ...
which would allow our main function to get command line parameters from the user which would be stored in the argv[] array.
argv[]
What is data? In a computer the most fundamental unit of data is the "bit" which represents one of two possible states (off/0 or on/1). By combining bits together into various sizes (bytes (8 bits), words (16 bits), long words (32 bits) or quad words(64 bits)) the computer can represent integers of various sizes.
Integer size: C type: unsigned range: signed range: 1 bit Bool 0-1 0-1 8 bits char 0-255 -128 - 127 16 bits short 0-65535 -32768 - 32767 32 bits int 0-~4 billion +/- ~2 billion 64 bits long 0-~18 quintillion +/-9 quintillion
Bool
char
short
int
long
By default C integers are signed (i.e. can be negative values.) To make them unsigned, you prefix the type with the "unsigned" modifier. ex:
unsigned int unsigned char
unsigned int
unsigned char
Negative numbers, floating point values, strings, arrays or other kinds of structured data arise from how the computer interprets the grouping of bits.
ASCII characters for example are 7 bit numeric values (stored in a 8 bit byte.) values. Use 'man ascii' from the command line to view the ASCII table.
value characters: 0 - 31 "control characters" Invisible, usually non-printable characters 10 '\n' (newline) 32 ' ' (space) 48 - 57 '0' - '9' (Numeric digit characters) 65 - 90 'A' - 'Z' (Upper-case letters) 97 - 122 'a' - 'z' (Lower-case letters)
'\n'
' '
'0'
'9'
'A'
'Z'
'a'
'z'
In C, the ASCII value of a character can be had by enclosing the character in single quotes, i.e. 'A' is 65, 'B' is 66, etc. In general it is considered better to use 'A' instead of 65 when comparing letters as 65 is considered a "magic number", i.e. it isn't clear what 65 means. 'A' is more meaningful to someone reading your code than 65 is.
'B'
A string is a sequence (array) of ASCII characters (encoded into 8 bit bytes) enclosed inside of double quotes. Strings are terminated by a null byte (numeric 0 or '\0'), though you don't see the null character in your string. Thus:
'\0'
"Hello" is the sequence of ASCII characters:
"Hello"
Character: 'H' 'e' 'l' 'l' 'o' '\0' Numeric value: 72, 101, 108, 108, 111, 0
'H'
'e'
'l'
'o'
Floating point values (allow fractional values, like 1.5, 2.6e135)
C-type: size: range: Precision float 32 bits ~ 10^+/-38 6 digits double 64 bits ~ 10^+/-308 15 digits long double 80 bits ~ 10^+/-4932 19 digits
float
double
long double
Floating point values are not always exact (for example 1/3 or .1 are just approximations) and they are always signed, unlike unsigned integers.
Any number with a decimal place in it is a floating point value, thus: .5, 0.5, 10., .100 are all floating point values.
.5
0.5
10.
.100
Floats can be specified in engineering format, for example: 5.2e-20 which is the same as saying: 5.2 x 10-20.
5.2e-20
5.2 x 10
-20