LAB 2 - The Structure of C Programs

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

Laboratory Module 2

The Structure of C Programs



Purpose:
To understand the structure of C programs
To understand how functions work in C
To learn how to use a C programming style guide

1 Preparation Before Lab

1.1 Theoretical aspects

1.1.1 The structure of C programs
Basic C Elements
The elements of a program in any language are the fixed, or defined, elements of the language
itself combined with user-defined elements. In C, the fixed elements are its 32 keywords, its operators, and
a few symbols for governing syntax.
The most basic user-defined elements are constants and variables:
1) Constants are fixed data values that you embed directly into your C source code. Constants are often
called "hard data," "hard-coded data," or "magic numbers," because they're defined prior to
compilation and cannot be altered by a program as it executes.
2) In contrast to constants (which define actual data), variables are definitions of memory locations that
will hold data. Variables enable you to reserve a space in computer memory that a program can use to
store different values as it executes.
Statements
Both fixed and user-defined elements are like the nouns, verbs, adjectives, and adverbs of a spoken
language. They are combined to build the equivalent of sentences, which in C are called statements.
Statements are instructions to the compiler to create machine-readable code to perform a specific action.
Like a period at the end of a sentence, a semi-colon is used to signify the end of a C statement.
Many C statements contain expressions. Expressions are like phrases within a sentence. They are
the combination of constants, variables, and operators that together are evaluated to yield a value that is
used within the larger C statement.
Code Blocks and Functions
Just as sentences can be grouped together to form paragraphs, C statements can be combined into
compound statements, or code blocks. Code blocks are groups of statements that are logically related and
treated as a unit. Braces, { }, are used to signify the beginning and ending of code blocks.
The most common code block is the body of a function. A function, like a chapter in a book,
divides a program into modules that perform a specific task. Unlike chapters in a book, C functions are
independent of one another and can be processed in any order.
Every C program must have at least one function called main(). The function main() is the location
the operating system passes control to when the program is run.
Preprocessor Directives
In addition to C statements, a C program can contain instructions to the compiler called
preprocessor directives or compiler directives. Although not part of the C language, preprocessor directives
expand the C programming environment by providing a mini-language to communicate with the compiler
itself. Preprocessor directives are commonly placed at the beginning of a source file and are preceded by a
pound sign, #.
External Functions and Header Files
A common use of preprocessing directives is in conjunction with external functions. Most of the C
programs that you will write will consist of calls to functions outside your source file, or external functions.
Most external functions you will use are stored in libraries and are called library functions.
Although library functions don't need to be added to your source code, information about them
does. This information is provided in text files called header files, which are created by the writer of the
function, usually the compiler manufacturer. By convention, header files have the extension of .h .
Header files can be merged with your program automatically by the compiler through the use of a
preprocessor directive called an include directive. For this reason, header files are also referred to as
include files.
Because C contains no built-in input/output commands, the most common header file that you will
include in your program is stdio.h . The stdio.h file contains information necessary to use the standard
library's input/output functions.
One of the most common input/output functions you will use in the standard library is printf(). The
printf() function enables your program to perform formatted output.
Function Calls
In order to use a function such as printf(), your program must transfer control to the function. This
transfer of control from one function to another is accomplished through function calls. A function call
consists of the name of the called function followed by, in parenthesis, any special information the function
needs to perform its task.
Comments
To provide explanations of what various parts of your program are designed to do, you can place
comments throughout the code. Programmer comments can be placed almost anywhere in a program as
long as they're delimited by the following character pairings to the right and to the left.
/* comment */
The next program is the typical program that programmer apprentices write for the first time. It is
the simplest programs that can be written in C, but it contains the fundamental components that every C
program has.

// first program in C
#include <stdio.h>
int main (){
printf("Hello World!");
return 0;
}

// first program in C
This is a comment line. All lines beginning with two slash signs (//) are considered comments and
do not have any effect on the behavior of the program. The programmer can use them to include short
explanations or observations within the source code itself. In this case, the line is a brief description of what
our program is.
#include <stdio.h>
Lines beginning with a pound sign (#) are directives for the preprocessor. They are not regular
code lines with expressions but indications for the compiler's preprocessor. In this case the directive
#include <stdio.h> tells the preprocessor to include the stdio.h standard file. This specific file (stdio.h)
includes the declarations of the basic standard input-output library in C, and it is included because its
functionality is going to be used later in the program.
int main ()
This line corresponds to the beginning of the definition of the main function. The main function is the
point by where all C programs start their execution, independently of its location within the source code. It
does not matter whether there are other functions with other names defined before or after it - the
instructions contained within this function's definition will always be the first ones to be executed in any C
program. For that same reason, it is essential that all C programs have a main function. What is contained
within braces { } is what the function does when it is executed.
printf("Hello World");
This line is a C statement. A statement is a simple or compound expression that can actually produce
some effect. In fact, this statement performs the only action that generates a visible effect in our first
program.
Notice that the statement ends with a semicolon character (;). This character is used to mark the end of
the statement and in fact it must be included at the end of all expression statements in all C programs.
The return statement causes the main function to finish. return may be followed by a return code (in our
example is followed by the return code 0). A return code of 0 for the main function is generally interpreted
as the program worked as expected without any errors during its execution. This is the most usual way to
end a C console program.

1.1.2 Introducing functions

A C function is a sub-program. It is a small, named piece of a program that is called up from other
parts of the same program.
A function must be defined once and can be called any number of times. A function has a name,
arguments, and a body. A common problem with programs is that a function call can not be matched up to
any function in the rest of the program.
The body is compiled and stored in memory. When the call is executed the computer jumps to the start
of the body. Once in the body it executes its code until it gets to the end or a 'return' statement. If it
executes an "exit" statement the whole program terminates. If the computer gets to a return or the end of the
function then it jumps to the instruction in the program immediately after the call.
A function provides a convenient way to encapsulate some computation, which can then be used
without worrying about its implementation. With properly designed functions, it is possible to ignore how a
job is done; knowing what is done is sufficient. C makes the sue of functions easy, convenient and
efficient; you will often see a short function defined and called only once, just because it clarifies some
piece of code.
A function definition has this form:
return-type function-name(parameter declarations, if any){
local variables

function code
}
Before using a function C must have knowledge about the type it returns and the parameter types the
function expects. The ANSI standard of C introduced a new (better) way of doing this than previous
versions of C. (Note: All new versions of C now adhere to the ANSI standard.)
The importance of prototyping is:
- It makes for more structured and therefore easier to read code.
- It allows the C compiler to check the syntax of function calls.
How this is done depends on the scope of the function. Basically if a functions has been defined before
it is used (called) then you are ok to merely use the function. If NOT then you must declare the function.
The declaration simply states the type the function returns and the type of parameters used by the function.
It is usual (and therefore good) practice to prototype all functions at the start of the program, although this
is not strictly necessary.
To declare a function prototype simply state the type the function returns, the function name and in
brackets list the type of parameters in the order they appear in the function definition.

1.1.3 C Programming Style Guide

Readability
There are a number of stylistic elements which can make a program more readable, including the use
of horizontal and vertical spacing, the conventions used in declarations, etc.. Each of these elements will be
discussed in turn.
As a good programmer you should strive to enhance the visual appearance of the code you write. The
effort you put in will begin to pay dividends as you debug your code.
Indentation
Indentation is used to enable a reader to determine the nesting level of a statement at a glance. In order
to be useful, indentation must be consistent the number of spaces used per indentation level should be
between 2 and 5 and the same style of indentation should be used throughout the program. Proper
indentation makes your program much easier to debug.

Spaces
Normally in programming the standard for the use of spaces is that you follow normal English rules.
This means that:
1. Most basic symbols in C (e.g., =, +, etc.) should have at least one space before and one space
after them, with the following notable exceptions:
- No space appears before a comma or a semicolon.
- No space appears before or after a period.
- No space appears between unary operators and their operands (e.g., ->, ++).
2. More than one space may be used if you are aligning things on adjacent lines.
Blank Lines
Blank lines should be used to separate long, logically related blocks of code. Specifically:
1. In the global section of a compilation unit, the include, const, typedef, and variable declaration
sections should be separated by at least one blank line.
2. Within a long piece of code, groups of related statements may be separated from other groups by a
blank line.
3. To be effective as an element of style, blank lines should be used consistently.
Statements
1. Each statement should appear on a separate line.
2. The opening brace following a control statement such as if or while should appear on the line after
the if or while, lined up with the left of the control statement, and the closing brace should appear on its
own line, lined up with the left of the control statement. The opening and closing braces for a function
should be lined up in the same way.
3. The statements within a { } pair are indented relative to the braces.
4. Even if only a single statement falls in the body of a compound statement, it is indented on a
separate line.
Declarations
1. Variables should be listed one per line (possibly with the exception of loop indices), with the type of
the variable preceding every declaration. Do not put blank lines between identifiers being declared. The
same rules apply to fields declared within a struct.
2. Related variables should be grouped together in the declaration section.
Comments
In the real world, both maintenance programmers and other members of a programming team rely on
comments to explain the program, function, or code fragment they are reading. If a comment and the code
disagree, the comment is presumed to be correct, and the code incorrect. Comments are used primarily to
state what the code is doing (its purpose), while the code itself describes how you are doing it. Thus, it is
only common sense that you should write the comment first (i.e., define what you are doing) before you
write the code.
Declaration Comments
1. Constants and variables are always commented with short, precise comments stating their purpose.
These comments normally follow the declaration on the same line and only rarely take more than a line or
two.
2. It is usually not necessary to comment types, whether global or local. However, fields within a struct
are always commented.
Sidebar Comments
A sidebar comment is one which explains a single statement and should follow the statement on the
same line. The comment should be brief, accurate and precise.
A sidebar comment should always be used after a closing brace to uniquely identify the compound
statement which is being ended, and is essential in finding the matching opening brace. In the case of a
function, the comment contains the name of the function.
In-line Comments
In-line comments explain a block of code. Such a comment should precede the code itself and should
be indented the same as the block it describes. A blank line should be placed before the in-line comment,
between the in-line comment and the block of code, and after the block of code to separate it from the next
block of code.
Sidebar comments and in-line comments should be used sparingly. Before adding such comments you
should first attempt to make the code itself more understandable by improving the identifier names used,
replacing groups of statements with function calls, reducing the control complexity of the code, etc..
Naming
When choosing names for items in your program, order is very important. As an example, suppose a
variable state has been declared of type StateType. This is fine as long as only one variable of this type is
used. The naming problem starts when a second variable of the same type is needed. A first possibility is
state2. This is certainly better than naming it s, but it would have been even better to pick really good
names like currentState, lastState, normalState, errorState, etc. for the variables and just name the type
State.
It is clear from this example that the type names must be chosen first. After having chosen the type
names one can start to name the functions, variables, and constants.
Type Names
The simplest and shortest names should be reserved for type (struct, class, etc.) identifiers. Therefore
they must be chosen before any other name, especially before the names for variables of this type. Types
should be named with short, generic nouns that reflect their contents. Type names should start with a
capital letter and, if the name consists of several words concatenated together, each successive word should
also be capitalized.
Examples: Entry, Table, Name, Node, StateTable.
Variable Names
In strongly typed languages, a variable is of a particular type. Therefore the structure adjective + type
name for variable names is an obvious suggestion. (The name does not have to contain an adjective;
alternatively, a name can take on the more general form qualified type name). Note that this naming
convention is not always appropriate however, especially when variables have standard types. For instance,
if your program contains an integer variable which stores the length of a list, it would be much better to
choose listLength or just length over lengthInt! The first letter of variable names should not be capitalized,
but each successive word in the name is capitalized.
Examples: response, length, currentEntry, headPointer.
It also acceptable to put an underscore character between words in a variable name.
Examples: current_entry, head_pointer, current_symbol.
Constants
All non-trivial constant values in a program should be assigned names. Constants often describe a limit
within a program. In these cases it is appropriate to use the prefix MAX or MIN in conjunction with the type
name. Otherwise, name constants like variable names. Names for constants should be in all capital letters
with underscores between words. This convention is also used for symbols defined in #define preprocessor
directives.
Examples: MAX_FRIENDS, PI, BLANK, MAX_LINE_LENGTH.
Functions
Function Prologues
The major reason for a function prologue is to explain the purpose of the function. A function prologue
should appear just before the implementation of the function and include the following sections:
1. Function name and parameter list: just as it appears later in the actual code.
2. Purpose: what the function does.
3. Algorithm: how the function does what it does. If a standard algorithm such as Quicksort is used, a
reference rather than an explanation is preferred.
4. Input and Output: what the function will expect from the user and what the user will see on the
screen.
5. Precondition: what assumptions the function makes about its input; under what conditions it fails to
operate properly.
6. Postcondition: what should be true after the routine is finished. An explanation of the return value, if
any, should also be included. Also include an explanation of any changed reference parameters.
Any of the above items except the first two may be left out if they are inappropriate. For example, if
the function does not expect any input, leave out the input section.
Function Names
Functions should be named differently depending upon whether they return a value. A void function is
(literally) called by its name, which stands for a group of statements to be executed. Therefore the name of
a void function should express the implied action (do this) by including an imperative verb. Since
functions operate on a specific type, the structure verb + type name is best suited for a function name.
Function names should be capitalized like type names.
Examples: GetEntry, DisplayError, PrintAddress, GetFirstElement, FindName.
Functions that return a value should contain nouns or adjectives. Again, since these types of functions
operate on a specific type, the form adjective + type name or noun + type name are good choices.
Examples: GreatestItem, CubeRoot, LastNode, HeadOfList, IsEmpty.
Formatting Function Declarations
The following guidelines apply to function declarations and prototypes.
1. When declaring functions, the leading parenthesis and first parameter (if any) are to be written on
the same line as the function name. Then, each subsequent parameter should be listed on a separate line to
allow for each to be commented.
2. Each function parameter is always commented on the same line as the declaration.
3. In function declarations and prototypes, a space should appear after the opening parenthesis
beginning the parameter list and before the matching closing parenthesis. However, no such spaces should
be used in function calls.
4. Functions should be separated by at least two blank lines.
An Example Program Edit the sample code: students.c

//********************************************************************
// students.c
// Author: Joe Student
// Date: May 15, 2008
// Class: Computer Programming
// Purpose: This program manages students.
// Input: (from standard input) first names, last names and phone numbers
// Output: (to an output file) an alphabetical listing of students
//********************************************************************
#include <stdio.h>
#include <iostream.h>
#include <iomanip.h> // For setw()
#include <fstream.h> // For file I/O
#include <string.h> // For strcmp()
#include <ctype.h> // For toupper()

const int MAX_STUDENTS = 150; // Maximum number of students

typedef struct Student
{
char firstName[9]; // First name of a student
char lastName[16]; // Last name of a student
char phoneNumber[10]; // Phone number of a student
};

void GetStudent( Student &student );
void Insert(Student list[], Student student, int *length);
void DisplayStudents(Student list[], int length);

int main( void )
{
Student addressBook[MAX_STUDENTS]; // Array of students' records
int length = 0; // Number of entries in addressBook
Student currentStudent; // Current record being entered
char response; // Response character from keyboard

// Prompt the user for up to MAX_FRIENDS address book entries
do
{
GetStudent(currentStudent);
printf("\n-->%s",currentStudent.firstName);
printf("\n-->%s",currentStudent.lastName);
printf("\n-->%s",currentStudent.phoneNumber);

printf("\n Is this entry correct? (Y or N) ");
fflush(stdin);
response = getchar();
printf("\n 1response = %c",response);
if (toupper(response) == 'Y'){
printf("\n inainte: length = %d ", length);
Insert(addressBook, currentStudent, &length);
printf("\n dupa: length = %d ", length);
DisplayStudents(addressBook, length);
}
printf("\n Do you wish to continue? (Y or N) ");
fflush(stdin);
response = getchar();
printf("\n 1response = %c",response);
} while (toupper(response) == 'Y' && length < MAX_STUDENTS);

if (length == MAX_STUDENTS)
printf("Address book is full.\n");
DisplayStudents(addressBook, length);
fflush(stdin);
getchar();
} // main()

//*********************************************************************
// void GetStudent( Student& theStudent )
// Purpose: Builds and returns a complete address book entry
// Input: (from standard input) a student's first name,
// last name, phone number
// Postcondition: User has been prompted for a student's first name
// and last name
// && entry.firstName == input string for first name
// && entry.lastName == input string for last name
//*********************************************************************
void GetStudent( Student &theStudent ) // Struct being built
{
// Get a students first name
printf("\n Enter student's first name: ");
scanf("%s", theStudent.firstName);
// Get a students last name
printf("\n Enter student's last name: ");
scanf("%s",theStudent.lastName);
// Get a student's phone number
printf("\n Enter student's phone number: ");
scanf("%s",theStudent.phoneNumber);
} // GetEntry()

//*********************************************************************
// void Insert( Entry list[], int& length, Entry item )
// Purpose: Inserts item into its proper place in sorted list
// Precondition: length < MAX_STUDENTS
// && list[0..length-1] are in ascending order
// && item is assigned
// Postcondition: item is in list
// && length == length@entry + 1
// && list[0..length-1] are in ascending order
// && IF item was already in list@entry
// item has been inserted before the one that
// was there
//*********************************************************************
void Insert( Student list[], Student item, int *length ) // Item to be inserted
{
printf("\n enter insert!");
int index = 0; // Position where item belongs
int count; // Loop control variable
list[*length] = item; // store item at position beyond end of list
// Exit loop when item is found, perhaps as sentinel
while (strcmp(item.lastName, list[index].lastName) > 0)
index++;
// Shift list[index..length-1] down one
for (count = *length - 1; count >= index; count--)
list[count+1] = list[count];
list[index] = item; // Insert item
printf("\n inainte##: length = %d ", *length);
(*length)++; // Increment length of list
printf("\n dupa##: length = %d ", *length);
printf("\n exit insert");
} // Insert()

//******************************************************************
// void DisplayStudents( const Student addressBook[], int length)
// Purpose: Displays all entries to the standard output
// Precondition: length <= MAX_FRIENDS
// && addressBook[0..length-1] are assigned
// Postcondition: Contents of addressBook[0..length-1] have been
// output to standard output
//******************************************************************
void DisplayStudents(Student list[], int length) // Number of entries
{
printf("\n enter display-length = %d ", length);
for (int counter = 0; counter < length; counter++)
{
printf("\n %s ", list[counter].firstName);
printf("%s ", list[counter].lastName);
printf("%s ", list[counter].phoneNumber);
} // for
} // DisplayStudents()

2 Examples
Example 1. Edit sample program power.c
/* Example: C program that computes power(x,y) = x
y
*/
#include <stdio.h>

int power(int base, int n); /* prototype */

main() {
int i; /* handy variable */
for (i = 0; i <= 10; ++i)
printf("2^%d %d\n",i,power(2,i));
}//end for

int power(int base, int i) {
int n; /*handy variable */
for (n = 1; i > 0; --i)
n = n * base;
return n;
}

Example 2. Edit sample program factorial.c
/* Example: A simple recursive factorial */

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

int fact(int);

int fact(int n){
if(0==n || 1==n)
return 1;
else
return n*fact(n-1);
}

void main(void){
int result = 0;
int x = 0;

printf(" n = ");
scanf("%d", &x);
result = fact(x);
printf("fact(%d) = %d", x, result);
}

3 Assignments

I.
1) A real number rad represents an angle in radians. Write a program that converts rad in degrees,
minutes and seconds.
2) It is known the time (HH:MM:SS) when a runner starts a race and also the time when he finishes it
(HH:MM:SS). Write a program that computes the running time.
3) Determine the largest (max) and the smallest (min) element from a sequence. The number of elements
n and the elements Ai are read from the standard input into the same variable.
4) There are given the grades obtained by students. Write a program that determines if all students passed
the exam or not. Calculate the percentage of students that obtained grades smaller than 8.
5)
a. Convert a number from base 10 into base 2.
b. Convert a number from base 2 into base 10.
c. Determine prime numbers smaller than a given number
6) Write a program which has 7 functions. The functions should be:
main() this calls the other 6 functions
getchar() a function which returns a char data type (from stdio.h)
get_short() a function which returns a short integer variable
get_float() a function which returns a floating point variable
prt_char() a function which prints its single, char argument
prt_short() a function which prints its single, short argument
prt_float() a function which prints its single, floating point argument
You should use scanf() to get the values of the variables from the input (the keyboard) and printf()
to print the values to the terminal.
7) Write a program that, given an integer, determines if it is prime or not (if it is not prime, you do not
need to print its factors).
8) The movie theater gives a discount to the customer if all of the following conditions apply:
- The customer is at most 17 years of age.
- The length of the movie is not more than 90 minutes.
(a) Complete the following C statement that prints out whether the customer gets a discount or not.

if ( (age ____ 17) ____ (movieLength ____ 90) )
printf("DISCOUNT APPLIES");
else
printf("NO DISCOUNT");
(b) Use DeMorgan's law to rewrite the if statement above without using the same logical operator you
used in part (a).
9) Write a simple C program that prompts the user to enter a Pittsburgh professional sports team. If they
enter "PIRATES", print out the message "Home run!". Or if they enter "STEELERS, print out the
message "Touchdown!". Or if they enter "PENGUINS", print out the message "Goal!". Otherwise,
print out "You lose.".
Keep in mind that they might not enter a sports team using all uppercase letters. For example, if they
enter "Pirates", you can treat that as "PIRATES". Otherwise, the team name must match exactly. For
example, "STEALERS" is not a match.

II.
1) How many ending 0s are in the product p=a1*a2**an ?
2) It a considered a system of equations determined by the values of coefficients a, b, c, m, n, p.
aX + bY = c
mX + nY = p
Find the solutions of the system. A discussion is needed.
3) Write a program that computes the solutions of a 2-nd degree equation aX^2 + b^X + c =0. The a, b, c
coefficients are real numbers and are known.
4) A point in plane is given by its coordinates (x,y). Write a program which finds the quadrant(s) a given
point belongs to.
5) Write a program with three functions besides main(). The first will have two arguments - a character
array and a short integer which holds the size of the array. With this function, initialize the elements of
the array to the characters of the alphabet, beginning with the letter entered at the keyboard and ending
with lower case 'z'. Thus, if the character entered is an 'a', then the array will have 26 characters (the
whole alphabet) stored into it. The second function will have three arguments - the character array
which was initialized by the first function, the number of characters actually stored into the array, and
an integer array (short) which is the same size as the maximum size of the character array. Set each
element of the short integer array equal to the decimal value of the alphabetic characters in the
character array. In the third function, print the characters in the character array to the standard output
using the "putchar()", built-in function, along with the decimal value of that character using the
fprintf() function (use stdout for the fp argument).
6) Write a program that finds the minimum number of bills and coins necessary to return a given amount
of money (Note: there are available 1c, 5c, 20c, 50c coins and 1$, 5%, 10$, 20$, 50$, 100$ bills).



III.

1) Write a program that computes

) 1 (
2
1 1
2


=
= =
N N
x x N
N
i
i
N
i
i
sigma
In is given the value of N and the values of measurements (
i
x ).
2) An integer number is said to be perfect number if its factors, including 1 but not the number itself, sum
to the number. For example, 6 is a perfect number because 6 = 1 + 2 + 3. Write a function perfect that
determines if the parameter number is a perfect number. Use this function in a program that determines
and prints the perfect numbers between 1 and 1000. Print the factors of each perfect number to confirm
that the number is indeed perfect. Challenge the power of your computer by testing numbers much
larger than 1000.
3) Write a recursive function power(base, exponent) that when invoked returns base
exponent
.
4) The greatest common divisor (gcd) of a non-negative integer M and a positive integer N can be defined
as follows, where mod(M, N) is the remainder when M is divided by N.
gcd(M, N) = N if mod(M, N)=0
= gcd(N, R) if mod(M, N) = R, where R > 0.
Design and test a recursive function in C called gcd(intM,intN) that computes the GCD of a sequence
of one or more pairs of integers prompted from the user. Recall that the % operator in C computes the
required mod operation. As your program is computing a GCD, it is to have the ability to print out a
new line to the screen to indicate each call to the function gcd. This line is to list the current values of
M and N. This "verbose" mode of operation is to be enabled or disabled when the program first starts
running, in response to a question sent to the user by the main function.

You might also like