CS137Part02 Loops Functions Recursion Arrays Post
CS137Part02 Loops Functions Recursion Arrays Post
• Like with switch statements, you can use the break; command
to end the termination of a while, do or for statement early.
• C also has continue statements which allows you to exit the
loop body early and go to just before the end of the loop body
• There is also a goto command that can jump to any labelled
part of the program.
• Using these statements almost always makes code harder to
read and so most programmers avoid or limit the use of these
as much as possible.
Example - Sum Three Nonzero Integers
Write a program that asks the user for an integer and determines if
it is a prime number. Print “Not Prime” if it is not prime and
“Prime” otherwise.
• Recall: A prime number is an integer greater than 1 whose
only positive divisors are 1 and itself.
Idea 1
Count all the divisors of the given number and if it is 2, we have a
prime number.
# include < stdio .h >
int main ( void ) {
int n , div =1 , c =0;
scanf ( " % d " ,& n );
if (n <=1) printf ( " Not Prime " );
else {
while ( div <= n ){
if ( n % div == 0) c ++;
div ++;
}
if ( c ==2) printf ( " Prime " );
else printf ( " Not Prime " );
}
return 0;
}
Optimization
There are a few ways we can make this code run faster
• If we have a non-prime number, then it has a divisor between
the number itself and 1 (not including endpoints). If we find
this, we can immediately break the code and print not prime
√
• If it has such a divisor d, there must be one less than n
where n is the given number for one of d or n/d is bounded
√
above by n.
• Let’s rewrite the code to account for these changes.
Idea 2
Search for a single divisor not 1 or n and if we find one return false.
# include < stdio .h >
int main ( void ) {
int n , div =2;
scanf ( " % d " ,& n );
if (n <=1) printf ( " Not Prime " );
else {
while ( div * div <= n ){
if ( n % div == 0) break ;
div ++;
}
if ( div * div <= n ) printf ( " Not Prime " );
else printf ( " Prime " );
}
return 0;
}
Comments
• This works well but gives us some problems if the year were
say negative.
• In fact, since we are in North America, we probably want the
year to be at least 1752.
• We can accomplish this by using assert statements.
• First, add #include <assert.h> to the beginning then
include assert(year > 1752);
Assert
• In general, assert(expr);
• If expr is true, this line does nothing
• Otherwise, it terminates the program with a message
containing the filename, line number, function and expression.
• This is great for debugging.
• Also great to leave it in (so long as expr is not
computationally expensive). Helps to remember assumptions,
causes program to fail “loudly” vs “quietly”, advises other
programmers if code undergoes modifications.
• Good for regression testing as well, that is checking that
changes haven’t broken anything in another part of the code.
Separate Compilation
Below are the contents of powers.c - the file defining the header
functions.
# include " powers . h " // notice the quotes !
int square ( int num ) { return num * num ;}
int cube ( int num ) { return num * square ( num );}
int quartic ( int num ) {
return square ( num )* square ( num );}
int quintic ( int num ) {
return square ( num )* cube ( num );}
Note - we separate these to help reduce compile time.
main.c
Below are the contents of main.c - the file defining the header
functions.
# include < stdio .h >
# include " powers . h "
int main ( void ){
int num =3;
printf ( " % d ^4 = % d \ n " , num , quartic ( num ));
num = 2;
printf ( " % d ^5 = % d \ n " , num , quintic ( num ));
return 0;
}
Note - we separate these to help reduce compile time.
Compiling
• To compile, use
gcc -o powers powers.c main.c
• This compiles the code into assembly code then to object
code and these files are automatically passed to the linker
merging them to a single file.
• Reminder the -o command means to send the output to the
filename immediately following.
• If you don’t want to link the files (ie you just want to
compile), use the command -c.
C Compiler
Source:
https://i.ytimg.com/vi/VDslRumKvRA/maxresdefault.jpg
More on Macros
Nor is
int a[n+1];
This is called a variable length array and is very frowned upon (in
fact, the official C standard rendered this feature as “optional” in
the later C11 standard). I wanted to show you this as an example.
We will not be using variable length arrays in our codes and is only
here to show you some additional examples and features (and so
that you can avoid it). Code found using variable length arrays will
receive 0.
Important Notes (Continued)
0 1 2
10 11 12
20 21 22
30 31 32
However...
0 a[0][0]
1 a[0][1]
2 a[0][2]
10 a[1][0]
11 a[1][1]
12 a[1][2]
20 a[2][0]
Example
• The line
sum += a[i][j];
can be replaced with
sum += a[0][i*3+j];
(Think back to how the memory model works!
• When initializing, all dimension except possibly the first must
be explicit. This holds also in function definitions.
• Example: int a[][2] = {{1,2},{3,4}};
• We will return in a few weeks to discuss more about pointers
in more detail.
Recursion
1 + b + b 2 + b 3 + ... + b n .