Make your own free website on Tripod.com
C Ripped Apart :: Section 1
Author: Mike Ware
Website: [warebiz] :: "The Programmer's Domain" - http://warebiz.tripod.com
Email: warebiz@yahoo.com
Copyright © 2003 Michael Shawn Ware, All Rights Reserved.


You are here --> [Section 1 :: Introduction to C]

"Jump To Articles"
    --> What is C?
    --> Variables / Data Types
    --> Preprocessor Capabilities
    --> Basic C Statements : Input / Output


What is C?

C is a structured programming language. It allows for the interplay between software and hardware and was designed for solving real-world problems efficiently. Because of its features, its debut to the programming industry turned many heads and persuaded many development firms to learn and immediately begin using it. At the time of its creation, no other language had capabilities that C possessed. This is why C became so popular at an amazing rate and why C++ was later developed to add and implement even more features to the language. As you will later find out, the operator ( ++ ) is the increment operator, meaning adding one to. Therefore, C++, can be thought of as C = C + 1. If it wasn't for C, C++ would have never been created. There is a also a C+ language, which was created after C and before C++. C+ is not as popular as C or C++ but nevertheless possesses similar characteristics. C has remained a dominant language in the programming industry because of its efficiency, power, flexibility, portability, and feature of being programmer oriented.

For a first program example, consider:


#include <stdlib.h>
#include <stdio.h>

int main( )
{
      printf("Hello, World.\n");
      printf("This is my very first C program.");

      return EXIT_SUCCESS;
}

As previously mentioned, C is a structured language. This means that C programs follow some type of form or structure, and it can be easily seen here that modules, which are more commonly called functions, play a role in making C a structured language. All C programs are made up of one or more functions, and main( ) will always represent the starting point of execution. By definition, a function is a subprogram within a program designed to carry out a particular task and perhaps return a value to the calling function. A function can call other functions which may also call other functions. Here, we only have one function, main( ), and we use it to simply output two statements using the printf( ) function, which is contained in the stdio header file. The stdlib header is needed for the enumerated constant EXIT_SUCCESS, which is used to return a value for 0 when the program is finished executing. This may seem confusing at first, but everything is explained in more detail in later articles. For now, note that functions are used to add "structure" to C programs. Also note that main( ) will always be included and will begin program execution.

Typical Structure of a C Program
All programs written in C follow a general structure. Include statements and other global identifiers ( constants, user-defined types ) will be placed at the beginning of a C source file. The include statements are pre-precessor directives that "include" code stored in other source files to be used in the program. This provides for a convenient way of "including" the same code in many programs rather than writing the same code for each program that needs it. Immediately following the global section of a source file, the mandatory main( ) function will appear. This marks the beginning of program execution and the flow of the program will branch out and be generally controlled by main( ). The definitions of additional functions that the program needs and uses will be placed after the main( ) function definition. Inside both main( ) and additional user-defined functions are executable statements that are terminated by a semi-colon. C terminates every executable statement with a semi-colon to simply denote that it is a executable statement that gives an instruction to the CPU (central processing unit) of a computer. We will see more about this later.

For a brief overview of C's syntax, which is the rules governing the formation of statements in a programming language, consider the following remarks. Please note that by syntax we mean the specific language (code) used to turn algorithms into programs and specific rules followed when programming in C. A programming language's syntax is critical because programs will not compile until code is syntax-error free. However, a program will run even though it may contain logic errors; these errors occur during program execution (but don't cause a crash) and must be recognized during testing.

All executable statements must be terminated with a semi-colon. User-defined functions do not need to be terminated with a semi-colon but user-defined type specifications are required to be.

Curly braces are used to mark the beginning and end of "block" statements or function definitions. For example, consider:

main( )
{     /* beginning curly brace */

}     /* end curly brace */

A function will always be given a name, either user-defined or "built-in", and will have a pair of parentheses attached to the end of its name. The parentheses actually make up a function's argument list. Variables that need to be "passed" into or "sent" to the function are placed inside the argument list. This allows for functions to perform calculations and operations with values contained in variables that are defined outside the scope of the function. We will see more about this when investigating how to pass variables by reference and value.

Programmer comments are placed within program code using the /*      */ statement with programmer remarks inserted between the start and end backslash/asterick grouping. Comments allow for documentation within a source file. Documentation refers to comments or statements within program code that are ignored by the compiler used solely to provide explanations and remarks about what particular code segments are supposed to do. Using comments is extremely crucial when developing well-structured complex programs, and it is good programming practice to always place comments in program code. Get into the habit of placing comments within program code during early programming experiences.

All executable statements will be made up of user-defined elements and "built-in" elements. User-defined elements refer to statements that you as the programmer create to handle and solve particular problems. "Built-in" elements refer to statements and functions previously defined in C, normally by the compiler developers, that the programmer can use by simply "calling" or specifying in programs. There are many "built-in" functions in C. There are also "built-in" keywords that have meaning in C to handle certain conditions. You will use a "built-in" function in most of the statements you write. Keywords allow for the definition of data types, control structures, and much more. Because keywords have special meaning, you cannot give another variable or function the same name as a keyword. The following is a listing of C keywords proposed by ANSI C standards:

//////////////////// ANSI C KEYWORDS //////////////////////////
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
////////////////////////////////////////////////////////////////


Common Programming Errors
There are basically two types of errors in programming: syntax and logic. Syntax errors occur when programs fail to compile because the programmer has mistakenly ignored a rule that must be followed with writing code statements. An example would be not terminating a executable statement with a semi-colon or giving a variable the same name as a keyword. Logical errors occur when programs successfully compile but do not behave or solve a particular problem correctly. This can occur in many ways, and you will most likely encounter them when you start developing complex programs. Syntax errors are generally easier to find and correct because during compilation, the compiler will alert you of the errors and possibly tell you the line of where the error occurs. A general rule to follow is to correct syntax errors that occur in the beginning of program execution first and work your way to the end. Some errors at the beginning of the code may make the compiler believe that other errors exist later in code when they in fact do not if you fix the preceding error. Logical errors are harder to find and correct simply because you will not notice them until performing program testing.

Although you only have been briefly introduced to some of C's features, we have covered enough information for you to write a simple program, just like the small program provided above. The following is a empty sample program that can be used as a "setup" program for you to open each time you write a new program. Use the copy and paste function to save the code as a .c source file. It has a good program format that will remind you of the importance of documenting program code:


/***********************************************************************************************
    PURPOSE: description of program
          USES: dependencies

    PROGRAMMER: your name
    DATE LAST UPDATED: last updated time
***********************************************************************************************/

/* pre-processor directives */
#include <stdlib.h>

/* global identifiers */


/* begin main definition */
int main( )
{


      return EXIT_SUCCESS;
}

/* other function definitions */

The next section provides an intro to C data types, variables, and some basic statements that are very important for beginners to grasp. Read on for more...

Variables / Data Types

Every program works with some form of data, either numerical or character. Computers are capable of working with data through the use of variables. Variables have an associated memory location inside a computer, and their value can be modified. It is important to note that the memory location of a variable stays constant throughout program execution; its value can change, and the memory location allows the computer to "look up" the variable in order to manipulate it. For example, consider a program used to calculate the average of three numbers. In the program code, there should be four variables: num1, num2, num3, and average. During execution of the program, the compiler will give each of the variables a memory location in the memory of the computer. If the variables are not set to a default value in the program, as they are placed into memory they will be assigned some type of garbage value until that value is changed during execution of the program.

In order to use a variable in a program, you must tell the computer which type of data it will be used to store (using a declaration statement). Here are three basic C types: int, float, and char. int is used for whole numbers without decimal points, float is used for real numbers with decimal points, and char is used for keyboard character or letter values. When declaring variables, you will need to specify a data type. You are letting the compiler know what type of data it is going to be working with. In C, data is either integral (integers and characters) or floating-point. Characters are considered integral because character values will eventually be converted into an ASCII (American Standard Code for Information Interchange), which is a system designed to associate character values with numerical values, value. There is also a bool (boolean) type. Boolean types can be used when using logical data; when something can be either true or false. A value of 1 is considered true, and value of 0 is considered false.

There are several possible sizes and for some of these data types there is a choice of unsigned or signed types. Signed simply means that the data can be negative or positive. Unsigned means the data will be strictly positive. In the following list, the sizes are representative only (compiler dependent).

char 1 byte -128 to 127
unsigned char 1 byte 0 to 255
int 2 bytes -32,768 to 32,767
unsigned int 2 bytes 0 to 65,535
long or (long int) 4 bytes -2,147,483,648 to 2,147,483,647
unsigned long 4 bytes 0 to 4,294,967,295
float 4 bytes 3.4 x 10^-38 to 3.4 x 10^38
double 8 bytes 1.7 x 10^-308 to 1.7 x 10^308
long double 10 bytes 3.4 x 10^-4932 to 3.4 x 10^4932


Note that integer values may be given in decimal, hexadecimal, or octal. Any value that begins with 0x or OX is a hexadecimal number. Any value that begins with 0 is octal. Also note that floating point values may be given in scientific notation. For example, the value 2.693 x 10^23 can be written as 2.693E+23.

Variable names must be begin with a letter, and then continue to be letters, digits, and underscores. Variable names should always be very descriptive and relate to the data it is used to store. For example, suppose I need a variable to store the grade of a student in a class; a possible descriptive variable name would be studentGrade. Descriptive names allow for easier program logic and easier updating routines, and they are critical when developing complex programs. C's standard library (preprocessor directives) defines variable names using an initial underscore so try to stay away from giving variables names beginning with underscores. The following is a listing of valid and invalid variable names:

Valid
starTrek
stu_First_Math
testScore1

Invalid
zook$     /* no dollar signs */
1dude     /* must begin with letter */
my Name     /* cannot contain spaces */

You must declare a variable before using it in a program. The form for declaring a variable is as follows:

    data-type identifier;

where data-type is a data type from the listing above and identifier is the name of the variable. The declaration statement simply defines the "type" of the variable and lets the compiler know the "type" of data it will be used to store. After declaration, the variable will hold a garbage value, which is an extreme value given by the CPU whose only use is to occupy memory storage until the variable is given a "true" value during program execution. For a few declaration examples, consider:

        int num1;
        float num2;
        char letter;

This code segment would declare num1 as being type int, num2 as being type float, and letter as being type char. From here on out in the program, num1 must be integer values, num2 must be floating point values, and letter must represent a single character value. Initialization is different from declaration because you will declare the variable and also give it an initial value. The initialization statement form is as follows:

    data-type identifier = value;

where data-type is naturally one of the data types described above, identifier is the name of the variable, and value is the variable's initial value. For a few initialization examples, consider:

        int num1 = 123;
        float num2 = 56.78;
        char letter = 'a';

This code segment would define num1 as type int with an initial value of 123, num2 of type float with an initial value of 56.78, and letter of type char with an initial value of 'a'. All variable values can change during program execution.

You can also initialize a variable constant. The form for named constants is:

    const data-type identifier = value; (where value is a literal)

The initializing is the same except for the preceding const keyword. When defining a variable as const, the variable's value cannot change during program execution. If the program tries to change its value, an error will occur. Constants are commonly used when sharing the same data for many different elements in a program. They also allow for easier program updating. For an example, consider:

    const int MAXSIZE = 450;

If we ever need to change MAXSIZE, which may be designed for numerous structures, we could simply change the value one time instead of manipulating each structure. We now have variables and data types covered. Let's move on to learn how we can use preprocessor statements to add efficiency to programs. Read on for more...

Preprocessor Capabilities

The preprocessor provides for very efficient instructions to take place before any program code is actually compiled. Preprocessor statements are not considered to be actual C executable statements; therefore there is no need to terminate them with a semi-colon or even include the assignment operator ( = ) which would otherwise be expected. They are also considered to be executed during compile time rather than during run-time execution. The form of a preprocessor statement is as follows:

    #define variableName value

where variableName is the name given to the constant value, and value is the value assigned to variableName. The pound symbol ( # ) is a giveaway that it is a preprocessor statement. The above form is used to define symbolic constants in programs. Symbolic constants specify values which cannot change during program execution. The basic idea of using symbolic constants is to give descriptive names to constant values that are normally used many times throughout the program. In turn, this makes updating the values of the constants very easy to accomplish in the future.

We have previously used the preprocessor statement to "include" or "link" other C files through the use of an #include statement at the very beginning of a program. The #include preprocessor statement searches a specified number of directories in search of the "target" file to be "linked" with the program. The #include statement provides a convenient way of using practical functions with programs without the need to write the code for each program; "include" the file containing the practical code and then use the needed functions. There are two forms for the #include statement:

    #include <file>
    #include "file"

The angle brackets form < > represent files that are normally created by the compiler developers and only search for the file in specified directories. The quotes " " form is normally used for user-defined header files and normally only search for the file in the current directory.

To see how preprocessor statements can be used in programs, consider the following complete program:

NOTE: This program presents statements that have not yet been covered in the tutorial. INPUT/OUTPUT statements are covered following this article [see Basic C Statements: INPUT / OUTPUT], and character strings are presented in the next section [see Character Strings (section 2)].


//////////////////////////// CODE COMPILED USING DEV-C++/C V.4 COMPILER ////////////////////////////

// PURPOSE: Demonstrates the use of preprocessor definitions.
//          Calculates the cost of purchasing concert tickets based on
//          a constant ticket price. Prompts user to enter name
//          and desired amount of tickets and performs necessary
//          calculations. A report summary displaying the user's name
//          and balance is generated as output to console.
//
//
// PROGRAMMER: Mike Ware
// DATE LAST UPDATED: 2-5-02

#include <stdlib.h>
#include <stdio.h>

#define MAXNAMELENGTH 25
#define TICKETCOST 32.50
#define SHOWINDEX 25

int main()
{
      char buyerName[MAXNAMELENGTH];
      int numOfTickets;
      float balance;

      printf("Dave Matthews Band Concert #%d\n\n", SHOWINDEX);
      printf("Enter first name: ");
      scanf("%s", buyerName);
      printf("Enter desired number of tickets: ");
      scanf("%d", &numOfTickets);

      // calculate balance based on ticket price
      balance = numOfTickets * TICKETCOST;

      printf("\n\nSUMMARY REPORT\n");
      printf("-------------------------------------------------\n");
      printf("NAME: %s\n", buyerName);
      printf("BALANCE: $%.2f\n", balance);
      printf("-------------------------------------------------\n\n");

      system("PAUSE");
      return EXIT_SUCCESS;
}

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

With preprocessor statements covered, let's see how we can use basic C statements to manipulate variables. Read on for more...

Basic C Statements: Input / Output

NOTE: In some of the following program examples, conversion modifiers, which are covered in the next section, are used to format output and input. For more information, [see Input / Output Conversion Modifiers (section 2)].

The basic C statements I want to discuss deal with getting input from the user of a program and displaying output by the program. This involves using two "built-in" member functions: printf( ) and scanf( ). printf( ) and scanf( ) allow for the interaction between the user and the actual program. printf( ) is used to "print" information or "send" information to the output stream. scanf( ) is used to "grab" or "store" information inputted by the user during program execution.

printf( )
As previously mentioned, the printf( ) function is used to display information (output). This is done by placing the information to be displayed inside the parentheses of the function using a list of arguments. The printf( ) will interpret the arguments and display results accordingly. The form of the printf( ) function is as follows:

    printf( controlString, [argument1, argument2, ...] );

where controlString is a string made up of characters to be printed and conversion specifiers describing variables that need to be printed in specific regions, and [argument1, argument2, ...] is a list of arguments, which may be variables, constants, or expressions, ordered in the way they should appear in controlString; the way they will eventually appear in the true form of output. For a first example, consider:


#include <stdlib.h>
#include <stdio.h>

int main( )
{
      printf("Hi, do only geeks master C?");

      return EXIT_SUCCESS;
}

Output produced:

Hi, do only geeks master C?

Notice that the data to be displayed was sent to printf as an argument string. Situations arise when a programmer needs to display the values of variables using the printf function. This requires a different form and use of format or conversion specifiers. For example, consider:


#include <stdlib.h>
#include <stdio.h>

int main( )
{
      int number1 = 115;

      printf("The value of variable number1 is: %d", number1);

      return EXIT_SUCCESS;
}

Output produced:

The value of variable number1 is: 115

Notice the changes made in the above code segment to handle the variable named number1. The control string still remains in quotes (as a string) but %d was placed inside, and number1 was placed as a second argument succeeding the control string argument with separation between the two arguments using a comma. This general form will be used when needing to display the values of variables using the prinf( ) function. %d is a format or conversion specifier that tells the compiler that a digit (matching the corresponding variable argument) needs to be displayed where it appears in the statement; other format specifiers are described below. Since number1 is of type int, this would be sufficient. number1 is passed as an argument so the value it holds will be displayed in place of %d. Here is an outline of basic printf( ) format specifiers:

Conversion Specifiers
    %d     --> display digit
    %f     --> display floating point number (decimal point values)
    %c     --> display character value
    %s     --> display string
    %u     --> display unsigned types
    %ld     --> display digit of type long
    %i     --> display signed decimal integer
    %p     --> display pointer

Since printf( ) is a function, it must return a value. It actually returns the value of the number of characters it printed or a negative value if an error occurred. When using the printf( ) function, there are certain ASCII characters that are considered "nonprinting", which mean they cannot be explicitly included in code. Examples are backspacing, dropping to next line, generating a horizontal tab, etc. To use these "nonprinting" character values in your programs, you will have to make use of a set of C escape symbols. The following is a listing of escape symbols:

\a     --> sounds an alert
\b     --> backspace
\n     --> newline character
\r     --> carriage return
\t     --> horizontal tab
\v     --> vertical tab
\\     --> displays backslash
\'     --> displays single quote character
\"     --> displays double quote character

These symbols can be included in printf( ) like any other "normal" character. For example, consider:


#include <stdlib.h>
#include <stdio.h>

int main( )
{

      printf("C\t is not too difficult to learn.\n");
      printf("\"Hopefully, C Ripped Apart is helpful.\"\n);

      return EXIT_SUCCESS;
}

Output produced:

C      is not too difficult to learn.
"Hopefully, C Ripped Apart is helpful."

When needing to display the values of multiple variables, you simply pass the variables as arguments in the same way as in our first example. Format specifiers for each variable to be displayed must be placed in the argument control string, and the variables must be passed as arguments matched in the order in which their corresponding format specifier falls in the control string. For example, consider:


#include <stdlib.h>
#include <stdio.h>

int main( )
{
      int stuId = 115;
      char stuGrade = 'A';
      float stuScore = 93.45;

      printf("Student %d earned a total score of %f and received a letter grade of %c.", stuId, stuScore, stuGrade);

      return EXIT_SUCCESS;
}

Output Produced:

Student 115 earned a score of 93.45 and received a grade of A.

With printing results to the screen using the printf( ) function covered in a brief fashion, we can now cover how the scanf( ) function is used to "grab" data specified by the user during program execution.

scanf( )
While the printf( ) function is used for displaying output, the scanf( ) function is used to "store" data supplied by the program user during execution of a program. The general form of the scanf( ) function is similar to the printf( ) and is as follows:

    scanf( controlString, (argument list) );

where controlString is a string containing the conversion specifiers used to format the data to be converted that was inputted by the user, and argument list is a listing of variables matching their corresponding conversion specifiers in controlString that will be assigned the data values supplied by the user. For a first example, consider:


//////////////////////////// CODE COMPILED USING DEV-C++/C V.4 COMPILER ////////////////////////////

#include <stdlib.h>
#include <stdio.h>

const int MAXIDLEN = 5;

int main()
{
      char productId[MAXIDLEN];
      float retailPrice, manurPrice;
      int quantity;

      printf("Enter the product Identification Number: ");
      scanf("%s", productId);
      printf("Enter the retail price and manufacturing price separated by a space: ");
      scanf("%f %f", &retailPrice, &manurPrice);
      printf("Enter the current quantity: ");
      scanf("%d", &quantity);

      printf("\n\nPRODUCT SUMMARY\n");
      printf("------------------------------------------\n");
      printf("PRODUCT ID: %s\n", productId);
      printf("RETAIL PRICE: $%.2f\n", retailPrice);
      printf("MANUFACTURING PRICE: $%.2f\n", manurPrice);
      printf("QUANTITY: %d\n\n", quantity);

      system("PAUSE");
      return EXIT_SUCCESS;
}

//////////////////////////// CODE COMPILED USING DEV-C++/C V.4 COMPILER ////////////////////////////

It is important to note that the argument list in the form of scanf uses pointers to variables rather than simple variables, expressions, and constants. A pointer provides direct access to where the variable is stored in the memory of a computer. In order to specify arguments as being passed as pointers, you must "pass" a reference to non-structured arguments using the ampersand symbol ( & ) as shown in the above program. This means that non-structured types such as integers and floating point values must be passed as a reference but structured types such as strings and arrays can simply be passed as usual because structured types are automatically passed by reference. For more info on strings, [see Character Strings (section 2)].

The conversion specifiers for scanf( ) are almost identical to printf( ). Here is a listing:

Conversion Specifiers
    %d     --> interpret digit
    %f     --> interpret floating point number (decimal point values)
    %c     --> interpret character value
    %s     --> interpret string
    %u     --> interpret unsigned types
    %i     --> interpret signed decimal integer
    %p     --> interpret pointer

Since scanf( ) is a function, it must also return a value. It actually returns the number of items successfully read during program execution or a value of 0 indicating an error/EOF occurred. EOF is denoted as end-of-file and is used to check for the terminating character placed at the end of a file.

We have now covered how to extract input using scanf( ) and how to display output using printf( ). When using these functions, you will most likely want to format the form of the output and input. We discover how to accomplish this task in the next section. Read on for more about input / output conversion modifiers...

Move on to next set of topics: Section 2 - C Basics

Back to Top