Professional Documents
Culture Documents
Miscellaneous topics
Swaroop Joshi
2023
Multidimensional Arrays
Multidimensional Arrays
row⬇ | col ➡ 0 1 2
0 1 2 3
1 4 5 6
2 7 8 9
int mat[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; Assigns these 9 values to it
Multidimensional Arrays
void display_matrix(int mat[3][3])
{
for (int r = 0; r < 3; ++r) row⬇ | col ➡ 0 1 2
{ 0 1 2 3
for (int c = 0; c < 3; ++c)
printf("%d ", mat[r][c]); 1 4 5 6
printf("\n");
}
2 7 8 9
}
1 2 3
4 5 6
7 8 9
row⬇ | col ➡ 0 1 2
0 1 2 3
1 4 5 6
2 7 8 9
Multidimensional Arrays Displaying the address of each
cell instead of its contents
1 2 3 4 5 6 7 8 9
fi
Multidimensional Arrays
void display_matrix_addr(int mat[3][3])
{
for (int r = 0; r < 3; ++r) row⬇ | col ➡ 0 1 2
{ 0 1 2 3
Think of it cas =an0;
for (int array
c <of3;arrays:
++c)
printf("%p
num_rows rows ", &mat[r][c]);
of num_cols each 1 4 5 6
printf("\n");
}
2 7 8 9
}
0x16fd6f444 0x16fd6f448 0x16fd6f44c
0x16fd6f450 0x16fd6f454 0x16fd6f458
0x16fd6f45c 0x16fd6f460 0x16fd6f464
1 2 3 4 5 6 7 8 9
A note about declaring -D arrays
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c)
m1[r][c] = k++;
display_matrix(m1, 3, 2);
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
}
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c)
m1[r][c] = k++;
display_matrix(m1, 3, 2);
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
}
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c)
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
m: int**
}
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c)
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
m: int**
}
Heap
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c)
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
m: int**
}
Heap
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c)
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
m: int**
}
Heap
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c) 1 2
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
m: int**
}
Heap
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c) 1 2
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
3 4
release_matrix(m1, 3, 2);
return 0;
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
m: int**
}
Heap
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c) 1 2
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
3 4
release_matrix(m1, 3, 2);
return 0;
5 6
}
2
-D arrays on the heap
int **alloc_matrix(int num_rows, int num_cols)
{
int **m = calloc(num_rows, sizeof(int *));
for (int i = 0; i < num_rows; ++i)
m[i] = calloc(num_cols, sizeof(int));
return m;
}
Heap
int main() {
int **m1 = alloc_matrix(3, 2);
int k = 1;
for (int r = 0; r < 3; ++r)
for (int c = 0; c < 2; ++c) 1 2
m1[r][c] = k++; m1: int**
display_matrix(m1, 3, 2);
3 4
release_matrix(m1, 3, 2);
return 0;
5 6
}
2
Write the code for release_matrix
-D arrays on the heap and trace it with the diagram
✤ Their scope will be from the point of declaration to the end of the le
✤ Be careful with global variables as a local variable can mask their scope
fi
Preprocessor
✤ #de ne
✤ De nes a macro
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
These printf statements are not
compiled if DEBUG is not #de ned
Conditional compilation
#include <stdio.h>
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
fi
These printf statements are not
compiled if DEBUG is not #de ned
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
fi
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
#define DEBUG 1
int max(int x, int y) { return x > y ? x : y; }
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
#define DEBUG 1
int max(int x, int y) { return x > y ? x : y; }
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} Now these statements are compiled and} executed
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
> gcc ifdebug.c ; ./a.out
#define DEBUG 1 Value of x is 20
int max(int x, int y) { return x > y ? x : y; } Value of x is 30
Largest = 30
int greatest_of_3(int x, int y, int z) {
x = max(x, y);
#ifdef DEBUG
printf("Value of x is %d\n", x);
#endif
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} Now these statements are compiled and} executed
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
> gcc ifdebug.c ; ./a.out
#define DEBUG 1 Does not have to be de ned to 1 Value of x is 20
int max(int x, int y) { return x > y ? x : y; } Value of x is 30
Largest = 30
int greatest_of_3(int x, int y, int z) {
x = max(x, y);
#ifdef DEBUG
printf("Value of x is %d\n", x);
#endif
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
fi
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
> gcc ifdebug.c ; ./a.out
#define DEBUG 1 Value of x is 20
int max(int x, int y) { return x > y ? x : y; } Value of x is 30
Largest = 30
int greatest_of_3(int x, int y, int z) {
x = max(x, y);
#ifdef DEBUG
printf("Value of x is %d\n", x);
#endif
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
> gcc ifdebug.c ; ./a.out
Value of x is 20
int max(int x, int y) { return x > y ? x : y; } Value of x is 30
Largest = 30
int greatest_of_3(int x, int y, int z) {
x = max(x, y);
#ifdef DEBUG Can also be de ned while compiling > gcc ifdebug.c -DDEBUG; ./a.out
printf("Value of x is %d\n", x); Value of x is 20
#endif Value of x is 30
Largest = 30
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
fi
Conditional compilation > gcc ifdebug.c ; ./a.out
Largest = 30
#include <stdio.h>
> gcc ifdebug.c ; ./a.out
Value of x is 20
int max(int x, int y) { return x > y ? x : y; } Value of x is 30
Largest = 30
int greatest_of_3(int x, int y, int z) {
x = max(x, y);
#ifdef DEBUG > gcc ifdebug.c -DDEBUG; ./a.out
printf("Value of x is %d\n", x); Value of x is 20
#endif Value of x is 30
Largest = 30
x = max(x, z);
#ifdef DEBUG int main() {
printf("Value of x is %d\n", x); int m3 = greatest_of_3(10, 20, 30);
#endif printf("Largest = %d\n", m3);
return x; return 0;
} }
Enums
✤ Sometimes you want to name some numeric values for better code
comprehension
✤ For example, instead of using ints 1, 2, 3, … for the seven days of the week,
you may want to create constants int MONDAY = 1, etc. so you can use
MONDAY, TUESDAY, etc. in your code and not worry about whether
MONDAY is 1 or 2
✤ But these constants have no relation to one another and maintaining them
can be cumbersome too
Enums
Enums
day d = mon;
day d = mon;
day d = mon;
day d = mon;
day tomorrow(day d)
✤ Write a function tomorrow that {
return d == sun ? mon : d + 1;
takes a day and returns the next }
day
typedef enum {
Enums mon = 1, tue, wed, thu, fri, sat, sun
} day;
day tomorrow(day d)
✤ Write a function tomorrow that {
return d == sun ? mon : d + 1;
takes a day and returns the next }
day
day tomorrow(day d)
✤ Write a function tomorrow that {
return d == sun ? mon : d + 1;
takes a day and returns the next }
day
double daily_earning[5];
✤ Can also be used as array subscripts daily_earning[mon] = 1329.56;
Switch-case
int watts;
printf("Enter wattage for your bulb: ");
scanf("%d", &watts);
int life;
switch (watts)
{
case 25:
life = 2500;
✤ Alternative to if-else chains for break;
case 40:
multiple alternative decisions
case 60:
life = 1000;
✤ The expression after case must be a break;
case 75:
constant → strings not supported
case 100:
life = 750;
✤ Careful with break break;
default:
life = 0;
✤ Use of default }
printf("The bulb should last %d hours\n", life);
char grade
fclose(src_fp); fclose(dst_fp);
return 0;
}
int main(int argc, char **argv) { main can take two parameters: a count of CL args,
if (argc != 3) { and an array of CL args as strings
fprintf(stderr, "Usage: %s <src_file> <dest_file>\n", argv[0]);
return 1;
}
FILE *src_fp, *dst_fp;
if (!(src_fp = fopen(argv[1], “r"))) {
printf("%s: No such file or directory\n\n", argv[1]);
return -1;
}
fclose(src_fp); fclose(dst_fp);
return 0;
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <src_file> <dest_file>\n", argv[0]);
return 1;
}
FILE *src_fp, *dst_fp;
if (!(src_fp = fopen(argv[1], “r"))) {
printf("%s: No such file or directory\n\n", argv[1]);
Check if the
return -1; number of arguments match; if they
} don’t show an error message and exit
fclose(src_fp); fclose(dst_fp);
return 0;
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <src_file> <dest_file>\n", argv[0]);
return 1;
}
FILE *src_fp, *dst_fp;
if (!(src_fp = fopen(argv[1], “r"))) {
Remember, fprintf
printf("%s: No such file or directory\n\n", argv[1]); is just like printf, but it takes an
return -1; additional argument, the stream to write to.
} stdout is the standard output;
if (!(dst_fp = fopen(argv[2], “w"))) { stderr is for error messages
printf("Cannot open %s for writing\n\n", argv[2]);
return -2;
}
fclose(src_fp); fclose(dst_fp);
return 0;
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <src_file> <dest_file>\n", argv[0]);
return 1;
}
FILE *src_fp, *dst_fp;
if (!(src_fp = fopen(argv[1], “r"))) {
printf("%s: No such file or directory\n\n", argv[1]);
return -1;
}
return 0;
}
Your turn
> ./avg-cli
✤ Write a program that takes one or Usage: ./avg-cli <num> [<more nums>]
✤ We concerned ourselves only with int and double for Z and R, respectively
✤ C has many other types – most of which are variants of these based on the range of
values to be represented or operations to be performed on them
✤ We concerned ourselves only with int and double for Z and R, respectively
✤ C has many other types – most of which are variants of these based on the range of
values to be represented or operations to be performed on them
The language defines a minimum
✤ Signed and unsigned variants of size for each type and
int main()
{ ... }
Function Declaration Cannot compile!
It does not understand is_odd at
#include <stdio.h>
int main()
{ ... }
Function Declaration #include <stdio.h>
v. Definition
Declare the function (without de ning it)
#include <stdbool.h>
int main()
{ ... }
fi
Function Declaration #include <stdio.h>
int main()
{ ... }
Multi file programs
int n = atoi(argv[1]);
printf("%d is %s\n”,
n,
is_even(n) ? "even" : "odd");
return 0;
}
📄 evenodd-cli.c
#include <stdio.h> #include "evenodd.h"
#include <stdbool.h>
bool is_even(unsigned int n); bool is_even(unsigned int n) {
bool is_odd(unsigned int n); return n == 0 ? true : is_odd(n - 1);
}
📄 evenodd.h
bool is_odd(unsigned int n) {
return n == 0 ? false : is_even(n - 1);
}
#include "evenodd.h"
📄 evenodd.c
#include <stdlib.h>
int n = atoi(argv[1]);
printf("%d is %s\n”,
n,
is_even(n) ? "even" : "odd");
return 0;
}
📄 evenodd-cli.c
#include <stdio.h> #include "evenodd.h"
#include <stdbool.h>
bool is_even(unsigned int n); bool is_even(unsigned int n) {
bool is_odd(unsigned int n); return n == 0 ? true : is_odd(n - 1);
}
📄 evenodd.h
bool is_odd(unsigned int n) {
return n == 0 ? false : is_even(n - 1);
}
#include "evenodd.h"
📄 evenodd.c
#include <stdlib.h>
int n = atoi(argv[1]);
printf("%d is %s\n”,
n,
is_even(n) ? "even" : "odd");
return 0;
}
📄 evenodd-cli.c
fi
#include <stdio.h> #include "evenodd.h"
#include <stdbool.h>
bool is_even(unsigned int n); bool is_even(unsigned int n) {
bool is_odd(unsigned int n); return n == 0 ? true : is_odd(n - 1);
}
📄 evenodd.h
bool is_odd(unsigned int n) {
return n == 0 ? false : is_even(n - 1);
}
#include "evenodd.h"
📄 evenodd.c
#include <stdlib.h>
return 0;
}
📄 evenodd-cli.c
fi
#include <stdio.h> #include "evenodd.h"
#include <stdbool.h>
bool is_even(unsigned int n); bool is_even(unsigned int n) {
bool is_odd(unsigned int n); return n == 0 ? true : is_odd(n - 1);
}
📄 evenodd.h
bool is_odd(unsigned int n) {
return n == 0 ? false : is_even(n - 1);
}
#include "evenodd.h"
📄 evenodd.c
#include <stdlib.h>