COMP1511 Programming Fundamentals

## COMP1511 Course Resources

Lab/Test/Assignment
Home computing
Resources
Other
Revision

## COMP1511 Week-by-Week

Tutorial
Laboratory
Tuesday February 26 Lecture Topics
Wednesday February 27 Lecture Topics
Tutorial
Laboratory
Tuesday March 06 Lecture Topics
Wednesday March 07 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday March 13 Lecture Topics
Wednesday March 14 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday March 20 Lecture Topics
Wednesday March 21 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday March 27 Lecture Topics
Wednesday March 28 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday April 10 Lecture Topics
Wednesday April 11 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday April 17 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday May 01 Lecture Topics
Wednesday May 02 Lecture Topics
Tutorial
Laboratory
Weekly Test
Wednesday May 08 Lecture Topics
Wednesday May 09 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday May 15 Lecture Topics
Wednesday May 16 Lecture Topics
Tutorial
Laboratory
Weekly Test
Tuesday May 22 Lecture Topics
Wednesday May 23 Lecture Topics
Tutorial
Laboratory
Tuesday May 29 Lecture Topics

## COMP1511 Topic-by-Topic

Course Overview
Introduction To C

A simple program demonstrating the use of printf

Compile by typing
` dcc -o hello_world hello_world.c `
or at home
` gcc -Wall -O -o hello_world hello_world.c `

Run by typing:
` ./hello_world `

```    ```#include <stdio.h>

int main(void) {
printf("Hello World!\n");
return 0;
}

``````

```    ```// This is a simple template for your first C programs
// Description
// Author
// Date

#include <stdio.h>

int main(void) {

printf("REPLACE THIS PRINTF WITH YOUR CODE\n");

return 0;
}

``````

C Basics

A simple program demonstrating the use of scanf to sum 2 numbers
```    ```#include <stdio.h>

int main(void) {
int x, y, sum;
printf("Enter x: ");
scanf("%d", &x);
printf("Enter y: ");
scanf("%d", &y);
sum = x + y;
// These 6 printfs can be better replaced by a single printf
printf("%d", x);
printf(" + ");
printf("%d", y);
printf(" = ");
printf("%d", sum);
printf("\n");
return 0;
}

``````

A simple program demonstrating the use of scanf to sum 2 numbers
```    ```#include <stdio.h>

int main(void) {
int x, y, sum;
printf("Enter x: ");
scanf("%d", &x);
printf("Enter y: ");
scanf("%d", &y);
sum = x + y;
printf("%d + %d = %d\n", x, y, sum);
return 0;
}

``````

A simple program demonstrating the use of scanf to sum 2 numbers
```    ```#include <stdio.h>

int main(void) {
int x, y;
printf("Enter x: ");
scanf("%d", &x);
printf("Enter y: ");
scanf("%d", &y);
printf("%d + %d = %d\n", x, y, x +y);
return 0;
}

``````

A simple program demonstrating the use of scanf
```    ```#include <stdio.h>

int main(void) {
int x, y;

printf("Enter x: ");
scanf("%d", &x);
printf("Enter y: ");
scanf("%d", &y);
answer = x * x + y * y;
printf("x squared + y squared = %d\n", answer);
return 0;
}

``````

Convert a temperature in fahrenheit to celsius
```    ```#include <stdio.h>

int main(void) {
double fahrenheit, celsius;

printf("Enter Fahrenheit temperature: ");
scanf("%lf", &fahrenheit);
celsius = 5.0 / 9.0 * (fahrenheit - 32);
printf("%lf Fahrenheit = %lf Celsius\n", fahrenheit, celsius);
return 0;
}

``````

Demonstrate approximate representation of reals producing error. sometimes if we subtract two approximations which are very close together we can can get a large relative error
correct answer if x == 0.000000011 (1 - cos(x)) / (x * x) is very close to 0.5 code prints 0.917540 which is wrong by a factor of almost two
```    ```#include <stdio.h>
#include <math.h>

int main(void) {
double x, y;
x = 0.000000011;
y = (1 - cos(x))  / (x * x);
printf("correct answer = ~0.5 but y = %lf\n", y);
return 0;
}

``````

Demonstrate approximate representation of reals
The value 0.1 can not be precisely represented as a real
As a result a non-zero value is printed
```    ```#include <stdio.h>

int main(void) {
double a, b;
a = 0.1;
b = 1 - (a + a + a + a + a + a + a + a + a + a);
printf("%g\n", b);
return 0;
}

``````

If

A simple program demonstrating the use of scanf and if statements
```    ```#include <stdio.h>

int main(void) {
int a, b;
printf("Enter a: ");
scanf("%d", &a);
printf("Enter b: ");
scanf("%d", &b);
if (a > b) {
printf("a is greater than b\n");
} else if (a < b) {
printf("a is less than b\n");
} else {
printf("a is equal to b\n");
}
return 0;
}

``````

A simple program demonstrating the use of scanf and if statements
```    ```#include <stdio.h>

int main(void) {
int a, b;
printf("Enter a: ");
scanf("%d", &a);
printf("Enter b: ");
scanf("%d", &b);
if (a > b) {
printf("%d is greater than %d\n", a, b);
} else if (a < b) {
printf("%d is less than %d\n", a, b);
} else {
printf("%d is equal to %d\n", a, b);
}
return 0;
}

``````

Convert a measurement in feet to metres

A simple program demonstrating the use of scanf, printf and an if statement

```    ```#include <stdio.h>

int main(void) {
int x, absoluteValue;

printf("Enter number: ");
scanf("%d", &x);

absoluteValue = x;
if (x < 0) {
absoluteValue = -1 * x;
}

printf("The absolute value of %d is %d\n", x, absoluteValue);
return 0;
}

``````

Print the result of an integer division

```    ```#include <stdio.h>

int main(void) {
int x, y;

printf("Enter x: ");
scanf("%d", &x);
printf("Enter y: ");
scanf("%d", &y);

if (y != 0) {
printf("%d/%d=%d\n", x, y, x/y);
} else {
printf("Can't divide by zero sorry\n");
}
return 0;
}

``````

A simple program demonstrating the use of scanf and if statements with complex conditions
```    ```#include <stdio.h>

#include <stdio.h>

int main(void) {
int x;
printf("Enter x: ");
scanf("%d", &x);

printf("%d has ", x);
if (x < 10 && x > -10) {
printf("1 digit");
}
if ((x >= 10 && x < 100) || (x <= -10 && x > -100)) {
printf("2 digits");
}
if (x >= 100 || x <= -100) {
printf("more than 2 digits");
}
printf("\n");

return 0;
}

``````

A simple program demonstrating the use of scanf and nested if statements
```    ```#include <stdio.h>

int main(void) {
int a;
printf("Enter a: ");
scanf("%d", &a);

printf("%d is a ", a);
if (a < 0) {
if (a < -100) {
printf("big");
} else {
printf("small");
}
printf(" negative");
} else {
if (a > 100) {
printf("big");
} else {
printf("small");
}
printf(" positive");
}
printf(" number.\n");

return 0;
}

``````

A simple program to check Pythagorean identity

Demonstrates danger of use == with doubles e.g. enter 1 for theta
```    ```#include <stdio.h>
#include <math.h>

int main(void) {
double theta, identity;

printf("Enter theta: ");
scanf("%lf", &theta);

identity = 1 - (sin(theta) * sin(theta) + cos(theta) * cos(theta));

if (identity == 0.0) {
printf("Pythagorean identity true for %lf\n", theta);
} else {
printf("Pythagorean wrong by %g for %lf\n", identity,  theta);
}

return 0;
}

``````

Calculate relativistic-mass of an object
```    ```#include <stdio.h>
#include <math.h>

#define SPEED_OF_LIGHT 299792458.0

int main(void) {
double mass, rest_mass;
double velocity;
double ratio;

printf("Enter rest mass: ");
scanf("%lf", &rest_mass);

printf("Enter velocity in metres/second: " );
scanf("%lf", &velocity);

// compute velocity as a fraction of speed of light
ratio = velocity / SPEED_OF_LIGHT;

if (ratio >= 1.0) {
printf("Error: velocity exceeds speed of light.\n");
} else {
// compute observed mass using Einstein's equation
mass = rest_mass / sqrt(1.0 - ratio*ratio);
printf("Observed mass = %1.6f\n", mass);
}

return 0;
}

``````

Functions

Lecture example illustrating simple function
```    ```#include <stdio.h>

// given x calculate value of polynomial with coefficients a, b, c

double evaluate_quadratic(double a, double b,  double c, double x) {
return (a * x * x) + (b * x) + c;
}

int main(int argc, char *argv[]) {
double x;
printf("Enter x: ");
scanf("%lf", &x);

double value = evaluate_quadratic(2.0, -3.0, 4.0, x);

printf("2x^2 - 3x + 4 = %lf\n", value);

return 0;
}

``````

Lecture example illustrating simple function
```    ```#include <stdio.h>
#include <math.h>

// given x calculate value of polynomial with coefficients a, b, c

double quadratic_root(double a, double b,  double c) {
return (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
}

double evaluate_quadratic(double a, double b, double c, double x) {
return (a * x * x) + (b * x) + c;
}

int main(int argc, char *argv[]) {
double a, b, c;
printf("Enter a: ");
scanf("%lf", &a);
printf("Enter b: ");
scanf("%lf", &b);
printf("Enter c: ");
scanf("%lf", &c);

double root = quadratic_root(a, b, c);

printf("Calculated root is %lf\n", root);

double value = evaluate_quadratic(a, b, c, root);

printf("The value of the quadratic for  %lf is %lf\n", root, value);

return 0;
}

``````

Simple lecture example of using functions
```    ```#include <stdio.h>

// calculate x to the power of 3
double cube(double x) {
double result;
result = x * x * x;
return result;
}

int main(void) {
double a, b;
printf("42 cubed is %lf\n", cube(42.03));
a = 2;
b = cube(a);
printf("2 cubed is %lf\n", b);
return 0;
}

``````

Simple lecture example of using functions
```    ```#include <stdio.h>

void print_hundred_messages(void);
void print_ten_messages(void);
void print_message(void);

int main(int argc, char *argv[]) {
print_hundred_messages();
return 0;
}

void print_hundred_messages(void) {
print_ten_messages();
print_ten_messages();
print_ten_messages();
print_ten_messages();
print_ten_messages();
print_ten_messages();
print_ten_messages();
print_ten_messages();
}

void print_ten_messages(void) {
print_message();
print_message();
print_message();
print_message();
print_message();
print_message();
print_message();
print_message();
}

void print_message(void) {
printf("C is good.\n");
printf("C is great.\n");
printf("We all love C.\n");
}

``````

Simple example illustrating call by value
```    ```#include <stdio.h>

int f(int x) {
int y;
// these assignments will have no effect on variables
// outside the function
x = x + 1;
y = 3;
return x * y;
}

int main(int argc, char *argv[]) {
int  x, y , z;
x = 1;
y = 2;
z = f(y);
// note the variables x & y are local to main
// and are not changed by assignment to variables
// of the same name in f
printf("x=%d y=%d z=%d\n", x, y, z);
return 0;
}

``````

Simple recursive calculation of factorials & Fibonacci numbers http://en.wikipedia.org/wiki/Factorial http://en.wikipedia.org/wiki/Fibonacci_number

Fibonacci calculation is very inefficient

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

int fibonacci(int n) {
if (n < 2) {
return 1;
}
return fibonacci(n - 1) + fibonacci(n-2);
}

int factorial(int n) {
if (n < 2) {
return 1;
}
return n * factorial(n - 1);
}

int main(void) {
int x;

printf("Enter number: ");
scanf("%d", &x);

printf("factorial %d = %d\n", x, factorial(x));
printf("fibonacci %d = %d\n", x, fibonacci(x));

return 0;
}

``````

While

A silly program which prints first 1000 multiples of 13

```    ```#include <stdio.h>

int main(void) {
printf("%d\n", 13);
printf("%d\n", 26);
printf("%d\n", 39);
printf("%d\n", 52);
printf("%d\n", 65);
printf("%d\n", 78);
printf("%d\n", 91);
printf("%d\n", 104);
printf("%d\n", 117);
printf("%d\n", 130);
printf("%d\n", 143);
printf("%d\n", 156);
printf("%d\n", 169);
printf("%d\n", 182);
printf("%d\n", 195);
printf("%d\n", 208);
printf("%d\n", 221);
printf("%d\n", 234);
printf("%d\n", 247);
printf("%d\n", 260);
printf("%d\n", 273);
printf("%d\n", 286);
printf("%d\n", 299);
printf("%d\n", 312);
printf("%d\n", 325);
printf("%d\n", 338);
printf("%d\n", 351);
printf("%d\n", 364);
printf("%d\n", 377);
...
``````

A silly program which prints first 1000 multiples of 13

```    ```#include <stdio.h>

int main(void) {
if (1 % 13 == 0) {
printf("%d\n", 1);
}
if (2 % 13 == 0) {
printf("%d\n", 2);
}
if (3 % 13 == 0) {
printf("%d\n", 3);
}
if (4 % 13 == 0) {
printf("%d\n", 4);
}
if (5 % 13 == 0) {
printf("%d\n", 5);
}
if (6 % 13 == 0) {
printf("%d\n", 6);
}
if (7 % 13 == 0) {
printf("%d\n", 7);
}
if (8 % 13 == 0) {
printf("%d\n", 8);
}
if (9 % 13 == 0) {
printf("%d\n", 9);
}
if (10 % 13 == 0) {
printf("%d\n", 10);
...
``````

A silly program which prints first 1000 multiples of 13

Note the same 4 lines are repeated 13000 times.
This means these lines could be replaced by a while loop which executes 13000 times.

```    ```#include <stdio.h>

int main(void) {
int i;
i = 1;
if (i % 13 == 0) {
printf("%d\n", i);
}
i = i + 1;
if (i % 13 == 0) {
printf("%d\n", i);
}
i = i + 1;
if (i % 13 == 0) {
printf("%d\n", i);
}
i = i + 1;
if (i % 13 == 0) {
printf("%d\n", i);
}
i = i + 1;
if (i % 13 == 0) {
printf("%d\n", i);
}
i = i + 1;
if (i % 13 == 0) {
printf("%d\n", i);
}
i = i + 1;
if (i % 13 == 0) {
printf("%d\n", i);
}
...
``````

A simple program which uses a while loop to print first 1000 multiples of 13

```    ```#include <stdio.h>

int main(void) {
int i;
i = 1;
while (i <= 13000) {
if (i % 13 == 0) {
printf("%d\n", i);
}
i = i + 1;
}

return 0;
}

``````

Another simple program which uses a while loop to print first 1000 multiples of 13

```    ```#include <stdio.h>

int main(void) {
int i;
i = 13;
while (i <= 13000) {
printf("%d\n", i);
i = i + 13;
}
return 0;
}

``````

Another simple program which uses a while loop to print first 1000 multiples of 13

```    ```#include <stdio.h>

int main(void) {
int i;
i = 1;
while (i <= 1000) {
printf("%d\n", i*13);
i = i + 1;
}
return 0;
}

``````

A simple program demonstrating the use of a while loop

```    ```#include <stdio.h>

int main(void) {
int n, upperBound, sum;
sum = 0;
upperBound = 10;
n = 1;
while (n <= upperBound) {
sum = sum + n;
n = n + 1;
}
printf("Sum of integers 1..%d is %d\n", upperBound, sum);
return 0;
}

``````

Read 43 numbers and then print the sum of the numbers

A simple program demonstrating while & scanf

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#define N_NUMBERS 42

#include <stdio.h>

int main(void) {
int x, sum, n;

sum = 0;
printf("Enter %d numbers:\n", N_NUMBERS);

n = 0;
while (n < N_NUMBERS) {
scanf("%d", &x);
sum = sum + x;
n = n + 1;
}

printf("Sum of the numbers is %d\n", sum);
return 0;
}

``````

Read n numbers and then print the sum of the numbers

A simple program demonstrating while & scanf

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

int main(void) {
int x, sum, n, nNumbers;

sum = 0;
printf("How many numbers do you wish to sum: ");
scanf("%d", &nNumbers);
printf("Enter %d numbers:\n", nNumbers);

n = 0;
while (n < nNumbers) {
scanf("%d", &x);
sum = sum + x;
n = n + 1;
}

printf("Sum of the numbers is %d\n", sum);
return 0;
}

``````

Read 5 numbers and print the largest

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

#define N_NUMBERS 5

int main(void) {
int howManyNumbers, number, maximum;
scanf("%d", &maximum);
howManyNumbers = 1;
while (howManyNumbers < N_NUMBERS) {
scanf("%d", &number);
if (number > maximum) {
maximum = number;
}
howManyNumbers = howManyNumbers + 1;
}
printf("Largest is %d\n", maximum);
return 0;
}

``````

Read numbers until a negative number is read then print the sum of the numbers (not including the negative number)

Version 1

A simple program demonstrating stopping a while loop when a particular value is read by scanf

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

int main(void) {
int x, sum;

sum = 0;
x = 0;
printf("Enter numbers, terminate with a negative number:\n");

while (x >= 0) {
scanf("%d", &x);
if (x > 0) {
sum = sum + x;
}
}

printf("Sum of the numbers is %d\n", sum);
return 0;
}

``````

Read numbers until a negative number is read then print the sum of the numbers (not including the negative number)

Version 2

A simple program demonstrating stopping a while loop when a particular value is read by scanf

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

int main(void) {
int x, sum;

sum = 0;
printf("Enter numbers, terminate with a negative number:\n");

scanf("%d", &x);
while (x >= 0) {
sum = sum + x;
scanf("%d", &x);
}

printf("Sum of the numbers is %d\n", sum);
return 0;
}

``````

Sum the series 1 + 1/2 + 1/3 + 1/4 + ...

```    ```#include <stdio.h>

#define N_SERIES_TERMS 1000

int main(void) {
int n;
double sum;

n = 1;
sum = 0;
while (n <= N_SERIES_TERMS) {
sum = sum + 1.0 / n;
n = n + 1;
}

printf("1 + 1/2 + 1/3 + + ... + 1/%d = %f\n", N_SERIES_TERMS, sum);
return 0;
}

``````

Calculate the mathematical constant e by summing the series 1 + 1/(1*2) + 1/(1*2*3) + 1/(1*2*3*4) + ... http://en.wikipedia.org/wiki/E_%28mathematical_constant%29

```    ```#include <stdio.h>

#define N_SERIES_TERMS 20

int main(void) {
int n;
double sum, factorial;

n = 1;
sum = 0;
factorial = 1;
while (n <= N_SERIES_TERMS) {
sum = sum + 1.0 / factorial;
factorial = factorial * n;
n = n + 1;
}

printf("1/1 + 1/1 + 1/(1*2) + 1/(1*2*3) + 1/(1*2*3*4)  + ... + 1/%.0f  = %.12f\n", factorial, sum);
return 0;
}

``````

Calculate the mathematical constant pi to 6 decimal places by summing the series 4 - 4/3 + 4/5 - 4/7 + 4/9 + ...

```    ```#include <stdio.h>

#define N_SERIES_TERMS 1000000

int main(void) {
int n;
double sum;

n = 0;
sum = 0;
while (n < N_SERIES_TERMS) {
if (n % 2 == 0) {
sum = sum + 4.0 / (2 * n + 1);
} else {
sum = sum - 4.0 / (2 * n + 1);
}
n = n + 1;
}

printf("4 - 4/3 + 4/5 - 4/7 + 4/9 + ... = %f\n", sum);
return 0;
}

``````

Calculate the the series 1 + 1/2 + 1/4 + 1/8 + ... until it converges to within 10 decimal places

```    ```#include <stdio.h>

#define ACCURACY  0.000000000001

int main(void) {
double sum, term;

sum = 0;
term = 1;

while (term > ACCURACY) {
sum = sum + term;
term = term / 2.0;
}

printf("1 + 1/2 + 1/4 + 1/8 + ...  = %.10f\n", sum);
return 0;
}

``````

Read numbers printing whether they are even or odd illustrates use of a sentinel variable (stop_loop)

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

int main(void) {
int stop_loop, number;

printf("Enter numbers, 0 to stop\n");

stop_loop = 0;
while (stop_loop != 1) {
scanf("%d", &number);
if (number == 0) {
stop_loop = 1;
} else if (number % 2 == 1) {
printf("%d is odd.\n", number);
} else {
printf("%d is even.\n", number);
}
}

return 0;
}

``````

A simple program which prints a square

```    ```#include <stdio.h>

#define SIDE_LENGTH 13

int main(void) {
int row, column;
row = 0;
while (row < SIDE_LENGTH) {
column = 0;
while (column <= SIDE_LENGTH) {
printf("*");
column = column + 1;
}
printf("\n");
row = row + 1;
}
return 0;
}

``````

A simple program which prints a triangle

```    ```#include <stdio.h>

#define SIDE_LENGTH 13

int main(void) {
int row, column;
row = 0;
while (row < SIDE_LENGTH) {
column = 0;
while (column <= row) {
printf("*");
column = column + 1;
}
printf("\n");
row = row + 1;
}
return 0;
}

``````

A simple program which reads integers and and if a composite number is read exists printing the factor

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

int main(void) {
int n, possibleFactor, keepLooping;
keepLooping = 1;
while (keepLooping == 1) {
printf("Enter a number: ");
scanf("%d", &n);
possibleFactor = 2;
while (possibleFactor < n && keepLooping == 1) {
if (n % possibleFactor == 0) {
printf("%d is composite %d is a factor\n", n, possibleFactor);
keepLooping = 0;
}
possibleFactor = possibleFactor + 1;
}
}
return 0;
}

``````

A simple program demonstrating nested while loops

It prints all prime numbers < 10000

```    ```#include <stdio.h>

int main(void) {
int n, possibleFactor, nFactors;
// loop through numbers 1..1000
n = 1;
while (n < 1000) {
// loop through numbers 1..n counting factors
possibleFactor = 1;
nFactors = 0;
while (possibleFactor <= n) {
if (n % possibleFactor == 0) {
nFactors = nFactors + 1;
}
possibleFactor = possibleFactor + 1;
}
if (nFactors <= 2) {
printf("%d is prime\n", n);
}
n = n + 1;
}
return 0;
}

``````

A simple program which reads integers and prints snap and exits if the same number is read twice in a row

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

int main(void) {
int n, previousN;

printf("Enter a number: ");
scanf("%d", &previousN);

printf("Enter a number: ");
scanf("%d", &n);

while (n != previousN) {
previousN = n;
printf("Enter a number: ");
scanf("%d", &n);
}

printf("Snap!\n");
return 0;
}

``````

Read numbers until end of input (or a non-number) is reached then print the sum of the numbers

Version 1

A simple program demonstrating stopping a while loop when scanf fails to read a number e.g. because end-of-input is reached

```    ```#include <stdio.h>

int main(void) {

sum = 0;
printf("Enter numbers, indicate end-of-input with control-D:\n");

// if scanf can read an integer it will place it in x and it will return 1
// if scanf can't read an integer it will not change x and it will return 0 or -1

sum = sum + x;
}
}

printf("Sum of the numbers is %d\n", sum);
return 0;
}

``````

Read numbers until end of input (or a non-number) is reached then print the sum of the numbers

Version 1

A simple program demonstrating stopping a while loop when scanf fails to read a number e.g. because end-of-input is reached

```    ```#include <stdio.h>

int main(void) {

sum = 0;
printf("Enter numbers, indicate end-of-input with control-D:\n");

// if scanf can read an integer it will place it in x and it will return 1
// if scanf can't read an integer it will not change x and it will return 0 or -1
sum = sum + x;
}

printf("Sum of the numbers is %d\n", sum);
return 0;
}

``````

Read numbers until end of input (or a non-number) is reached then print the sum of the numbers

Version 2

A simple program demonstrating stopping a while loop when scanf fails to read a number e.g. because end-of-input is reached

```    ```#include <stdio.h>

int main(void) {
int sum, x;

sum = 0;

printf("Enter number: ");
while (scanf("%d", &x) == 1) {
sum = sum + x;
printf("Enter number: ");
}

printf("Sum of the numbers is %d\n", sum);
return 0;
}

``````

Arrays

Read 5 numbers and print them in reverse order - the hard way

This approach quickly becomes impractical if you want to read more numbers a much better approach is to use an array

```    ```#include <stdio.h>

int main(void) {
int x0, x1, x2, x3, x4;
printf("Enter 5 numbers: ");
scanf("%d", &x0);
scanf("%d", &x1);
scanf("%d", &x2);
scanf("%d", &x3);
scanf("%d", &x4);
printf("Numbers reversed are:\n");
printf("%d\n", x4);
printf("%d\n", x3);
printf("%d\n", x2);
printf("%d\n", x1);
printf("%d\n", x0);
return 0;
}

``````

Read 5 numbers and print them in reverse order

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.
The constants 4 & 5 below would be better replaced with a #define
```    ```#include <stdio.h>

int main(void) {
int x[5], i, j;
printf("Enter 5 numbers: ");
i = 0;
while (i < 5) {
scanf("%d", &x[i]);
i = i + 1;
}
printf("Numbers reversed are:\n");
j = 4;
while (j >= 0) {
printf("%d\n", x[j]);
j = j - 1;
}
return 0;
}

``````

Read 5 numbers and print them in reverse order
```    ```#include <stdio.h>

#define N_NUMBERS 5

int main(void) {
int x[N_NUMBERS], i, j;

printf("Enter %d numbers: ", N_NUMBERS);
i = 0;
while (i < N_NUMBERS) {
scanf("%d", &x[i]);
i = i + 1;
}
printf("Numbers reversed are:\n");
j = N_NUMBERS - 1;
while (j >= 0) {
printf("%d\n", x[j]);
j = j - 1;
}
return 0;
}

``````

Read 5 numbers and print them in reverse order
This version checks that the scanf was able to read the number
```    ```#include <stdio.h>

#define N_NUMBERS 5

int main(void) {
int x[N_NUMBERS], i, j, scanfFailed;

printf("Enter %d numbers: ", N_NUMBERS);
i = 0;
scanfFailed = 0;
while (i < N_NUMBERS && scanfFailed == 0) {
if (scanf("%d", &x[i]) != 1) {
scanfFailed = 1;
}
i = i + 1;
}
if (scanfFailed == 1) {
} else {
printf("Numbers reversed are:\n");
j = N_NUMBERS - 1;
while (j >= 0) {
printf("%d\n", x[j]);
j = j - 1;
}
}
return 0;
}

``````

Read n numbers and print them in reverse order

Note for simplicity we are assuming scanf succeeds in reading an integer.
A robust program would check that scanf returns 1 to indicate an integer read.

```    ```#include <stdio.h>

#define MAX_NUMBERS 1000000

int main(void) {
int x[MAX_NUMBERS], i, j, howMany;
scanf("%d", &howMany);
if (howMany > MAX_NUMBERS) {
printf("I'm sorry, Dave. I'm afraid I can't do that.\n");
howMany = MAX_NUMBERS;
}
i = 0;
while (i < howMany) {
scanf("%d", &x[i]);
i = i + 1;
}
printf("Numbers reversed are:\n");

j = howMany - 1;
while (j >= 0) {
printf("%d\n", x[j]);
j = j - 1;
}
return 0;
}

``````

A simple program which reads integers and prints snap and exits if the same number is read twice

This version uses a sentinel variable (stopNow)
The use of a sentinel variable is very useful programming pattern which can be used in many situations

But see variant_snap1.c for a simpler solution using return

```    ```#include <stdio.h>

#define MAX_NUMBERS 100000

int main(void) {
int numbers[MAX_NUMBERS];

stopNow = 0;
while (stopNow == 0) {
printf("Enter a number: ");
if (scanf("%d", &numbers[nNumbersRead]) != 1) {
stopNow = 1;
} else {
i = 0;
printf("Snap!\n");
stopNow = 1;
}
i = i + 1;
}
printf("Sorry my array is full I have to stop!\n");
stopNow = 1;
}
}
}
return 0;
}

``````

A simple program which reads integers and prints snap and exits if the same number is read twice

Note the use of return to leave the main function and hence finish program execution

```    ```#include <stdio.h>

#define MAX_NUMBERS 100000

int main(void) {
int numbers[MAX_NUMBERS];

printf("Enter a number: ");
if (scanf("%d", &numbers[nNumbersRead]) != 1) {
return 0;
}
i = 0;
printf("Snap!\n");
return 0;
}
i = i + 1;
}
}
printf("Sorry my array is full I have to stop!\n");
return 0;
}

``````

Read annual rainfall and plot as bar graph
This version always reads N_YEARS of rainfall
```
Sample execution:

% dcc plot_rainfall0.c
% a.out
Enter 10 years of rainfall totals
Enter year: 2005
Enter rainfall(mm): 816
Enter year: 2006
Enter rainfall(mm): 994.0
Enter year: 2007
Enter rainfall(mm): 1499.2
Enter year: 2008
Enter rainfall(mm): 1082.6
Enter year: 2009
Enter rainfall(mm): 956.2
Enter year: 2010
Enter rainfall(mm): 1153.8
Enter year: 2011
Enter rainfall(mm): 1369.2
Enter year: 2012
Enter rainfall(mm): 1213.6
Enter year: 2013
Enter rainfall(mm): 1344.4
Enter year: 2014
Enter rainfall(mm): 893.8

1 asterisk == 100 mm of rainfall
2005 ********
2006 *********
2007 **************
2008 **********
2009 *********
2010 ***********
2011 *************
2012 ************
2013 *************
2014 ********

```

```    ```#include <stdio.h>

#define N_YEARS  10
#define SCALE    100

int main(void) {
int    whichYear[N_YEARS];
double rainfall[N_YEARS];
int    year, asterisk, nAsterisks;

printf("Enter %d years of rainfall totals\n", N_YEARS);

year = 0;
while (year < N_YEARS) {
printf("Enter year: ");
scanf("%d", &whichYear[year]);
printf("Enter rainfall(mm): ");
scanf("%lf", &rainfall[year]);
year = year + 1;
}

printf("\n1 asterisk == %d mm of rainfall\n", SCALE);

year = 0;
while (year < N_YEARS) {
printf("%4d ", whichYear[year]);
nAsterisks = rainfall[year] / SCALE;
asterisk = 0;
while (asterisk < nAsterisks) {
printf("*");
asterisk = asterisk + 1;
}
printf("\n");
year = year + 1;
}

return 0;
}

``````

Read annual rainfall and plot as bar graph
This version asks the user how many years of rainfall they wish to plot
```
Sample execution:

% dcc plot_rainfall1.c
% a.out
How many years of rainfall do you want to graph: 10
Enter year: 2005
Enter rainfall(mm): 816
Enter year: 2006
Enter rainfall(mm): 994.0
Enter year: 2007
Enter rainfall(mm): 1499.2
Enter year: 2008
Enter rainfall(mm): 1082.6
Enter year: 2009
Enter rainfall(mm): 956.2
Enter year: 2010
Enter rainfall(mm): 1153.8
Enter year: 2011
Enter rainfall(mm): 1369.2
Enter year: 2012
Enter rainfall(mm): 1213.6
Enter year: 2013
Enter rainfall(mm): 1344.4
Enter year: 2014
Enter rainfall(mm): 893.8

1 asterisk == 100 mm of rainfall
2005 ********
2006 *********
2007 **************
2008 **********
2009 *********
2010 ***********
2011 *************
2012 ************
2013 *************
2014 ********

```

```    ```#include <stdio.h>

#define MAXIMUM_YEARS 20000
#define SCALE    100

int main(void) {
int    whichYear[MAXIMUM_YEARS];
double rainfall[MAXIMUM_YEARS];
int    year, asterisk, nAsterisks, nYears;

printf("How many years of rainfall do you want to graph: ");
scanf("%d", &nYears);
if (nYears > MAXIMUM_YEARS) {
printf("Limiting years read to  maximum possible: %d\n", MAXIMUM_YEARS);
nYears = MAXIMUM_YEARS;
}

year = 0;
while (year < nYears) {
printf("Enter year: ");
scanf("%d", &whichYear[year]);
printf("Enter rainfall(mm): ");
scanf("%lf", &rainfall[year]);
year = year + 1;
}

printf("\n1 asterisk == %d mm of rainfall\n", SCALE);

year = 0;
while (year < nYears) {
printf("%4d ", whichYear[year]);
nAsterisks = rainfall[year] / SCALE;
asterisk = 0;
while (asterisk < nAsterisks) {
printf("*");
asterisk = asterisk + 1;
}
printf("\n");
year = year + 1;
}

return 0;
}

``````

Read annual rainfall and plot as bar graph
This version reads years & their rainfall until the users enters 0 for a year
```
Sample execution:

% dcc plot_rainfall2.c
% a.out
Enter year[0 to stop]: 2005
Enter rainfall(mm): 816
Enter year[0 to stop]: 2006
Enter rainfall(mm): 994.0
Enter year[0 to stop]: 2007
Enter rainfall(mm): 1499.2
Enter year[0 to stop]: 2008
Enter rainfall(mm): 1082.6
Enter year[0 to stop]: 2009
Enter rainfall(mm): 956.2
Enter year[0 to stop]: 2010
Enter rainfall(mm): 1153.8
Enter year[0 to stop]: 2011
Enter rainfall(mm): 1369.2
Enter year[0 to stop]: 2012
Enter rainfall(mm): 1213.6
Enter year[0 to stop]: 2013
Enter rainfall(mm): 1344.4
Enter year[0 to stop]: 2014
Enter rainfall(mm): 893.8
Enter year: 0

1 asterisk == 100 mm of rainfall
2005 ********
2006 *********
2007 **************
2008 **********
2009 *********
2010 ***********
2011 *************
2012 ************
2013 *************
2014 ********

```

```    ```#include <stdio.h>

#define MAXIMUM_YEARS 20000
#define SCALE    100

int main(void) {
int    whichYear[MAXIMUM_YEARS];
double rainfall[MAXIMUM_YEARS];
int    year, asterisk, nAsterisks, nYears;

year = 0;
nYears = MAXIMUM_YEARS;
while (year < MAXIMUM_YEARS) {
printf("Enter year[0 to stop]: ");
scanf("%d", &whichYear[year]);
if (whichYear[year] == 0) {
nYears = year;
year = MAXIMUM_YEARS;
} else {
printf("Enter rainfall(mm): ");
scanf("%lf", &rainfall[year]);
year = year + 1;
}
}

printf("\n1 asterisk == %d mm of rainfall\n", SCALE);

year = 0;
while (year < nYears) {
printf("%4d ", whichYear[year]);
nAsterisks = rainfall[year] / SCALE;
asterisk = 0;
while (asterisk < nAsterisks) {
printf("*");
asterisk = asterisk + 1;
}
printf("\n");
year = year + 1;
}

return 0;
}

``````

Read annual rainfall and plot as bar graph
This version reads years & their rainfall until end-of-file
```
Sample execution:

% dcc plot_rainfall3.c
% a.out
Enter year: 2005
Enter rainfall(mm): 816
Enter year: 2006
Enter rainfall(mm): 994.0
Enter year: 2007
Enter rainfall(mm): 1499.2
Enter year: 2008
Enter rainfall(mm): 1082.6
Enter year: 2009
Enter rainfall(mm): 956.2
Enter year: 2010
Enter rainfall(mm): 1153.8
Enter year: 2011
Enter rainfall(mm): 1369.2
Enter year: 2012
Enter rainfall(mm): 1213.6
Enter year: 2013
Enter rainfall(mm): 1344.4
Enter year: 2014
Enter rainfall(mm): 893.8
<control-D>

1 asterisk == 100 mm of rainfall
2005 ********
2006 *********
2007 **************
2008 **********
2009 *********
2010 ***********
2011 *************
2012 ************
2013 *************
2014 ********

```

```    ```#include <stdio.h>

#define MAXIMUM_YEARS 20000
#define SCALE    100

int main(void) {
int    whichYear[MAXIMUM_YEARS];
double rainfall[MAXIMUM_YEARS];
int    year, asterisk, nAsterisks, nYears;

year = 0;
nYears = MAXIMUM_YEARS;
while (year < MAXIMUM_YEARS) {
printf("Enter year: ");
if (scanf("%d", &whichYear[year]) == 0) {
nYears = year;
year = MAXIMUM_YEARS;
} else {
printf("Enter rainfall(mm): ");
scanf("%lf", &rainfall[year]);
year = year + 1;
}
}

printf("\n1 asterisk == %d mm of rainfall\n", SCALE);

year = 0;
while (year < nYears) {
printf("%4d ", whichYear[year]);
nAsterisks = rainfall[year] / SCALE;
asterisk = 0;
while (asterisk < nAsterisks) {
printf("*");
asterisk = asterisk + 1;
}
printf("\n");
year = year + 1;
}

return 0;
}

``````

Read annual rainfall and plot as bar graph
This version reads years & their rainfall until end-of-file and puts -1 in the array as a a marker
```
Sample execution:

% dcc plot_rainfall4.c
% a.out
Enter year: 2005
Enter rainfall(mm): 816
Enter year: 2006
Enter rainfall(mm): 994.0
Enter year: 2007
Enter rainfall(mm): 1499.2
Enter year: 2008
Enter rainfall(mm): 1082.6
Enter year: 2009
Enter rainfall(mm): 956.2
Enter year: 2010
Enter rainfall(mm): 1153.8
Enter year: 2011
Enter rainfall(mm): 1369.2
Enter year: 2012
Enter rainfall(mm): 1213.6
Enter year: 2013
Enter rainfall(mm): 1344.4
Enter year: 2014
Enter rainfall(mm): 893.8
<control-D>

1 asterisk == 100 mm of rainfall
2005 ********
2006 *********
2007 **************
2008 **********
2009 *********
2010 ***********
2011 *************
2012 ************
2013 *************
2014 ********

```

```    ```#include <stdio.h>

#define MAXIMUM_YEARS 20000
#define SCALE    100

int main(void) {
int    whichYear[MAXIMUM_YEARS];
double rainfall[MAXIMUM_YEARS];
int    year, asterisk, nAsterisks;

year = 0;
while (year < MAXIMUM_YEARS) {
printf("Enter year: ");
if (scanf("%d", &whichYear[year]) == 0) {
whichYear[year] = -1;
year = MAXIMUM_YEARS;
} else {
printf("Enter rainfall(mm): ");
scanf("%lf", &rainfall[year]);
year = year + 1;
}
}
whichYear[MAXIMUM_YEARS - 1] = -1;

printf("\n1 asterisk == %d mm of rainfall\n", SCALE);

year = 0;
while (whichYear[year] >= 0) {
printf("%4d ", whichYear[year]);
nAsterisks = rainfall[year] / SCALE;
asterisk = 0;
while (asterisk < nAsterisks) {
printf("*");
asterisk = asterisk + 1;
}
printf("\n");
year = year + 1;
}

return 0;
}

``````

Read SIZE x SIZE numbers and test if they form a magic square http://en.wikipedia.org/wiki/Magic_square
and exits if the same number is read twice

```Lo Shu Square
4  9  2
3  5  7
8  1  6
Magic square of primes
17  89  71
113  59   5
47  29 101
```

```    ```#include <stdio.h>

#define SIZE 3

int main(void) {
int x[SIZE][SIZE];
int row, column;
int magicConstant, sum;
int notMagicSquare;

row = 0;
while (row < SIZE) {
column = 0;
while (column < SIZE) {
if (scanf("%d", &x[row][column]) != 1) {
return 0;
}
column = column + 1;
}
row = row + 1;
}
printf("Numbers are:\n");
// print potential magic square
row = 0;
while (row < SIZE) {
column = 0;
while (column < SIZE) {
printf("%d ", x[row][column]);
column = column + 1;
}
printf("\n");
row = row + 1;
}

// sum first row
magicConstant = 0;
row = 0;
while (row < SIZE) {
magicConstant = magicConstant + x[0][row];
row = row + 1;
}

// check if sum of each row matches sum of first row
notMagicSquare = 0;
row = 1;
while (row < SIZE) {
sum = 0;
column = 0;
while (column < SIZE) {
sum = sum + x[row][column];
column = column + 1;
}
if (sum != magicConstant) {
notMagicSquare = 1;
}
row = row + 1;
}

// check if sum of each column matches sum of first row
column = 0;
while (column < SIZE) {
sum = 0;
row = 0;
while (row < SIZE) {
sum = sum + x[row][column];
row = row + 1;
}
if (sum != magicConstant) {
notMagicSquare = 1;
}
column = column + 1;
}

// summing diagonals left as an exercise

if (notMagicSquare == 0) {
printf("Is a magic square\n");
} else {
printf("Not a magic square\n");
}
return 0;
}

``````

Characters And Strings

Print "Andrew Rocks!" - using ASCII codes for the characters

Compare the 8 andrew_rocks?.c programs which are all equivalent to get a better understanding of how & why C encodes character sequences

```    ```#include <stdio.h>

int main(void) {
putchar(65);     // printf("%c", 65) is equivalent
putchar(110);
putchar(100);
putchar(114);
putchar(101);
putchar(119);
putchar(32);
putchar(82);
putchar(111);
putchar(99);
putchar(107);
putchar(115);
putchar(33);
putchar(10);
return 0;
}
``````

Print "Andrew Rocks!" - using character constants to get the ASCII codes for the characters
'A' is the C shorthand for the ASCII code for the character A (65)

```    ```#include <stdio.h>

int main(void) {
putchar('A');   // equivalent to putchar(65)
putchar('n');
putchar('d');
putchar('r');
putchar('e');
putchar('w');
putchar(' ');
putchar('R');
putchar('o');
putchar('c');
putchar('k');
putchar('s');
putchar('\n');
return 0;
}
``````

Print "Andrew Rocks!" - using character constants to get the ASCII codes for the characters, store them in array, and print the array. Note we have to track the array length.

```    ```#include <stdio.h>

#define LENGTH 14

int main(void) {
int asciiCodes[14];

asciiCodes[0] = 'A';
asciiCodes[1] = 'n';
asciiCodes[2] = 'd';
asciiCodes[3] = 'r';
asciiCodes[4] = 'e';
asciiCodes[5] = 'w';
asciiCodes[6] = ' ';
asciiCodes[7] = 'R';
asciiCodes[8] = 'o';
asciiCodes[9] = 'c';
asciiCodes[10] = 'k';
asciiCodes[11] = 's';
asciiCodes[12] = '!';
asciiCodes[13] = '\n';

int i = 0;
while (i < LENGTH) {
putchar(asciiCodes[i]);
i = i + 1;
}

return 0;
}
``````

Print "Andrew Rocks!" - using character constants to get the ASCII codes for the characters, initialize an array to the values , and print the array.
Note we have to track the array length.

```    ```#include <stdio.h>

#define LENGTH 14

int main(void) {
int asciiCodes[LENGTH] = {'A','n','d','r','e','w',' ','R','o','c','k','s','!','\n'};

int i = 0;
while (i < LENGTH) {
putchar(asciiCodes[i]);
i = i + 1;
}

return 0;
}
``````

Print "Andrew Rocks!" - using character constants to get the ASCII codes for the characters, and initialize the array to the vales array using , and print the array.

This version has a extra special value in the array (0) to indicate the end of the sequence. This means we no longer have to keep track of how many characters in the array (note the while loop condition)

```    ```#include <stdio.h>

int main(void) {
// if we don't specify the size of an array being initialized C will make
// it big enough to hold all the initializing elements (15 in this case)
int asciiCodes[] = {'A','n','d','r','e','w',' ','R','o','c','k','s','!','\n',0};

int i = 0;
while (asciiCodes[i] != 0) {
putchar(asciiCodes[i]);
i = i + 1;
}

return 0;
}
``````

Print "Andrew Rocks!" - using character constants to get the ASCII codes for the characters, and initialize the array to the vales array using , and print the array.

This version has switched to using the numeric type char. This type is almost always 8 bits and shouldn't be used for arithmetic. It is commonly used to hold ASCII encodings.

```    ```#include <stdio.h>

int main(void) {
// if we don't specify the size of an array being initialized C will make
// it big enough to hold all the initializing elements (15 in this case)
char asciiCodes[] = {'A','n','d','r','e','w',' ','R','o','c','k','s','!','\n',0};

int i = 0;
while (asciiCodes[i] != 0) {
putchar(asciiCodes[i]);
i = i + 1;
}

return 0;
}
``````

Print "Andrew Rocks!" - using character constants to get the ASCII codes for the characters, and initialize the array to the vales array using , and print the array.

C has a convenient shorthand for char arrays containing a sequence of
ASCII codes with an extra 0 value marking the end of the sequence.
Its "Andrew Rocks!";

Compare the 8 andrew_rocks?.c programs which are all equivalent to get a better understand of how & why C encodes character sequences

```    ```#include <stdio.h>

int main(void) {
char asciiCodes[] = "Andrew Rocks!\n";
int i;

i = 0;
while (asciiCodes[i] != 0) {
putchar(asciiCodes[i]);
i = i + 1;
}

return 0;
}
``````

Print "Andrew Rocks!" - using character constants to get the ASCII codes for the characters, and initialize the array to the vales array using , and print the array.

C has a convenient shorthand for char arrays containing a sequence of
ASCII codes with an extra 0 value marking the end of the sequence.
Its "Andrew Rocks!";

A number of C library functions accept zero-terminated char arrays
For example printf with the "%s" specification (below)

```    ```#include <stdio.h>

int main(void) {
char asciiCodes[] = "Andrew Rocks!\n";
printf("%s", asciiCodes);
return 0;
}
``````

Print the 128 ASCII character encodings

```    ```#include <stdio.h>

int main(void) {
int ascii;
ascii = 0;
while (ascii < 128) {
printf("In ASCII %d prints as %c\n", ascii, ascii);
ascii = ascii + 1;
}
return 0;
}

``````

```    ```#include <stdio.h>

int main(void) {
// getchar returns an int which will contain either
// the ASCII code of the character read or EOF

int ch = getchar();
while (ch != EOF) {
printf("you entered the character: '%c' which has ASCII code %d\n", ch, ch);
ch = getchar();
}
return 0;
}

``````

Read characters until eof, printing them with lower case letters convert to upper case

```    ```#include <stdio.h>

int make_upper_case(int character);

int main(void) {
// getchar returns an int which will contain either
// the ASCII code of the character read or EOF

int character = getchar();
while (character != EOF) {

int new_character = make_upper_case(character);
putchar(new_character);

character = getchar();
}
return 0;
}

// return upper case letter corresponding to lower case letter
// e.g. given 'f' return 'F'
// other characters returned unchanged
//
// library function toupper() in <ctype.h> does this task

int make_upper_case(int character) {
if (character >= 'a' && character <= 'z') {
int alphabetPosition = character - 'a';
return 'A' + alphabetPosition;
} else {
return character;
}
}

``````

convert a single character to an int
```    ```#include <stdio.h>

#define MAX_LINE 4096

int main(int argc, char *argv[]) {
char line[MAX_LINE];
int i;

printf("Enter a single digit number: ");
fgets(line, MAX_LINE, stdin);
if (line[0] >= '0' && line[0] <= '9') {
i = line[0] - '0';
printf("You entered %d\n", i);
}
return 0;
}

``````

convert a string read from stdin using getchar to an int

```    ```#include <stdio.h>

int main(void) {

printf("Enter a number: ");
int c = getchar();

int n = 0;
while (c >= '0' && c <= '9') {
n = 10 * n + (c - '0');
c = getchar();
}
printf("You entered %d\n", n);

return 0;
}

``````

print last argument
```    ```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
if (argc == 1) {
printf("I have no arguments\n");
} else {
printf("my last argument is %s\n", argv[argc - 1]);
}
return 0;
}

``````

print command line argument
```    ```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
int i;
printf("argc=%d\n", argc);
i = 0;
while (i < argc) {
printf("argv[%d]=%s\n", i, argv[i]);
i = i + 1;
}
return 0;
}

``````

Convert command-line arguments to integers and print their sum.

No check is made that the command-line arguments are actually integers.
See strol for a more powerful library function which would allow checking.

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

int main(int argc, char *argv[]) {

int sum = 0;
int argument = 1;
while (argument < argc) {
sum = sum + atoi(argv[argument]);
argument= argument + 1;
}
printf("sum of command-line arguments = %d\n", sum);

return 0;
}

``````

Simple example reading a line of input and examining characters
```    ```#include <stdio.h>

#define SIZE 8000

int main(void) {
char x[SIZE];

printf("Enter some input: ");
if (fgets(x, SIZE, stdin) == NULL) {
return 0;
}

// the built-in function strlen could be used here
int nCharacters = 0;
while (x[nCharacters] != '\n' && x[nCharacters] != '\0') {
nCharacters = nCharacters + 1;
}

// if we don't find a newline - the whole line can't have been read
if (x[nCharacters] != '\n') {
return 0;
}

printf("That line contained %d characters\n", nCharacters);

if (nCharacters > 0) {
printf("The first character was %c\n", x[0]);
printf("The last character was %c\n", x[nCharacters-1]);
}
return 0;
}

``````

```    ```#include <stdio.h>

#define MAX_LINE 1024

int main(void) {
char line[MAX_LINE];

// fgets returns NULL if it can't read any characters
while (fgets(line, MAX_LINE, stdin) != NULL) {
printf("you entered the line: %s", line);
}
return 0;
}

``````

convert a string read from stdin to an int using the atoi function from the standard C library note no error checking

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

#define MAX_LINE 4096

int main(int argc, char *argv[]) {
char line[MAX_LINE] = {0};
int n;

printf("Enter a number: ");
fgets(line, MAX_LINE, stdin);
n = atoi(line);
printf("You entered %d\n", n);

return 0;
}

``````

convert a string read from stdin using fgets to an int

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

#define MAX_LINE 4096

int main(void) {
char line[MAX_LINE] = {0};

printf("Enter a number: ");
fgets(line, MAX_LINE, stdin);
int n = 0;
int i = 0;
while (line[i] > '0' && line[i] < '9') {
n = 10 * n + (line[i] - '0');
i = i + 1;
}
printf("You entered %d\n", n);
return 0;
}

``````

Read numbers until eof or non-number encountered
```    ```#include <stdio.h>

int main(void) {
int num;
// scanf returns the number of items read
while (scanf("%d", &num) == 1) {
printf("you entered the number: %d\n", num);
}
return 0;
}

``````

```    ```#include <stdio.h>

int main(void) {
// getchar returns an int which will contain either
// the ASCII code of the character read or EOF

// using an assignment in a loop/if condition is
// not recommended for novice programmers
// but is used widely by experienced C programmers

int ch;
while ((ch = getchar()) != EOF) {
printf("you entered the character: '%c' which has ASCII code %d\n", ch, ch);
}
return 0;
}

``````

Reads lines of input until end-of-input
Print snap! if two consecutive lines are identical

See snap_line1.c for how to use functions to produce simpler code

```    ```#include <stdio.h>

#define MAX_LINE 4096

int main(int argc, char *argv[]) {
char line[MAX_LINE];
char lastLine[MAX_LINE];

// read first line into array lastLine
printf("Enter line: ");
fgets(lastLine, MAX_LINE, stdin);

printf("Enter line: ");
while (fgets(line, MAX_LINE, stdin) != NULL) {
int i = 0;

// count how many characters differ
// between line & lastLine

int differences = 0;
while (line[i] != '\0' && lastLine[i] != 0) {
if (lastLine[i] != line[i]) {
differences = differences + 1;
}
i = i + 1;
}

if (differences == 0) {
// lines are identical
printf("Snap!\n");
}

// arrays can't be assigned so copy elements
// of lastLine to line using a loop
int j = 0;
while (line[j] != '\0') {
lastLine[j] = line[j];
j = j + 1;
}
lastLine[j] = '\0';

printf("Enter line: ");
}

return 0;
}

``````

Reads lines of input until end-of-input
Print snap! if two consecutive lines are identical

See snap_line2.c to see how to replace compareArrays & copyArray calls to with (strcmp & strcpy) from <string.h>

```    ```#include <stdio.h>

#define MAX_LINE 4096

int compareArrays(char array1[], char array2[]);
void copyArray(char destinationArray[], char sourceArray[]);

int main(int argc, char *argv[]) {
char line[MAX_LINE];
char lastLine[MAX_LINE];

// read first line into array lastLine
printf("Enter line: ");
fgets(lastLine, MAX_LINE, stdin);

printf("Enter line: ");
while (fgets(line, MAX_LINE, stdin) != NULL) {

if (compareArrays(line, lastLine) == 0) {
// lines are identical
printf("Snap!\n");
}

copyArray(lastLine, line);

printf("Enter line: ");
}

return 0;
}

// return 1 if array1 & array2 differ in any element, 0 otherwise
// array1 & array2 must be null-terminated char arrays
// strcmp from  <string.h> performs similar function

int compareArrays(char array1[], char array2[]) {
int i = 0;
while (array1[i] != '\0') {
if (array1[i] != array2[i]) {
return 1;
}
i = i + 1;
}
if (array2[i] == '\0') {
return 0;
} else {
return 1;
}
}

// copy elements in sourceArray to destinationArray
// sourceArray must be a null-terminated char array
// destinationArray must be large enough to hold string
// strcpy from  <string.h> performs the same function

void copyArray(char destinationArray[], char sourceArray[]) {
int i = 0;
while (sourceArray[i] != '\0') {
destinationArray[i] = sourceArray[i];
i = i + 1;
}
destinationArray[i] = '\0';
}

``````

Simple example of file creation creates file "andrew.txt" containing 1 line ("Andrew rules!")
```    ```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
FILE *outputStream;

outputStream = fopen("andrew.txt", "a");
if (outputStream == NULL) {
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], "andrew.txt");
return 1;
}

fprintf(outputStream, "Andrew rules!\n");
fclose(outputStream);

return 0;
}

``````

Simple example of file creation appends to file "andrew.txt" the line "Andrew rules!"
```    ```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
FILE *outputStream;

outputStream = fopen("andrew.txt", "a");
if (outputStream == NULL) {
perror("andrew.txt"); // prints why the open failed
return 1;
}

fprintf(outputStream, "Andrew rules!\n");
fclose(outputStream);

return 0;
}

``````

Simple implementation of reading files passed as command line arguments using fgetc - in other words cat
```    ```#include <stdio.h>

int main(int argc, char *argv[]) {

// go through a list of files specified on the command line
// printing their contents in turn to standard output

int argument = 1;
while (argument < argc) {

// FILE is an opaque (hidden type) defined in stdio.h
// "r" indicate we are opening file to read contents

FILE *stream = fopen(argv[argument], "r");
if (stream == NULL) {
perror(argv[argument]);  // prints why the open failed
return 1;
}

// fgetc returns next the next byte (ascii code if its a text file)
// from a stream
// it returns the special value EOF if not more bytes can be read from the stream

int c = fgetc(stream);

// return  bytes from the stream (file) one at a time

while (c != EOF) {
fputc(c, stdout); // write the byte to standard output
c = fgetc(stream);
}

argument = argument + 1;
}
return 0;
}

``````

Simple implementation of reading files passed as command line arguments using fgets - in other words cat
```    ```#include <stdio.h>
#define MAX_LINE 1024

int main(int argc, char *argv[]) {
int argument = 1;
while (argument < argc) {

FILE *stream = fopen(argv[argument], "r");
if (stream == NULL) {
perror(argv[argument]);  // prints why the open failed
return 1;
}

char line[MAX_LINE];
while (fgets(line, MAX_LINE, stream) != NULL) {
printf("%s", line);
}

argument = argument + 1;
}
return 0;
}

``````

Simple example of cp command copy contents of file specified as first argument to file specified as 2nd argument 8/5//18
```    ```#include <stdio.h>

int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <source file> <destination file>\n", argv[0]);
return 1;
}

FILE *inputStream = fopen(argv[1], "r");
if (inputStream == NULL) {
perror(argv[1]);  // prints why the open failed
return 1;
}

FILE *outputStream = fopen(argv[2], "w");
if (outputStream == NULL) {
// perror could be used for a better error message here
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], argv[2]);
return 1;
}

int c = fgetc(inputStream);
while (c != EOF) {
fputc(c, outputStream);
c = fgetc(inputStream);
}
fclose(outputStream);

return 0;
}

``````

Simple implementation of Unix wc command
It counts lines, word & characters in the file specified as an argument

See later version for more sophisticated argument handling

```    ```#include <stdio.h>
#include <ctype.h>

#define MAX_LINE 4096

void process_stream(FILE *stream, char stream_name[]);

int main(int argc, char *argv[]) {

if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}

FILE *in = fopen(argv[1], "r");
if (in == NULL) {
// perror could be used for a better error message here
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], argv[1]);
return 1;
}

process_stream(in, argv[1]);

return 0;
}

void process_stream(FILE *stream, char stream_name[]) {
int line_count = 0;
int character_count = 0;
int word_count = 0;

int lastc = ' ';
int c = fgetc(stream);

while (c != EOF) {
if (c == '\n') {
line_count = line_count + 1;
}
if (isspace(c) && !isspace(lastc)) {
word_count = word_count + 1;
}
character_count = character_count + 1;
lastc = c;
c = fgetc(stream);
}

if (!isspace(lastc)) {
word_count = word_count + 1;
}

printf("%s contains %d lines %d words %d characters\n", stream_name, line_count, word_count, character_count);
}

``````

/ Simple implementation of Unix wc command
It counts lines, word & characters from the files specified as arguments

If no files are specified instead stdin is processed
This allows use in a pipeline, e.g.: % dcc grep.c -o grep % dcc wc_fgetc1.c -o wc % ./grep return grep.c grep.c:30: return 1; grep.c:38: return 1; grep.c:44: return 0; % ./grep return grep.c | ./wc <stdin> contains 3 lines 9 words 85 characters

```    ```#include <stdio.h>
#include <ctype.h>

#define MAX_LINE 4096

void process_stream(FILE *stream, char stream_name[]);

int main(int argc, char *argv[]) {

if (argc == 1) {
// if no files are specified, process stdin
process_stream(stdin, "<stdin>");
} else {
int argument = 1;
while (argument < argc) {
FILE *in = fopen(argv[argument], "r");
if (in == NULL) {
// perror could be used for a better error message here
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], argv[argument]);
return 1;
}

process_stream(in, argv[argument]);

argument = argument + 1;
}
}

return 0;
}

void process_stream(FILE *stream, char stream_name[]) {
int line_count = 0;
int character_count = 0;
int word_count = 0;

int lastc = ' ';
int c = fgetc(stream);

while (c != EOF) {
if (c == '\n') {
line_count = line_count + 1;
}
if (isspace(c) && !isspace(lastc)) {
word_count = word_count + 1;
}
character_count = character_count + 1;
lastc = c;
c = fgetc(stream);
}

if (!isspace(lastc)) {
word_count = word_count + 1;
}

printf("%s contains %d lines %d words %d characters\n", stream_name, line_count, word_count, character_count);
}

``````

Simple implementation of Unix wc command
It counts lines, word & characters in the file specified as an argument

This version uses fgets
```    ```#include <stdio.h>
#include <ctype.h>

#define MAX_LINE 4096

void process_stream(FILE *stream, char stream_name[]);

int main(int argc, char *argv[]) {
FILE *in;

if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}

in = fopen(argv[1], "r");
if (in == NULL) {
// perror could be used for a better error message here
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], argv[1]);
return 1;
}
process_stream(in, argv[1]);

return 0;
}

void process_stream(FILE *stream, char stream_name[]) {
char line[MAX_LINE];

int line_count = 0;
int character_count = 0;
int word_count = 0;

while (fgets(line, MAX_LINE, stream) != NULL) {
int i = 0;
while (line[i] != '\0') {
if (i > 0 && isspace(line[i]) && !isspace(line[i - 1])) {
word_count = word_count + 1;
}
character_count = character_count + 1;
i = i + 1;
}

// this if handles case of line being longer than MAX_LINE
if (!isspace(line[i - 1])) {
word_count = word_count + 1;
}  else if (line[i - 1] == '\n') {
line_count = line_count + 1;
}
}

printf("%s contains %d lines %d words %d characters\n", stream_name, line_count, word_count, character_count);
}

``````

Print lines containing specified pattern from the files specified as arguments
This version provides the unix filter behaviour where if no files are specified it process stdin

Note this code will produce incorrect results if matched lines contain >= MAX_LINE characters. Fixing this left as an exercise

```    ```#include <stdio.h>
#include <string.h>

#define MAX_LINE 65536

void search_stream(FILE *stream, char stream_name[], char search_for[]);

int main(int argc, char *argv[]) {

if (argc < 2) {
fprintf(stderr, "Usage: %s <prefix> <files>\n", argv[0]);
return 1;
} if (argc == 2) {
search_stream(stdin, "<stdin>", argv[1]);
} else {

int argument = 2;
while (argument < argc) {
FILE *in = fopen(argv[argument], "r");
if (in == NULL) {
// perror could be used for a better error message here
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], argv[argument]);
return 1;
}

search_stream(in, argv[argument], argv[1]);
argument = argument + 1;
}

}

return 0;
}

void search_stream(FILE *stream, char stream_name[], char search_for[]) {
char line[MAX_LINE];

int line_number = 1;
while (fgets(line, MAX_LINE, stream) != NULL) {
if (strstr(line, search_for) != NULL) {
printf("%s:%d:%s", stream_name, line_number, line);
}
line_number = line_number + 1;
}
}

``````

Print lines starting with specified string from specified files

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

#define MAX_LINE 1024

int is_prefix(char prefix[], char str[]);

int main(int argc, char *argv[]) {

if (argc < 2) {
fprintf(stderr, "Usage: %s <prefix> <files>\n", argv[0]);
exit(1);
}

char *searchString = argv[1];
int argument = 2;
while (argument < argc) {

FILE *stream = fopen(argv[argument], "r");
if (stream == NULL) {
// perror could be used for a better error message here
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], argv[argument]);
return 1;
}

char line[MAX_LINE];
while (fgets(line, MAX_LINE, stream) != NULL) {
if (is_prefix(searchString, line)) {
printf("%s", line);
}
}

fclose(stream);
argument = argument + 1;
}
return 0;
}

// test if str starts with prefix
int is_prefix(char prefix[], char str[]) {
int length = strlen(prefix);
return strncmp(prefix, str, length) == 0;
}

``````

print lines form file after replacing specified pattern after replacing specified pattern
```    ```#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE 1024
#define MAX_REPLACEMENT_LINE 32768

void replace(char string[], char target[], char replacement[], char new_string[], int new_string_len);

int main(int argc, char *argv[]) {
char line[MAX_LINE];
char changed_line[MAX_REPLACEMENT_LINE];

if (argc < 3) {
fprintf(stderr, "Usage: %s <target> <replacement> <files>\n", argv[0]);
exit(1);
}

char *target_string = argv[1];
char *replacement_string = argv[2];

int argument = 0;
while (argument < argc) {
FILE *stream = fopen(argv[argument], "r");
if (stream == NULL) {
// perror could be used for a better error message here
fprintf(stderr, "%s: open of '%s' failed\n", argv[0], argv[argument]);
return 1;
}

while (fgets(line, MAX_LINE, stream) != NULL) {
replace(line, target_string, replacement_string, changed_line, MAX_REPLACEMENT_LINE);
printf("%s", changed_line);
}

argument = argument + 1;
}

return 0;
}

// copy string to new_string replacing all instances of target with replacement

void replace(char string[], char target[], char replacement[], char new_string[], int new_string_len) {
int target_length = strlen(target);
int replacement_length = strlen(replacement);

int i = 0;
int j = 0;
while (string[i] != '\0' && j < new_string_len - 1) {

// if we have found the target string

if (strncmp(target, &string[i], target_length) == 0) {

// instead copy the replacement string to the new array

strncpy(&new_string[j], replacement, replacement_length);
i = i + target_length;
j = j + replacement_length;
} else {
new_string[j] = string[i];
i = i + 1;
j = j + 1;
}
}

new_string[j] = '\0';
}

``````

Pointers
```    ```#include <stdio.h>

int main(void) {
int x;

return 0;
}
``````

Simple example illustrating use of pointers to return values from a function
```    ```#include <stdio.h>

void powers(double x, double *square, double *cube) {
*square = x * x;
*cube = x * x * x;
}

int main(void) {
double s, c;

powers(42, &s, &c);

printf("42^2 = %lf\n", s);
printf("42^3 = %lf\n", c);
return 0;
}

``````

Simple example of using pointer to pass reference to variables
```    ```#include <stdio.h>

void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}

int main(int argc, char *argv[]) {
int x = 42;
int y = 13;

printf("x=%d y=%d\n", x, y);

swap(&x, &y);

printf("x=%d y=%d\n", x, y);

return 0;
}

``````

Simple example illustrating use of pointers with array elements
```    ```#include <stdio.h>

int main(void) {
int nums[7] = {5,6,7,8,9,10,11};

int *n = &nums[3];
printf("n[0]=%d n[1]=%d n[2]=%d \n", n[0], n[1], n[2]);

char string[12] = "Hello World";
char *s = &string[6];
printf("string = %s\n", string);
printf("s = %s\n", s);
printf("&string[9] = %s\n", &string[9]);

s = &string[2];
s[2] = '\0';     // equivalent to string[4] = '\0'
printf("string = %s\n", string);
printf("s = %s\n", s);

return 0;
}

``````

Simple example illustrating use of pointers with array elements
```    ```#include <stdio.h>

void print_array(int array[], int array_length);

int main(void) {
int nums[10] = {5,6,7,8,9,10,11,12,13,14};

printf("Entire array: ");
print_array(nums, 10);

printf("Elements 3..6: ");
print_array(&nums[3], 4);

return 0;
}

void print_array(int array[], int array_length) {
int i = 0;
while (i < array_length) {
printf("%d", array[i]);
if (i != array_length - 1) {
printf(",");
}
i = i + 1;
}
printf("\n");
}

``````

print lines form file after replacing specified pattern after replacing specified pattern
```    ```#include <stdio.h>
#include <string.h>

#define MAX_LINE 1024
#define MAX_REPLACEMENT_LINE 32768

void replace(char string[], char target[], char replacement[], char new_string[], int new_string_len);

int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s <target> <replacement> <files>\n", argv[0]);
return 1;
}
char *target_string = argv[1];
char *replacement_string = argv[2];

int argument = 0;
while (argument < argc) {
FILE *stream = fopen(argv[argument], "r");
if (stream == NULL) {
perror(argv[argument]);
return 1;
}

char line[MAX_LINE];
while (fgets(line, MAX_LINE, stream) != NULL) {
char changed_line[MAX_REPLACEMENT_LINE];
replace(line, target_string, replacement_string, changed_line, MAX_REPLACEMENT_LINE);
printf("%s", changed_line);
}

argument = argument + 1;
}
return 0;
}

// copy string to new_string replacing all instances of target with replacement

void replace(char string[], char target[], char replacement[], char new_string[], int new_string_len) {
int target_length = strlen(target);
int replacement_length = strlen(replacement);

int i = 0;
int j = 0;
while (string[i] != '\0' && j < new_string_len - 1) {

// if we have found the target string

if (strncmp(target, &string[i], target_length) == 0) {

// instead copy the replacement string to the new array

strncpy(&new_string[j], replacement, replacement_length);
i = i + target_length;
j = j + replacement_length;
} else {
new_string[j] = string[i];
i = i + 1;
j = j + 1;
}
}

new_string[j] = '\0';
}

``````

Extra C
```    ```#include <stdio.h>

int x;

void f(int j) {
x = j;
}

int main(void) {
printf("%d\n", x); // prints 0
f(42);
printf("%d\n", x); // prints 42
x = 1;
printf("%d\n", x); // prints 1
return 0;
}

``````

```    ```#include <stdio.h>

int f(int j) {
static int x;
x = x + j;
return x;
}
int main(void) {
printf("%d\n", f(1)); // prints 1
printf("%d\n", f(2)); // prints 3
printf("%d\n", f(4)); // prints 7
return 0;
}

``````

```    ```#include <stdio.h>

int main(void) {
int x = 42;
int y = 11;
double f;

f = x / y;
printf("42/11=%f\n", f); // prints 3.000000
f = x/((double)y);       // convert y to a double
printf("42/11=%f\n", f); // prints 3.818182
return 0;
}

``````

Malloc
simple examples of using sizeof
```    ```#include <stdio.h>

int main(void) {

printf("sizeof (char) = %d\n", (int)sizeof (char));
printf("sizeof (int) = %d\n", (int)sizeof (int));
printf("sizeof (double) = %d\n", (int)sizeof (double));
printf("sizeof int[10] = %d\n", (int)sizeof (int[10]));
printf("sizeof int * = %d\n", (int)sizeof (int *));
printf("sizeof \"hello\" = %d\n", (int)sizeof "hello");

return 0;
}

``````

simple example of using malloc to create an array
Read n numbers and print them in reverse order
```    ```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

int n;
scanf("%d", &n);

int *numbers = malloc(n * sizeof (int));
if (numbers == NULL) {
fprintf(stderr, "%s: malloc failed\n", argv[0]);
return 1;
}

for (int i = 0; i < n; i = i + 1) {
scanf("%d", &numbers[i]);
}

printf("Numbers reversed are:\n");
for (int i = n - 1; i >= 0; i = i - 1) {
printf("%d\n", numbers[i]);
}

// free the allocated storage
// this would happen on program exit anyway
free(numbers);
return 0;
}

``````

example of using malloc to progressively allocate larger array as needed
Read n numbers and print them in reverse order
```    ```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
int n = 0;
int arraySize = 4;
int *array = malloc(arraySize * sizeof (int));
if (array == NULL) {
fprintf(stderr, "%s: malloc failed\n", argv[0]);
return 1;
}

while (scanf("%d", &array[n]) == 1) {
n = n + 1;
if (n == arraySize) {

// allocate larger array
int newArraySize = 2 * arraySize;
int *newArray = malloc(newArraySize * sizeof (int));
if (newArray == NULL) {
fprintf(stderr, "%s: malloc failed\n", argv[0]);
return 1;
}

// copy contents of old array to new array
for (int i = 0; i < arraySize; i = i + 1) {
newArray[i] = array[i];
}

// deallocate old array
free(array);

// change pointer to new array
array = newArray;
arraySize = newArraySize;
printf("Array size increased to %d\n", arraySize);
}
}

printf("Numbers reversed are:\n");
for (int i = n - 1; i >= 0; i = i - 1) {
printf("%d\n", array[i]);
}

// free the allocated storage
// this would happen on program exit anyway
free(array);
return 0;
}

``````

example of using realloc to progressively allocate larger array as needed
Read n numbers and print them in reverse order
```    ```#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
int n = 0;
int arraySize = 4;
int *array = malloc(arraySize * sizeof (int));
if (array == NULL) {
fprintf(stderr, "%s: malloc failed\n", argv[0]);
return 1;
}

while (scanf("%d", &array[n]) == 1) {
n = n + 1;
if (n == arraySize) {
// allocate larger array
arraySize = 2 * arraySize;
array = realloc(array, arraySize * sizeof (int));
if (array == NULL) {
fprintf(stderr, "%s: realloc failed\n", argv[0]);
return 1;
}
printf("Array size increased to %d\n", arraySize);
}
}

printf("Numbers reversed are:\n");
for (int i = n - 1; i >= 0; i = i - 1) {
printf("%d\n", array[i]);
}

// free the allocated storage
// this would happen on program exit anyway
free(array);
return 0;
}

``````

Lists
```\$ dcc list.c
\$ a.out
Enter a number: 1
Enter a number: 2
Enter a number: 3
Enter a number: 4
Enter a number: 5
Enter a number:
List entered was: [1, 2, 3, 4, 5]
First element in list is: 1.
Last element in list is: 5.
Length of list is: 5.
Sum of the list is: 15.
42 is not in the list.
```

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

struct node {
struct node *next;
int         data;
};

struct node *create_node(int data, struct node *next);
struct node *append(struct node *head, int value);
struct node *find_node(struct node *head, int data);

int
main(int argc, char *argv[]) {

while (1) {
int number;
printf("Enter a number: ");
if (scanf("%d", &number) != 1) {
break;
}
}

printf("List is empty.\n");
return 0;
}
printf("\nList entered was: ");

printf("\nFirst element in list is: %d.\n", head->data);
printf("Last element in list is: %d.\n", last(head)->data);
printf("Length of list is: %d.\n", length(head));
printf("Sum of the list is: %d.\n", sum(head));

if (find_node(head, 42) != NULL) {
printf("42 is in the list.\n");
} else {
printf("42 is not in the list.\n");
}
return 0;
}

// Create a new struct node containing the specified data,
// and next fields, return a pointer to the new struct node.

struct node *create_node(int data, struct node *next) {
struct node *n = malloc(sizeof (struct node));
if (n == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
n->data = data;
n->next = next;
return n;
}

// return pointer to last node in list
// NULL is returned if list is empty

struct node *last(struct node *head) {
return NULL;
}

while (n->next != NULL) {
n = n->next;
}
return n;
}

// create a new list node containing value
// and append it to end of list

struct node *append(struct node *head, int value) {
// new node will be last in list, so next field is NULL
struct node *n = create_node(value, NULL);
// new node is now  head of the list
return n;
} else {
// change next field of last list node
// from NULL to new node
last(head)->next = n;  /* append node to list */
}
}

// return sum of list data fields

int sum = 0;
// execute until end of list
while (n != NULL) {
sum += n->data;
// make n point to next item
n = n->next;
}
return sum;
}

// return sum of list data fields: using for loop

int sum = 0;
for (struct node *n = head; n != NULL; n = n->next) {
sum += n->data;
}
return sum;
}

// print contents of list in Python syntax

printf("[");
for (struct node *n = head; n != NULL; n = n->next) {
printf("%d", n->data);
if (n->next != NULL) {
printf(", ");
}
}
printf("]");
}

// return count of nodes in list

int len = 0;
for (struct node *n = head; n != NULL; n = n->next) {
len = len + 1;
}
return len;
}

// return pointer to first node with specified data value
// return NULL if no such node

struct node *find_node(struct node *head, int data) {

// search until end of list reached
while (n != NULL) {
// if matching item found return it
if (n->data == data) {
return n;
}

// make node point to next item
n = n->next;
}

// item not in list
return NULL;
}

// previous function written as for loop

struct node *find_node1(struct node *head, int data) {
for (struct node *n = head; n != NULL; n = n->next) {
if (n->data == data) {
return n;
}
}
return NULL;
}

// previous function written as a more concise while loop

struct node *find_node2(struct node *head, int data) {
while (n != NULL && n->data != data) {
n = n->next;
}
return n;
}

``````

linked list processing functions from list.c - recursive versions
```    ```#include <stdio.h>
#include <stdlib.h>

struct node {
struct node *next;
int         data;
};

struct node *create_node(int data, struct node *next);
struct node *append(struct node *head, int value);
struct node *find_node(struct node *head, int data);

int
main(int argc, char *argv[]) {

while (1) {
int number;
printf("Enter a number: ");
if (scanf("%d", &number) != 1) {
break;
}
}

printf("List is empty.\n");
return 0;
}
printf("\nList entered was: ");

printf("\nFirst element in list is: %d.\n", head->data);
printf("Last element in list is: %d.\n", last(head)->data);
printf("Length of list is: %d.\n", length(head));
printf("Sum of the list is: %d.\n", sum(head));

if (find_node(head, 42) != NULL) {
printf("42 is in the list.\n");
} else {
printf("42 is not in the list.\n");
}
return 0;
}

// Create a new struct node containing the specified data,
// and next fields, return a pointer to the new struct node.

struct node *create_node(int data, struct node *next) {
struct node *n = malloc(sizeof (struct node));
if (n == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
n->data = data;
n->next = next;
return n;
}

// return pointer to last node in list
// NULL is returned if list is empty

struct node *last(struct node *head) {
}
}

// create a new list node containing value
// and append it to end of list

struct node *append(struct node *head, int value) {
return create_node(value, NULL);
}
}

// return sum of list data fields: using recursive call

return 0;
}
}

// print contents of list in Python syntax

printf("[");
}
printf("]");
}

printf(", ");
}
}

// return count of nodes in list

return 0;
}
}

// return pointer to first node with specified data value
// return NULL if no such node

struct node *find_node(struct node *head, int data) {
}
}

``````

Stacks And Queues
```Three implementations of a Stack Abstract Data Type
https://en.wikipedia.org/wiki/Abstract_data_type

\$ dcc stack_example.c  stack_list.c -o stack_example
\$ a.out
3
12
12
11
10
0
\$ dcc stack_example.c  stack_array.c -o stack_example
\$ a.out
3
12
12
11
10
0
\$ dcc stack_example.c  stack_realloc.c -o stack_example
\$ a.out
3
12
12
11
10
0
```

```    ```#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

int main(void) {
stack s;

s = stack_create();

stack_push(s, 10);
stack_push(s, 11);
stack_push(s, 12);

printf("%d\n", stack_size(s)); // prints 3

printf("%d\n", stack_top(s)); // prints 12

printf("%d\n", stack_pop(s)); // prints 12
printf("%d\n", stack_pop(s)); // prints 11
printf("%d\n", stack_pop(s)); // prints 10

printf("%d\n", stack_size(s)); // prints 0

return 0;
}

``````

```    ```/*
Stack Abstract Data Type
https://en.wikipedia.org/wiki/Abstract_data_type

Actual implementation of stack opaque to (hidden from) user
*/

typedef struct stack_internals *stack;

stack stack_create(void);           // create a new stack
void stack_free(stack s);           // free a stack
void stack_push(stack s, int item); // add new item to stack
int stack_pop(stack s);             // remove top item from stack and return it
int stack_is_empty(stack s);        // return true if stack is empty
int stack_top(stack s);             // return top item from stack but don't remove it
int stack_size(stack s);            // return number elements in stack

``````

```Implementation of stack Abstract Data Type with an array
```

```    ```#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

#define MAX 2048

struct stack_internals {
int elements[MAX];
int top;
};

// create a new stack
stack stack_create(void) {
stack s = malloc(sizeof *s);
if (s == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
s->top = 0;
return s;
}

// add new item to stack
void stack_push(stack s, int item) {
if (s->top == MAX) {
fprintf(stderr, "push() exceeds maximum stack size %d\n", MAX);
exit(1);
}
s->elements[s->top] = item;
s->top = s->top + 1;
}

// remove top item from stack and return it
int stack_pop(stack s) {
if (stack_is_empty(s)) {
fprintf(stderr, "pop() of empty stack\n");
exit(1);
}
s->top = s->top - 1;
return s->elements[s->top];
}

// return true if stack is empty
int stack_is_empty(stack s) {
return s->top == 0;
}

int stack_top(stack s) {
if (stack_is_empty(s)) {
fprintf(stderr, "top() of empty stack\n");
exit(1);
}
return s->elements[s->top-1];
}

// return number elements in stack
int stack_size(stack s) {
return s->top;
}

// free a stack
void stack_free(stack s) {
free(s);
}

``````

```Implementation of stack Abstract Data Type with a linked list
```

```    ```#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

struct stack_internals {
struct node   *top;
int            size;
};

struct node {
int       data;
struct node *next;
};

// create a new stack
stack stack_create(void) {
stack s = malloc(sizeof *s);
if (s == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
s->top = NULL;
s->size = 0;
return s;
}

// add new item to stack
void stack_push(stack s, int item) {
struct node *n = malloc(sizeof *n);
n->data = item;
n->next  = s->top;
s->top = n;
s->size = s->size + 1;
}

// remove top item from stack and return it
int stack_pop(stack s) {
int i;
struct node *n;

if (stack_is_empty(s)) {
fprintf(stderr, "pop() of empty stack\n");
exit(1);
}

n = s->top;
i = n->data;
s->top = s->top->next;
s->size = s->size - 1;
free(n);
return i;
}

// return true if stack is empty
int stack_is_empty(stack s) {
return s->top == NULL;
}

int stack_top(stack s) {
if (stack_is_empty(s)) {
fprintf(stderr, "top() of empty stack\n");
exit(1);
}
return s->top->data;
}

// return number elements in stack
int stack_size(stack s) {
return s->size;
}

// free a stack
void stack_free(stack s) {
while (!stack_is_empty(s)) {
stack_pop(s);
}
free(s);
}

``````

```Implementation of stack Abstract data Type with  malloc/realloc
```

```    ```#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

#define INITIAL_STACK_SIZE 1024

struct stack_internals {
int *elements;
int size;
int top;
};

// create a new stack
stack stack_create(void) {
stack s = malloc(sizeof *s);
if (s == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
s->size = INITIAL_STACK_SIZE;
s->elements = malloc(s->size * sizeof s->elements[0]);
if (s->elements == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
s->top = 0;
return s;
}

// add new item to stack
void stack_push(stack s, int item) {
if (s->top == s->size) {
s->size = s->size * 2;
s->elements = realloc(s->elements, s->size * sizeof s->elements[0]);
if (s->elements == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
}
s->elements[s->top] = item;
s->top = s->top + 1;
}

// remove top item from stack and return it
int stack_pop(stack s) {
if (stack_is_empty(s)) {
fprintf(stderr, "pop() of empty stack\n");
exit(1);
}
s->top = s->top - 1;
return s->elements[s->top];
}

// return true if stack is empty
int stack_is_empty(stack s) {
return s->top == 0;
}

int stack_top(stack s) {
if (stack_is_empty(s)) {
fprintf(stderr, "top() of empty stack\n");
exit(1);
}
return s->elements[s->top-1];
}

// return number elements in s
int stack_size(stack s) {
return s->top;
}

// free a stack
void stack_free(stack s) {
free(s->elements);
free(s);
}

``````

```
Read stdin checking   { [ ( left brackets match ) ] } right brackets
Other characters ignored.

\$ dcc brackets.c stack_list.c -o brackets   # or stack_array.c or stack_realloc.c
\$ ./brackets
[ {{ ( ) } ]
Error: bracket mismatch '{' versus ']'
```

```    ```#include <stdio.h>

#include "stack.h"

int main(void) {

stack s = stack_create();

int ch = getchar();
while (ch != EOF) {

if (ch == '{' || ch == '(' || ch == '[') {
stack_push(s, ch);
} else if (ch == '}' || ch == ')' || ch == ']') {
if (stack_is_empty(s)) {
printf("Error: unbalanced '%c'\n", ch);
return 1;
}

int left_bracket = stack_pop(s);
if (
(ch == '}' && left_bracket != '{') ||
(ch == ')' && left_bracket != '(') ||
(ch == ']' && left_bracket != '[')
) {
printf("Error: bracket mismatch '%c' versus '%c'\n", left_bracket, ch);
return 1;
}
}

ch = getchar();
}

if (!stack_is_empty(s)) {
printf("Error: unbalanced '%c'\n", stack_pop(s));
return 1;
}

return 0;
}

``````

```Reverse Polish notation calculator using stack ADT

https://en.wikipedia.org/wiki/Reverse_Polish_notation

\$ dcc postfix.c stack_list.c -o postfix   # or stack_array.c or stack_realloc.c
\$ ./postfix
15 7 1 1 + - / 3 * 2 1 1 + + -
Result: 5
```

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

#include "stack.h"

#define MAX_LINE 4096
int main(void) {

char line[4096];
while (fgets(line, sizeof line, stdin) != NULL) {
stack s = stack_create();

int i = 0;
while (line[i] != '\0') {
int ch = line[i];

if (isdigit(ch)) {
// convert chars to num push number onto stack
// and skip over digits

int num = atoi(&line[i]);

stack_push(s, num);

while (isdigit(line[i])) {
i = i + 1;
}
} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {

// pop 2 values from stack
// calculate result
// push result onto stack

int a = stack_pop(s);
int b = stack_pop(s);

int result;
if (ch == '+') {
result = b + a;
} else if (ch == '-') {
result = b - a;
} else if (ch == '*') {
result = b * a;
} else {
result = b / a;
}

stack_push(s, result);
}
i = i + 1;
}

printf("Result: %d\n", stack_pop(s));
}

return 0;
}

``````

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

#include "queue.h"

int main(void) {
queue q;

q = queue_create();
queue_enqueue(q, 10);
queue_enqueue(q, 11);
queue_enqueue(q, 12);

printf("%d\n", queue_size(q)); // prints 3
printf("%d\n", queue_front(q)); // prints 10
printf("%d\n", queue_dequeue(q)); // prints 10
printf("%d\n", queue_dequeue(q)); // prints 11
printf("%d\n", queue_dequeue(q)); // prints 12

return 0;
}

``````

```    ```/*
Queue Abstract Data Type

https://en.wikipedia.org/wiki/Abstract_data_type

Actual implementation of queue opaque to (hidden from) user
*/

typedef struct queue_internals *queue;

queue queue_create(void);                  // create a new queue
void queue_free(queue q);              // free a queue
void queue_enqueue(queue q, int item); // add new item to queue
int queue_dequeue(queue q);            // remove next item from queue and return it
int queue_is_empty(queue q);           // return true if queue is empty
int queue_front(queue q);              // return next item from queue but don't remove it
int queue_size(queue q);               // return number elements in queue

``````

completion left as an exercise
```    ```#include <stdio.h>
#include <stdlib.h>
#include "queue.h"

struct queue_internals {
};

struct node {
struct node *next;
int       data;
};

// create a new queue
queue queue_create(void) {
return NULL;
}

// add new item to queue
void queue_enqueue(queue queue, int item) {
}

// remove top item from queue and return it
int queue_dequeue(queue queue) {
return 0;
}

// return true if queue is empty
int queue_is_empty(queue queue) {
return 0;
}

int queue_front(queue queue) {
return 0;
}

// return number elements in queue
int queue_size(queue queue) {
return 0;
}

// free a queue
void queue_free(queue queue) {
}

``````

Illegal C
```    ```#include <stdio.h>
#include <stdlib.h>

void f() {
int i;
int x = 9;
int a[10];

for (i = 0; i < 16; i++)
printf("%2d: Address %x contains %p\n", i, &a[10+i], a[10+i]);
}

int main(void) {
int a = 7;
printf("function main is at address 0x%x\n", &main);
printf("function f is at address 0x%x\n", &f);
f();
return 0;
}

``````

```
Run at CSE like this

\$ gcc-7 invalid0.c -o invalid0
\$ ./invalid0
42 42 42 77 77 77 77 77 77 77

```

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

int main(void) {
int a[10];
int b[10];
printf("a[9] is at address %p\n", &a[9]);
printf("b[9] is at address %p\n", &b[9]);

for (int i = 0; i < 10; i++) {
a[i] = 77;
}

// loop writes to b[10] .. b[12] which don't exist -
// with gcc 7.3 on x86_64/Linux
// b[12] is stored where a[0] is stored
// with gcc 7 on CSE lab machines
// b[10] is stored where a[0] is stored

for (int i = 0; i <= 12; i++) {
b[i] = 42;
}

// prints 42 77 77 77 77 77 77 77 77 77 on x86_64/Linux
// prints 42 42 42 77 77 77 77 77 77 77 at CSE
for (int i = 0; i < 10; i++) {
printf("%d ", a[i]);
}
printf("\n");

return 0;
}

``````

```
Run at CSE like this

\$ gcc-7 invalid1.c -o invalid1
\$ ./invalid1
42 42 42 77 77 77 77 77 77 77

```

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

int main(void) {
int i;
int a[10];
printf("i is at address %p\n", &i);
printf("a[0] is at address %p\n", &a[0]);
printf("a[9] is at address %p\n", &a[9]);
printf("a[10] would be stored at address %p\n", &a[10]);

// loop writes to a[10] .. a[11] which don't exist -
// but with gcc 7 on x86_64/Linux
// i would be stored where a[11] is stored

for (i = 0; i <= 11; i++) {
a[i] = 0;
}

return 0;
}

``````

```
Run at CSE like this

\$ gcc-7 invalid2.c -o invalid2
\$ ./invalid2

```

```    ```#include <stdio.h>

void f(int x);

int main(void) {

f(5);

return 0;
}

void f(int x) {
int a[10];

// a[19] doesn't exist
// with gcc-7 at CSE variable answer in main
// happens to be where a[21] would be
// on 64-bit Linux try 19 instead of 21

printf("a[21] would be stored at address %p\n", &a[21]);

a[21] = 42;
}

``````

```
Run at CSE like this

\$ gcc-7 invalid3.c -o invalid3
\$ ./invalid3
I will never be printed.
argc was 1
\$

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

void f(void);

void f(void);

int main(int argc, char *argv[]) {

f();

if (argc > 0) {
printf("I will always be printed.\n");
}

if (argc <= 0) {
printf("I will never be printed.\n");
}

printf("argc was %d\n", argc);
return 0;
}

void f() {
int a[10];

// function f has it return address on the stack
// the next statement which is:  if (argc > 0)
//
// with gcc7 at CSE  f's return address is stored where a[11] would be
//
// so changing a[11] changes where the function returns
//
// adding 28 to a[11] happens to cause it to return several statements later
// at the printf("I will never be printed.\n");
//
// on 64 bit linux  machines try instead a[14] += 24

a[11] += 28;
}

``````

```
Run at CSE like this

\$ gcc-7 invalid4.c -o invalid4
\$ ./invalid4
Welcome. You are authorized.
\$

```
```    ```#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
int authenticated = 0;

int i = 0;
int ch = getchar();
while (ch != '\n' && ch != EOF) {
ch = getchar();
i = i + 1;
}

if (strcmp(password, "secret") == 0) {
authenticated = 1;
}

// a password longer than 8 characters will overflow the array password
// the variable authenticated is at the address where
// where password[8] would be and gets overwritten
//
// This allows access without knowing the correct password

if (authenticated) {
printf("Welcome. You are authorized.\n");
} else {
printf("Welcome. You are unauthorized.  Your death will now be implemented.\n");
printf("Welcome. You will experience a tingling sensation and then death. \n");
printf("Remain calm while your life is extracted.\n");
}

return 0;
}

``````

Sorting And Searching
```\$ dcc compare_search.c
\$ ./a.out 1000000
Array size is 1000000, elements are:  3 10 14 6 26 49 61 69 72 73 105 130 36 137 141 58 150 184 197 159 209 ...

Search for? 49
Linear search: 49 is in the numbers - search took 6 operations
Binary search: 49 is in the numbers - search took 20 operations

Search for? 42
Linear search: 42 is not in the numbers - search took 1000000 operations
Binary search: 42 is not in the numbers - search took 20 operations
```

Instrument linear search and binary search with an operation counter and compare their performance on a sorted arrays of random numbers.

Array size is specified as a command line argument

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

int linear_search(int array[], int length, int x);
int binary_search(int array[], int length, int x);
void quicksort(int array[], int length);
void quicksort1(int array[], int lo, int hi);
int partition(int array[], int lo, int hi);
void sorted_random_ints(int array[], int length);
void random_ints(int array[], int length);

// we use a global variable to instrument the program
// and count operations performed

int operation_counter;

int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <array-size>\n", argv[0]);
exit(1);
}
int length = atoi(argv[1]);

// use malloc to create an array so we can
// because we may want an array too large to be a global variable

int *numbers = malloc(length * sizeof (int));
if (numbers == NULL) {
fprintf(stderr, "%s: <array-size>\n", argv[0]);
exit(1);
}

sorted_random_ints(numbers, length);

printf("Array size is %d, elements are: ", length);

for (int i = 0; i < length; i = i + 1) {
printf(" %d", numbers[i]);
if (i == 20) {
printf(" ... ");
i = length;
}
}
printf("\n");

while (1) {
int x;
printf("Search for? ");
if (scanf("%d", &x) != 1) {
free(numbers);
return 0;
}

operation_counter = 0;
printf("\nLinear search: ");
if (linear_search(numbers, length, x) == 1) {
printf("%d is in the numbers", x);
} else {
printf("%d is not in the numbers", x);
}
printf(" - search took %d operations\n", operation_counter);

operation_counter = 0;
printf("Binary search: ");
if (binary_search(numbers, length, x) == 1) {
printf("%d is in the numbers", x);
} else {
printf("%d is not in the numbers", x);
}
printf(" - search took %d operations\n\n", operation_counter);
}
}

int linear_search(int array[], int length, int x) {

for (int i = 0; i < length; i = i + 1) {
operation_counter++;
if (array[i] == x) {
return 1;
}
}

return 0;
}

int binary_search(int array[], int length, int x) {
int lower = 0;
int upper = length - 1;
while (lower <= upper) {
int mid = (lower + upper)/ 2;
operation_counter++;
if (array[mid] == x) {
return 1;
} else if (array[mid] > x) {
upper = mid - 1;
} else {
lower = mid + 1;
}
}
return 0;
}

// fill array with pseudo-random ints

void random_ints(int array[], int length) {
for (int i = 0; i < length; i = i + 1) {
array[i] = rand() % (10 * length);
}
}

// fill array with pseudo-random ints in sorted (non-decreasing) order

void sorted_random_ints(int array[], int length) {
random_ints(array, length);
quicksort(array, length);
}

// https://en.wikipedia.org/wiki/Quicksort

void quicksort(int array[], int length) {
quicksort1(array, 0, length - 1);
}

void quicksort1(int array[], int lo, int hi) {
if (lo >= hi) {
return;
}
// rearrange array so that
// all elements smaller than pivot value are below it and
// all element larger than pivot value are above it
int p = partition(array, lo, hi);
// sort lower part of array
quicksort1(array, lo, p);

// sort upper part of array
quicksort1(array, p + 1, hi);
}

int partition(int array[], int lo, int hi) {
int i = lo;
int j = hi;

// use middle value as pivot
int pivotValue = array[(lo + hi) / 2];

// start from left and right ends
while (1) {

// Look for pair to swap

while (array[i] < pivotValue) {
i = i + 1;
operation_counter++;
}

while (array[j] > pivotValue) {
j = j - 1;
operation_counter++;
}

// No pair to swap so return
if (i >= j) {
return j;
}
// and swap them over
int temp = array[i];
array[i] = array[j];
array[j] = temp;
i = i + 1;
j = j - 1;
}
}

``````

```\$ dcc compare_sort.c
\$ ./a.out
Array size    10:  bubblesort took       81 operations,  quicksort took     24 operations
Array size   100:  bubblesort took     8415 operations,  quicksort took    457 operations
Array size  1000:  bubblesort took   981018 operations,  quicksort took   9351 operations
Array size 10000:  bubblesort took 98790120 operations,  quicksort took 102807 operations
```

Instrument quicksort and bubblesort with an operation counter and compare performance on arrays of random numbers of size 10..10000

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

// use a global variable to count operations
// at key points for both sorting algorithms
int operation_counter;

void bubblesort(int array[], int length);
void quicksort(int array[], int length);
void quicksort1(int array[], int lo, int hi);
int partition(int array[], int lo, int hi);
void random_ints(int array[], int length);

int main(void) {
for (int n = 10; n <= 10000; n = n * 10) {
int numbers1[n];
int numbers2[n];

random_ints(numbers1, n);
for (int i = 0; i < n; i = i + 1) {
numbers2[i] = numbers1[i];
}

printf("Array size %5d: ", n);
operation_counter = 0;
bubblesort(numbers1, n);
printf(" bubblesort took %8d operations,", operation_counter);
operation_counter = 0;
quicksort(numbers2, n);
printf("  quicksort took %6d operations\n", operation_counter);

for (int i = 0; i < n; i = i + 1) {
if(numbers2[i] != numbers1[i]) {
printf("arrays differ at index %d\n", i);
return 1;
}
}
}
return 0;
}

// https://en.wikipedia.org/wiki/Bubble_sort

void bubblesort(int array[], int length) {
int swapped = 1;
while (swapped) {
swapped = 0;
for (int i = 1; i < length; i = i + 1) {
operation_counter++;
if (array[i] < array[i - 1]) {
int tmp = array[i];
array[i] = array[i - 1];
array[i - 1] = tmp;
swapped = 1;
}
}
}
}

// https://en.wikipedia.org/wiki/Quicksort

void quicksort(int array[], int length) {
quicksort1(array, 0, length - 1);
}

void quicksort1(int array[], int lo, int hi) {
if (lo >= hi) {
return;
}
// rearrange array so that
// all elements smaller than pivot value are below it and
// all element larger than pivot value are above it
int p = partition(array, lo, hi);
// sort lower part of array
quicksort1(array, lo, p);

// sort upper part of array
quicksort1(array, p + 1, hi);
}

int partition(int array[], int lo, int hi) {
int i = lo;
int j = hi;

// use middle value as pivot
int pivotValue = array[(lo + hi) / 2];

// start from left and right ends
while (1) {

// Look for pair to swap

while (array[i] < pivotValue) {
i = i + 1;
operation_counter++;
}

while (array[j] > pivotValue) {
j = j - 1;
operation_counter++;
}

// No pair to swap so return
if (i >= j) {
return j;
}
// and swap them over
int temp = array[i];
array[i] = array[j];
array[j] = temp;
i = i + 1;
j = j - 1;
}
}

// fill array with pseudo-random ints

void random_ints(int array[], int length) {
for (int i = 0; i < length; i = i + 1) {
array[i] = rand() % (10 * length);
}
}

``````

Exam