Open-book midterm cheat sheet — all key topics with examples
Every program's skeleton — main, includes, comments
// Every C program MUST have main() — execution starts here #include <stdio.h> // include standard I/O library (gives printf, scanf) #include <string.h> // needed for strlen(), strcmp() int main(void) { printf("Hello, world!\n"); return 0; // 0 = success; main() must return int } /* Multi-line comment stripped by preprocessor — zero effect on execution speed */
#include directives go at the top, before any code. Only main() is mandatory — #include is optional (but you'll almost always need stdio.h).| Sequence | Meaning |
|---|---|
\n | newline |
\t | tab |
\\ | backslash |
\" | double quote |
\' | single quote |
\0 | null terminator (ASCII 0) |
;)| Trap | Wrong | Right |
|---|---|---|
| Assignment vs equality | if (x = 5) — always true! | if (x == 5) |
Missing & in scanf | scanf("%d", x) | scanf("%d", &x) |
| double in scanf | scanf("%f", &d) | scanf("%lf", &d) |
| Integer division | int/int = int: 7/2 = 3 | (float)7 / 2 = 3.5 |
| Chained comparison | 1 < x < 10 always true | x > 1 && x < 10 |
| Missing break in switch | falls through to next case | add break; each case |
| String size | char s[5] = "hello" — no room for \0! | char s[6] for 5 chars |
| Compare strings | if (s == "hi") — compares addresses | strcmp(s, "hi") == 0 |
| Return value used | void f() { return 5; } | use int f() |
| Post vs pre-increment | printf("%d", x++) prints OLD x | printf("%d", ++x) prints NEW x |
printf, scanf, format specifiers, #define
| Type | Size | Example value | printf / scanf |
|---|---|---|---|
int | 4 bytes | 42, -7 | %d |
float | 4 bytes | 3.14f | %f / %f |
double | 8 bytes | 3.14 | %f / %lf |
char | 1 byte | 'A', 65 | %c |
char[] | n bytes | "hello" | %s |
& before scalar variables in scanf. Arrays (like char str[]) don't need it — the array name is already an address.| Specifier | Use for | Example code | Output |
|---|---|---|---|
%d | int | printf("%d", 42) | 42 |
%f | float / double (printf) | printf("%f", 3.14) | 3.140000 |
%.2f | float, 2 decimal places | printf("%.2f", 3.14159) | 3.14 |
%e | scientific notation | printf("%e", 31400.0) | 3.140000e+04 |
%lf | double (scanf only) | scanf("%lf", &d) | — |
%c | single char | printf("%c", 'A') | A |
%d with char | char as integer (ASCII) | printf("%d", 'A') | 65 |
%s | string (char array) | printf("%s", "hi") | hi |
%% | literal percent sign | printf("100%%") | 100% |
int x; scanf("%d", &x); // & required — passes address of x printf("%d\n", x); // no & — just pass the value double d; scanf("%lf", &d); // %lf for double in scanf printf("%.3f\n", d); // %f is fine for double in printf char name[50]; scanf("%s", name); // no & — array name IS an address printf("Hello, %s!\n", name); char c = 'A'; printf("%c\n", c); // prints: A printf("%d\n", c); // prints: 65 (ASCII value) // Calculations inside printf — totally valid printf("%d\n", 5 + 4); // prints: 9
// #define — preprocessor macro, replaced BEFORE compilation // No type, no memory allocated, no semicolon #define MAX 100 #define PI 3.14159 int arr[MAX]; // becomes: int arr[100] // sizeof — returns size in bytes at compile time sizeof(int) // → 4 sizeof(double) // → 8 char arr[10] = "hi"; sizeof(arr) // → 10 (allocated size) strlen(arr) // → 2 (string length, not counting \0)
int, float, etc.). Underscores ARE allowed.// Key ASCII values to memorise: // '0' = 48, '9' = 57 (digits are sequential) // 'A' = 65, 'Z' = 90 (uppercase sequential) // 'a' = 97, 'z' = 122 (lowercase sequential, 'a'-'A' = 32) // Digit character → integer value char ch = '7'; int n = ch - '0'; // → 7 ('7'=55, '0'=48, 55-48=7) // Integer value → digit character int n = 4; char ch = n + '0'; // → '4' // Uppercase → lowercase char upper = 'G'; char lower = upper + 32; // → 'g' (or use upper + ('a'-'A')) // Lowercase → uppercase char lower = 'g'; char upper = lower - 32; // → 'G' // Check type of character if (ch >= 'A' && ch <= 'Z') { /* uppercase */ } if (ch >= 'a' && ch <= 'z') { /* lowercase */ } if (ch >= '0' && ch <= '9') { /* digit */ } // Letter position (A=0, B=1 ... Z=25) int pos = upper - 'A'; // 'G'-'A' = 6
char is just a small integer. Characters in a range ('A'–'Z', '0'–'9') are guaranteed to be consecutive, so arithmetic on them is portable.// %[flags][width][.precision]specifier printf("%4d\n", 42); // " 42" right-align in 4-char field printf("%-4d|\n", 42); // "42 |" left-align (- flag) printf("%04d\n", 42); // "0042" zero-pad to width 4 printf("%8.2f\n", 3.14159); // " 3.14" width 8, 2 decimal places printf("%.4f\n", 3.14159); // "3.1416" 4 decimal places, no width printf("%-10s|\n", "hi"); // "hi |" left-align string // Useful for tables — line up columns: for (int i = 1; i <= 5; i++) printf("%-3d %4d\n", i, i * i); // 1 1 // 2 4 // 3 9 // 4 16 // 5 25
// %s stops at whitespace — can't read a sentence: scanf("%s", name); // reads one word only ("John" from "John Smith") // fgets reads the whole line including spaces: fgets(name, sizeof(name), stdin); // reads "John Smith\n" — watch for \n at end! // Remove the newline fgets leaves in the buffer: name[strcspn(name, "\n")] = '\0'; // replaces \n with null terminator // Reading a char AFTER an int — newline gets stuck in buffer: int n; char c; scanf("%d", &n); scanf("%c", &c); // BUG: c gets '\n' left from previous scanf! scanf(" %c", &c); // FIX: space before %c skips all whitespace/newlines // Reading multiple values on one scanf: scanf("%d %d", &x, &y); // fine — whitespace in format matches any whitespace
int or float with scanf, if you next read a char, add a space before %c to flush the leftover newline.Arithmetic, logical, increment/decrement, precedence
| Operators | Direction |
|---|---|
* / % | left → right |
+ - | left → right |
// 3 * 3 % 6 + 4 * 5
// = (3*3) % 6 + (4*5) ← * and % left to right
// = 9 % 6 + 20
// = 3 + 20 = 23
| Op | Meaning |
|---|---|
&& | logical AND (both true) |
|| | logical OR (either true) |
! | logical NOT |
& | bitwise AND (different!) |
== | equality check |
!= | not equal |
int x = 4; // Pre-increment: changes value BEFORE use printf("%d", ++x); // prints 5, x is now 5 // Post-increment: uses current value FIRST, then increments printf("%d", x++); // prints 5, x becomes 6 after // Classic trap: int x=4, y=4; printf("%d,%d", ++x, y--); // ++x → 5 (pre), y-- → 4 printed then y becomes 3 // Output: 5,4
4 > y > 1 does NOT work as math in C.(4 > y) > 1 → 0 or 1 > 1 → always false.(4 > y && y > 1)// (type)expression — convert to a different type before the operation int a = 7, b = 2; (double)a / b // → 3.5 cast BEFORE dividing ✓ (double)(a / b) // → 3.0 integer division happens FIRST, then cast ✗ (int)3.9 // → 3 truncates toward zero (NOT rounded) (int)-3.9 // → -3 also truncates toward zero // Classic trap — average of two ints: int sum = 7; float avg = (float)sum / 2; // → 3.5 ✓ cast numerator first float bad = sum / 2; // → 3.0 ✗ integer division, then implicit cast
float/double BEFORE the /. If you cast after (double)(a/b), integer division already discarded the remainder.| Level | Operators | Direction |
|---|---|---|
| 1 (highest) | ( ) [ ] -> . | left→right |
| 2 | ! ++ -- (cast) * & sizeof (all unary) | right→left |
| 3 | * / % | left→right |
| 4 | + - | left→right |
| 5 | << >> (bit shift) | left→right |
| 6 | < <= > >= | left→right |
| 7 | == != | left→right |
| 8 | & (bitwise AND) | left→right |
| 9 | ^ (bitwise XOR) | left→right |
| 10 | | (bitwise OR) | left→right |
| 11 | && (logical AND) | left→right |
| 12 | || (logical OR) | left→right |
| 13 | ?: (ternary) | right→left |
| 14 (lowest) | = += -= *= /= %= etc. | right→left |
& / | have LOWER precedence than == / !=. So x & 1 == 0 parses as x & (1 == 0) — always parenthesize bitwise ops. Also: && beats || in precedence.if/else, switch, ternary
if (x > 0) { printf("positive\n"); } else if (x < 0) { printf("negative\n"); } else { printf("zero\n"); }
// condition ? value_if_true : value_if_false int max = (a > b) ? a : b; int x = 5; int y = (x > 3) ? 10 : 20; // 5 > 3 is true → y = 10 printf((n == 1) ? "one" : "other");
switch (a) { case 0: printf("zero\n"); break; // REQUIRED to stop fall-through case 5: printf("five\n"); break; case 10: // no break → falls through to next case case 11: printf("ten or eleven\n"); break; default: printf("other\n"); }
break, execution continues into the next case. This is usually a bug — always add break unless you intentionally want fall-through.for, while, do-while — with tracing examples, break & continue
// ┌─ init ──┐ ┌── condition ──┐ ┌─ update ─┐ for (int i = 0; i < 5; i++) { printf("%d ", i); } // Output: 0 1 2 3 4 // init runs once; condition checked before each iteration; // update runs after each iteration // Count DOWN: for (int i = 20; i >= 2; i -= 2) { printf("%d ", i); } // Output: 20 18 16 14 12 10 8 6 4 2 // for (int i = 1; i < 100; ++i) // runs for i = 1, 2, 3, ... 99 (NOT 0, NOT 100)
// Checks condition FIRST // May execute 0 times int i = 1; while (i <= 3) { printf("%d\n", i); i++; } // i=1 → prints 1, i becomes 2 // i=2 → prints 2, i becomes 3 // i=3 → prints 3, i becomes 4 // i=4, 4 <= 3 false → STOP // Output: 1 2 3
// Executes body FIRST, then checks // ALWAYS runs at least once int i = 1, sum = 0; do { sum += i; i++; } while (i <= 3); // i=1: sum=1, i→2, check 2≤3 ✓ // i=2: sum=3, i→3, check 3≤3 ✓ // i=3: sum=6, i→4, check 4≤3 ✗ STOP // Output: sum = 6
// break — exits the INNERMOST loop immediately for (int i = 0; i < 10; i++) { if (i == 5) break; printf("%d ", i); } // Output: 0 1 2 3 4 (stops at 5, never prints 5) // continue — skips REST of current iteration, goes to next for (int i = 0; i < 6; i++) { if (i % 2 == 0) continue; // skip even printf("%d ", i); } // Output: 1 3 5 // break in NESTED loops — only exits the INNERMOST loop for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (j == 1) break; // exits inner loop only printf("%d,%d ", i, j); } // outer loop continues normally } // Output: 0,0 1,0 2,0
| Use | When |
|---|---|
for | You know the number of iterations in advance |
while | Repeat until a condition changes; may need 0 iterations |
do-while | Body must run at least once (e.g. menu that shows before first input) |
// Outer loop runs N times. // For EACH outer iteration, inner loop runs M times fully. // Total iterations = N × M for (int i = 1; i <= 3; i++) { // outer: runs 3 times for (int j = 1; j <= 4; j++) { // inner: runs 4 times per outer printf("(%d,%d) ", i, j); } printf("\n"); // newline after each row } // (1,1) (1,2) (1,3) (1,4) // (2,1) (2,2) (2,3) (2,4) // (3,1) (3,2) (3,3) (3,4) // Total: 3×4 = 12 prints
#include <stdio.h> int main(void) { for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 5; j++) { printf("%4d", i * j); // %4d = right-align in 4-char field } printf("\n"); } } // 1 2 3 4 5 // 2 4 6 8 10 // 3 6 9 12 15 // 4 8 12 16 20 // 5 10 15 20 25
j resets to 1 every time outer loop advances i.// ── Right triangle (row i prints i stars) ── for (int i = 1; i <= 5; i++) { for (int j = 1; j <= i; j++) // inner limit = i (grows!) printf("* "); printf("\n"); } // * // * * // * * * // * * * * // * * * * * // ── Upside-down triangle (row i prints 5-i+1 stars) ── for (int i = 5; i >= 1; i--) { for (int j = 1; j <= i; j++) printf("* "); printf("\n"); } // * * * * * // * * * * // * * * // * * // * // ── Number triangle ── for (int i = 1; i <= 4; i++) { for (int j = 1; j <= i; j++) printf("%d ", j); printf("\n"); } // 1 // 1 2 // 1 2 3 // 1 2 3 4
i (the outer variable), the shape grows or shrinks per row.#include <stdio.h> int main(void) { int grid[3][4]; /* Fill: grid[r][c] = r*10 + c */ for (int r = 0; r < 3; r++) for (int c = 0; c < 4; c++) grid[r][c] = r * 10 + c; /* Print row by row */ for (int r = 0; r < 3; r++) { for (int c = 0; c < 4; c++) printf("%4d", grid[r][c]); printf("\n"); } } // 0 1 2 3 // 10 11 12 13 // 20 21 22 23 /* Sum all elements with nested loops */ int sum = 0; for (int r = 0; r < 3; r++) for (int c = 0; c < 4; c++) sum += grid[r][c]; // sum = 0+1+2+3 + 10+11+12+13 + 20+21+22+23 = 138
// ── Find every pair (i,j) that sums to a target ── int nums[] = {1, 4, 3, 2}; int target = 5; for (int i = 0; i < 4; i++) { for (int j = i + 1; j < 4; j++) { // j starts at i+1 — no repeats if (nums[i] + nums[j] == target) printf("(%d, %d)\n", nums[i], nums[j]); } } // (1, 4) // (3, 2) // ── Print only UPPER triangle of a grid (i ≤ j) ── for (int i = 1; i <= 4; i++) { for (int j = 1; j <= 4; j++) { if (j < i) printf(" "); // blank space for lower triangle else printf("%4d", i*j); } printf("\n"); } // 1 2 3 4 // 4 6 8 // 9 12 // 16
// What does this print? Trace step by step. int count = 0; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= i; j++) { count++; } } printf("%d\n", count);
// What does this print? for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == j) printf("%d ", i); } } // Only prints when row == col (the diagonal) // Output: 0 1 2
Prototypes, pass-by-value, void, static, scope — with many examples
// 1. PROTOTYPE (declaration) — tells compiler the signature // Return type, name, parameter types. Names are optional. double mySqrt(int x); // prototype at top of file void greet(void); // void param = NO arguments int add(int, int); // parameter names optional in prototype // 2. DEFINITION — actual implementation double mySqrt(int x) { return x * x; // return type must match prototype } void greet(void) { printf("Hello!\n"); return; // bare return OK in void function } // (or just fall off the end) // 3. CALL double result = mySqrt(5); greet();
int foo(); is valid).// The function gets a COPY — changing it does NOT affect the original void addTen(int n) { n = n + 10; // only changes the local copy } int main() { int x = 5; addTen(x); printf("%d\n", x); // still 5! addTen had no effect on x } // To modify the original, pass a POINTER: void addTenPtr(int *n) { *n = *n + 10; // dereference to modify original } addTenPtr(&x); printf("%d\n", x); // now 15
int show() { printf("3"); return 5; // function exits HERE printf("4"); // NEVER reached — dead code after return } int main() { int a = show(); // show() prints "3", returns 5 printf("%d", a); // prints 5 } // Total output: 35
void counter() { static int count = 0; // initialized ONCE, then remembered count++; printf("%d\n", count); } counter(); // prints 1 counter(); // prints 2 counter(); // prints 3 // Regular local: created fresh each call, destroyed on return // Static local: created once, lives for the entire program
int globalVar = 100; // global — accessible from any function void funcA() { int local = 5; // local — only exists inside funcA printf("%d %d", local, globalVar); } void funcB() { // local from funcA is NOT accessible here printf("%d", globalVar); // global IS accessible }
void foo(void); // C: explicitly NO parameters void foo(); // C: unspecified parameter list (old style — avoid) // In C++, both mean the same thing. // In C, foo() means "I haven't told you what parameters it takes".
#include <stdio.h> // Prototypes int add(int a, int b); float average(int *arr, int n); void printArray(int *arr, int n); int main(void) { int nums[] = {10, 20, 30, 40}; printArray(nums, 4); printf("Avg: %.1f\n", average(nums, 4)); printf("Sum first two: %d\n", add(nums[0], nums[1])); return 0; } int add(int a, int b) { return a + b; } float average(int *arr, int n) { int sum = 0; for (int i = 0; i < n; i++) sum += arr[i]; return (float)sum / n; } void printArray(int *arr, int n) { for (int i = 0; i < n; i++) printf("%d ", arr[i]); printf("\n"); }
Declaration, initialization, access, sizeof, 2D arrays
int arr[5]; // uninitialized (garbage values) int arr[5] = {1, 2, 3, 4, 5}; // fully initialized int arr[5] = {1, 2}; // rest = 0 → {1,2,0,0,0} int arr[5] = {0}; // all zeros → {0,0,0,0,0} int arr[] = {10, 20, 30}; // size inferred: 3 elements // Access — 0-indexed! arr[0] = 100; // first element arr[4] = 500; // last element of arr[5] // arr[5] is OUT OF BOUNDS — undefined behavior!
0. This is guaranteed by the C standard.char str[10] = "hello"; sizeof(str) // → 10 (total allocated bytes — always fixed) strlen(str) // → 5 (characters before \0 — the string length) int nums[5] = {1,2,3,4,5}; sizeof(nums) // → 20 (5 ints × 4 bytes each) sizeof(nums) / sizeof(int) // → 5 (number of elements)
// Divide total byte-size by size of one element #define LEN(arr) (sizeof(arr) / sizeof((arr)[0])) int nums[] = {10, 20, 30, 40, 50}; int n = LEN(nums); // → 5 (works for any type) // Equivalent to: sizeof(nums) / sizeof(int) → 20/4 = 5 // Safe loop — no magic number: for (int i = 0; i < LEN(nums); i++) printf("%d ", nums[i]);
sizeof returns the pointer size (4 or 8 bytes), not the array size. Always pass n as a separate parameter.int grid[3][4]; // 3 rows, 4 columns = 12 total elements int grid[3][4] = { {1, 2, 3, 4}, // row 0 {5, 6, 7, 8}, // row 1 {9, 10, 11, 12} // row 2 }; grid[0][0] // → 1 (row 0, col 0) grid[2][3] // → 12 (row 2, col 3) // Iterate with nested loops: for (int r = 0; r < 3; r++) for (int c = 0; c < 4; c++) printf("%d ", grid[r][c]);
& address-of, * dereference, arithmetic, const, arrays and pointers
int x = 42; int *p = &x; // p holds the ADDRESS of x (& = address-of) printf("%d\n", x); // 42 — the value printf("%p\n", p); // 0x... — the address stored in p printf("%d\n", *p); // 42 — dereference: value AT the address *p = 100; // dereference to WRITE: changes x to 100 printf("%d\n", x); // 100 // & = "address of" (use to create a pointer to something) // * = "dereference" (use to access what a pointer points to)
int arr[] = {10, 20, 30, 40}; int *p = arr; // array name decays to &arr[0] // These are ALL equivalent: arr[2] // → 30 *(arr + 2) // → 30 (arr[i] == *(arr+i)) p[2] // → 30 *(p + 2) // → 30 // Stepping through with pointer arithmetic: for (int i = 0; i < 4; i++) printf("%d ", *(p + i)); // Output: 10 20 30 40 // p+2 gives the ADDRESS of arr[2] // *(p+2) gives the VALUE at arr[2] = 30
// Read right-to-left to decode: const int *p = &x; // pointer to const int // CAN change where p points // CANNOT change *p (the value) *p = 5; // ERROR — value is read-only through p p = &y; // OK — p can point elsewhere int * const p = &x; // const pointer to int // CANNOT change where p points // CAN change *p (the value) *p = 5; // OK p = &y; // ERROR — pointer is locked
const modifies whatever is immediately to its right. const int *p → const applies to int (value is locked). int * const p → const applies to p (pointer is locked).int *p; double x = 3.14; p = &x; // ERROR: assigning double* to int* // p would misread x's bytes as an int // Always match pointer type to variable type
char arrays, null terminator, strlen, char[] vs char*
// A string is a char array ending in '\0' (null terminator) char str[] = "hello"; // Memory layout: ['h']['e']['l']['l']['o']['\0'] // 0 1 2 3 4 5 // sizeof(str) = 6 (6 bytes including \0) // strlen(str) = 5 (5 characters NOT counting \0) // Manual construction: char str[6]; str[0] = 'h'; str[1] = 'i'; str[2] = '\0'; printf("%s\n", str); // "hi"
char arr[] = "hello"; // COPIES literal into stack array → MODIFIABLE arr[0] = 'H'; // OK — arr is a local copy char *p = "hello"; // POINTS to read-only string literal → DO NOT MODIFY *p = 'H'; // UNDEFINED BEHAVIOR — usually crashes (segfault) // Passing strings to functions — use char* parameter: void printStr(char *str) { // correct: char* not char printf("%s\n", str); } void printStr(char str) { // WRONG: single char, not string printf("%s\n", str); // bug — line A in quiz Q4 }
#include <string.h> when using strlen, strcmp, strcpy, etc.| Function | What it does |
|---|---|
strlen(s) | Length — NOT counting \0 |
strcpy(dest, src) | Copy src into dest (dest must be big enough) |
strncpy(dest, src, n) | Copy at most n chars (safer) |
strcat(dest, src) | Append src to end of dest |
strncat(dest, src, n) | Append at most n chars |
strcmp(a, b) | Compare: 0=equal, <0=a before b, >0=a after b |
strncmp(a, b, n) | Compare first n chars only |
strchr(s, c) | Pointer to first c in s, NULL if not found |
strstr(hay, needle) | Pointer to first substring, NULL if not found |
strcspn(s, delim) | Index of first char in delim found in s |
// ─── Use strcmp to compare strings — NEVER use == ─────────────── char a[] = "hello", b[] = "hello"; if (a == b) { } // WRONG — compares addresses if (strcmp(a, b) == 0) { } // CORRECT — compares contents // ─── Build a string with strcpy + strcat ──────────────────────── char full[100]; strcpy(full, "Hello"); strcat(full, ", World!"); printf("%s\n", full); // Hello, World! // ─── fgets leaves '\n' at end — remove it with strcspn ────────── char line[80]; fgets(line, sizeof(line), stdin); line[strcspn(line, "\n")] = '\0'; // replace first \n with \0 // strcspn returns the index of the first '\n', so we zero it out // ─── strchr — find a char in a string ─────────────────────────── char *pos = strchr("hello", 'l'); // points to first 'l' if (pos != NULL) printf("found at index %ld\n", pos - "hello"); // pointer subtraction
strcmp returns 0 for equal strings — so the condition to check equality is strcmp(a,b) == 0, NOT strcmp(a,b) (which would be truthy for UNequal strings).fopen, fclose, reading & writing, argc/argv, standard streams
| Mode | Action | File must exist? | Truncates? |
|---|---|---|---|
"r" | Read only | Yes → NULL if not | No |
"w" | Write (create/overwrite) | No — creates it | Yes |
"a" | Append (write to end) | No — creates it | No (preserves content) |
"r+" | Read + write | Yes → NULL if not | No |
"rb", "wb" | Binary read/write | same as above | same |
fopen fails, it returns NULL. Using a NULL file pointer causes a crash. Always if (fp == NULL) { ... } after opening.#include <stdio.h> int main(void) { FILE *fp; // FILE* — not int*, not FILE fp = fopen("data.txt", "r"); if (fp == NULL) { // ALWAYS check for failure printf("Error opening file\n"); return 1; } // Method 1: read line by line with fgets char line[100]; while (fgets(line, sizeof(line), fp) != NULL) { printf("%s", line); // fgets keeps the \n } // Method 2: read character by character rewind(fp); // go back to start int c; while ((c = getc(fp)) != EOF) { putc(c, stdout); } // Method 3: read formatted data int n; rewind(fp); while (fscanf(fp, "%d", &n) == 1) { printf("%d\n", n); } fclose(fp); // always close! return 0; }
FILE *fp = fopen("out.txt", "w"); // "w" creates or truncates if (fp == NULL) return 1; fprintf(fp, "Value: %d\n", 42); // like printf but to file fputs("A line of text\n", fp); // write a string putc('!', fp); // write a single char fclose(fp); // Append mode — preserves existing content: FILE *log = fopen("log.txt", "a"); fprintf(log, "New entry\n"); // added to the END fclose(log);
| Pointer | Refers to | Example use |
|---|---|---|
stdin | Keyboard input | fscanf(stdin, "%d", &x) = scanf("%d", &x) |
stdout | Screen output | fprintf(stdout, "Hi") = printf("Hi") |
stderr | Error output | fprintf(stderr, "Error!\n") |
char ch = '$'; putc(ch, stdout); // prints: $ ✓ // These are all equivalent to the above: printf("%c", ch); // ✓ correct fprintf(stdout, "%c", ch); // ✓ correct printf("$"); // ✓ correct (hardcoded) printf(ch); // ✗ WRONG — first arg must be a format // string literal, not a variable. // Also a security vulnerability!
int main(int argc, char *argv[]) { // argc = total argument count (INCLUDES program name) // argv[0] = program name ("./test") // argv[1] = first arg ("a1") // argv[2] = second arg ("b2") // argv[3] = third arg ("c3") printf("argc = %d\n", argc); for (int i = 0; i < argc; i++) printf("argv[%d] = %s\n", i, argv[i]); } // Run: ./test a1 b2 c3 // argc = 4 (4 tokens total) // argv[0] = "./test" // argv[1] = "a1" ← first argument // argv[2] = "b2" // argv[3] = "c3" // Open file named by first argument: FILE *fp = fopen(argv[1], "r"); if (fp == NULL) { fprintf(stderr, "Cannot open %s\n", argv[1]); return 1; }
scanf("%d", &x); // reads from keyboard fscanf(stdin, "%d", &x); // identical to scanf — stdin = keyboard fscanf(fp, "%d", &x); // reads from file fp // fscanf() CAN read from console — False that it "cannot get input from terminal"
Common library functions — remember to #include and link -lm for math
| Function | Returns |
|---|---|
sqrt(x) | square root |
pow(a, b) | a raised to power b |
fabs(x) | absolute value (double) |
round(x) | nearest integer (as double) |
floor(x) | round down → floor(3.9) = 3.0 |
ceil(x) | round up → ceil(3.1) = 4.0 |
llround(x) | nearest integer (as long long) |
log(x) | natural log (base e) |
log10(x) | base-10 log |
sin(x) cos(x) | trig (radians) |
| Function | Does |
|---|---|
atoi("42") | string → int |
atof("3.14") | string → double |
abs(-5) | absolute value (int) |
EXIT_SUCCESS | 0 — clean exit |
EXIT_FAILURE | 1 — error exit |
getchar() | read one char from stdin (returns int) |
putchar(c) | write one char to stdout |
puts(s) | print string + automatic \n |
sprintf(buf,fmt,...) | printf into a string buffer |
perror("msg") | print system error message |
// Float arithmetic is imprecise — can't represent 0.1 + 0.2 exactly: printf("%.17f\n", 0.1 + 0.2); // 0.30000000000000004 ! // For money: convert to integer CENTS using llround() to avoid drift double price = 3.14; long long cents = llround(price * 100.0); // 314 — exact // Math examples: printf("%.2f\n", sqrt(16.0)); // 4.00 printf("%.2f\n", pow(2.0, 8.0)); // 256.00 printf("%.2f\n", fabs(-9.5)); // 9.50 printf("%.0f\n", ceil(3.1)); // 4 printf("%.0f\n", floor(3.9)); // 3 // sprintf — build a string from formatted data char buf[50]; sprintf(buf, "Score: %d / %d", 8, 10); printf("%s\n", buf); // Score: 8 / 10
gcc options you need — especially -lm for math.h
# Basic compilation gcc file.c -o file # Recommended — C11 standard with all warnings gcc file.c -std=c11 -Wall -Wextra -o file # With math.h (sqrt, pow, fabs, etc.) — MUST add -lm gcc file.c -std=c11 -Wall -lm -o file # Multiple source files gcc main.c other.c -std=c11 -Wall -lm -o program # With debug symbols (for gdb / debugger) gcc file.c -std=c11 -Wall -g -o file
| Flag | What it does |
|---|---|
-std=c11 | Use C11 standard (allows int i in for-loop init, VLAs, etc.) |
-Wall | Enable most useful warnings |
-Wextra | Extra warnings beyond -Wall |
-lm | Link math library — required for sqrt, pow, fabs, llround, etc. |
-o name | Name the output executable |
-g | Include debug symbols (for stepping through with gdb) |
-lm. It must come AFTER the source files on the command line.Lab-style questions with full working code — loops and functions covered most thoroughly
#include <stdio.h>
int main(void) {
char name[50];
int age;
float gpa;
printf("Name: "); scanf("%s", name);
printf("Age: "); scanf("%d", &age);
printf("GPA: "); scanf("%f", &gpa);
printf("--- Summary ---\n");
printf("Student: %s\n", name);
printf("Age now: %d, in 5 years: %d\n", age, age + 5);
printf("GPA: %.2f\n", gpa);
return 0;
}
scanf needs & for int/float but NOT for char arrays. Use %.2f to print exactly 2 decimal places.3 * 3 % 6 + 4 * 5? (b) given int x=4, y=4, what does printf("%d,%d", ++x, y--) print?#include <stdio.h>
int main(void) {
/* (a) Left-to-right for *, %, * then +
3*3 = 9 → 9%6 = 3 → 4*5 = 20 → 3+20 = 23 */
printf("%d\n", 3 * 3 % 6 + 4 * 5); /* 23 */
/* (b) ++x: pre-increment — x becomes 5 BEFORE printf
y--: post-decrement — y is still 4 WHEN printed, then y becomes 3 */
int x = 4, y = 4;
printf("%d,%d\n", ++x, y--); /* 5,4 */
/* (c) Chained comparison TRAP */
int v = 2;
if (4 > v > 1) /* evaluates as (4>v)>1 = 1>1 = false! */
printf("math works\n");
if (4 > v && v > 1) /* correct way */
printf("logic works\n");
return 0;
}
#include <stdio.h>
int main(void) {
int n, sum = 0;
printf("Enter N: ");
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
sum += i; /* same as: sum = sum + i */
}
printf("Sum(1 to %d) = %d\n", n, sum);
return 0;
}
/* Trace for N=4:
i=1: sum=1
i=2: sum=3
i=3: sum=6
i=4: sum=10
i=5: 5<=4 false, loop ends. Output: 10 */
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 20; i++) {
/* check BOTH first — order matters! */
if (i % 3 == 0 && i % 5 == 0) printf("FizzBuzz\n");
else if (i % 3 == 0) printf("Fizz\n");
else if (i % 5 == 0) printf("Buzz\n");
else printf("%d\n", i);
}
return 0;
}
% 3 first and hit break/else, you'll never reach the "FizzBuzz" case for 15.#include <stdio.h>
int main(void) {
for (int row = 1; row <= 5; row++) {
for (int col = 1; col <= 5; col++) {
printf("%4d", row * col); /* %4d = right-align in 4 chars */
}
printf("\n"); /* newline after each row */
}
return 0;
}
#include <stdio.h>
int main(void) {
int n;
do {
printf("Enter a number between 1 and 10: ");
scanf("%d", &n);
if (n < 1 || n > 10)
printf("Invalid! Try again.\n");
} while (n < 1 || n > 10); /* keep looping while invalid */
printf("You entered: %d\n", n);
return 0;
}
long factorial(int n) that returns n! using a loop. Call it from main for a user-supplied n.#include <stdio.h>
long factorial(int n); /* prototype */
int main(void) {
int n;
printf("Enter n: ");
scanf("%d", &n);
printf("%d! = %ld\n", n, factorial(n));
return 0;
}
long factorial(int n) { /* definition */
long result = 1;
for (int i = 2; i <= n; i++)
result *= i; /* result = result * i */
return result;
}
/* Trace for n=5:
i=2: result=2
i=3: result=6
i=4: result=24
i=5: result=120 → returns 120 */
addTen(x) does NOT modify x. Then fix it using a pointer parameter.#include <stdio.h>
void addTen_byval(int n); /* modifies a COPY — does nothing to caller */
void addTen_ptr(int *n); /* modifies the ORIGINAL via pointer */
int main(void) {
int x = 5;
addTen_byval(x);
printf("After byval: %d\n", x); /* still 5 — x unchanged */
addTen_ptr(&x); /* pass ADDRESS of x */
printf("After ptr: %d\n", x); /* now 15 */
return 0;
}
void addTen_byval(int n) {
n = n + 10; /* only changes the local copy of n */
}
void addTen_ptr(int *n) {
*n = *n + 10; /* dereference: changes the value at the address */
}
#include <stdio.h>
void counter(void);
int main(void) {
counter();
counter();
counter();
return 0;
}
void counter(void) {
static int calls = 0; /* initialized ONCE — survives between calls */
calls++;
printf("Called %d time(s)\n", calls);
}
calls would be re-initialized to 0 on every call, always printing "Called 1 time(s)".char getGrade(int score) that returns 'A' (≥90), 'B' (≥80), 'C' (≥70), 'D' (≥60), or 'F'. Test with several scores.#include <stdio.h>
char getGrade(int score);
int main(void) {
int scores[] = {95, 82, 71, 65, 50};
int n = sizeof(scores) / sizeof(int); /* number of elements */
for (int i = 0; i < n; i++)
printf("Score %d → Grade %c\n", scores[i], getGrade(scores[i]));
return 0;
}
char getGrade(int score) {
if (score >= 90) return 'A';
else if (score >= 80) return 'B';
else if (score >= 70) return 'C';
else if (score >= 60) return 'D';
else return 'F';
}
int findMax(int *arr, int n) that returns the largest value in an integer array.#include <stdio.h>
int findMax(int *arr, int n);
int main(void) {
int arr[] = {3, 17, 5, 42, 8, 1, 99, 7};
int n = sizeof(arr) / sizeof(int); /* 8 elements */
printf("Max = %d\n", findMax(arr, n));
return 0;
}
int findMax(int *arr, int n) {
int max = arr[0]; /* start with first element */
for (int i = 1; i < n; i++)
if (arr[i] > max)
max = arr[i];
return max;
}
void reverse(int *arr, int n) that reverses the array in-place using only pointer arithmetic (two-pointer technique). Print the array before and after.#include <stdio.h>
void reverse(int *arr, int n);
void printArray(int *arr, int n);
int main(void) {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(int);
printf("Before: "); printArray(arr, n);
reverse(arr, n);
printf("After: "); printArray(arr, n);
return 0;
}
void reverse(int *arr, int n) {
int *left = arr; /* pointer to first element */
int *right = arr + n - 1; /* pointer to last element */
while (left < right) {
int temp = *left; /* swap values at left and right */
*left = *right;
*right = temp;
left++; /* move pointers inward */
right--;
}
}
void printArray(int *arr, int n) {
for (int i = 0; i < n; i++)
printf("%d ", *(arr + i)); /* pointer arithmetic: same as arr[i] */
printf("\n");
}
arr[i] and *(arr+i) are identical. Two-pointer swap: start one pointer at the left end and one at the right, swap and move inward until they meet.void swap(int *a, int *b) function that swaps two integers. Demonstrate that the values in main() are actually changed.#include <stdio.h>
void swap(int *a, int *b);
int main(void) {
int x = 10, y = 20;
printf("Before: x=%d, y=%d\n", x, y);
swap(&x, &y); /* pass ADDRESSES */
printf("After: x=%d, y=%d\n", x, y);
return 0;
}
void swap(int *a, int *b) {
int temp = *a; /* save value at a */
*a = *b; /* write value at b into a */
*b = temp; /* write saved value into b */
}
int countChar(char *str, char target) that walks through a string using pointer arithmetic and counts how many times target appears.#include <stdio.h>
int countChar(char *str, char target);
int main(void) {
char sentence[] = "hello world";
printf("'l' appears %d time(s)\n", countChar(sentence, 'l')); /* 3 */
printf("'o' appears %d time(s)\n", countChar(sentence, 'o')); /* 2 */
printf("'z' appears %d time(s)\n", countChar(sentence, 'z')); /* 0 */
return 0;
}
int countChar(char *str, char target) {
int count = 0;
while (*str != '\0') { /* walk until null terminator */
if (*str == target)
count++;
str++; /* advance pointer to next char */
}
return count;
}
float average(int *scores, int n). Print the average and how many students scored above it.#include <stdio.h>
float average(int *scores, int n);
int main(void) {
int n;
printf("How many students? ");
scanf("%d", &n);
int scores[n];
for (int i = 0; i < n; i++) {
printf("Score %d: ", i + 1);
scanf("%d", &scores[i]);
}
float avg = average(scores, n);
printf("Average: %.2f\n", avg);
int above = 0;
for (int i = 0; i < n; i++)
if (scores[i] > avg) above++;
printf("%d student(s) scored above average\n", above);
return 0;
}
float average(int *scores, int n) {
int sum = 0;
for (int i = 0; i < n; i++)
sum += scores[i];
return (float)sum / n; /* cast to float before division! */
}
sum / n would be integer division (truncates). (float)sum / n forces floating-point division.switch with fall-through case labels.#include <stdio.h>
int main(void) {
char str[100];
int a=0, e=0, i=0, o=0, u=0;
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
for (int j = 0; str[j] != '\0'; j++) {
switch (str[j]) {
case 'a': case 'A': a++; break;
case 'e': case 'E': e++; break;
case 'i': case 'I': i++; break;
case 'o': case 'O': o++; break;
case 'u': case 'U': u++; break;
/* non-vowels: no case match, nothing happens */
}
}
printf("a=%d e=%d i=%d o=%d u=%d\n", a, e, i, o, u);
return 0;
}
case labels before one break = fall-through. case 'a': case 'A': both route to the same a++. The loop condition str[j] != '\0' stops at the null terminator.#include <stdio.h>
int main(void) {
int scores[] = {85, 92, 78, 95, 88};
int n = 5;
/* --- Write --- */
FILE *fp = fopen("grades.txt", "w");
if (fp == NULL) { printf("Cannot create file\n"); return 1; }
for (int i = 0; i < n; i++)
fprintf(fp, "%d\n", scores[i]);
fclose(fp);
printf("Wrote %d scores to grades.txt\n", n);
/* --- Read back --- */
fp = fopen("grades.txt", "r");
if (fp == NULL) { printf("Cannot open file\n"); return 1; }
int total = 0, count = 0, val;
while (fscanf(fp, "%d", &val) == 1) { /* returns 1 while reading OK */
total += val;
count++;
}
fclose(fp);
printf("Average from file: %.2f\n", (float)total / count);
return 0;
}
argv[1]. Open it for reading (print error + exit if it fails). Count lines using fgets(), then print the total.#include <stdio.h>
int main(int argc, char *argv[]) {
/* argc = number of tokens including program name
argv[0] = "./counter", argv[1] = "myfile.txt" */
if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("Error: cannot open '%s'\n", argv[1]);
return 1; /* non-zero = failure */
}
int lines = 0;
char buf[256];
while (fgets(buf, sizeof(buf), fp) != NULL)
lines++;
fclose(fp);
printf("'%s' contains %d line(s)\n", argv[1], lines);
return 0;
}
/* Run: ./counter grades.txt
argv[0]="./counter", argv[1]="grades.txt", argc=2 */
getc/putc.#include <stdio.h>
int main(void) {
FILE *src = fopen("grades.txt", "r");
FILE *dest = fopen("backup.txt", "w");
if (src == NULL || dest == NULL) {
printf("File error\n");
return 1;
}
int c;
while ((c = getc(src)) != EOF) /* read one char; EOF signals end */
putc(c, dest); /* write that char to destination */
fclose(src);
fclose(dest);
printf("File copied successfully\n");
return 0;
}
getc returns an int (not char) because EOF is typically -1, which doesn't fit in a char. Always use int c.#include <stdio.h>
int main(void) {
int a = 5;
switch (a) {
case 0: printf("a"); break;
case 5: printf("b"); break; /* matches here */
case 10: printf("c"); /* no break — but never reached */
}
return 0;
}
case 5, prints "b", then break exits the switch. case 10 is never reached so its missing break doesn't matter.#include <stdio.h>
int main(void) {
int i = 1, sum = 0;
do {
sum += i;
i++;
} while (i <= 3);
printf("%d\n", sum);
return 0;
}
#include <stdio.h>
int show();
void main() {
int a;
a = show();
printf("%d", a);
}
int show() {
printf("3");
return 5;
printf("4"); /* unreachable — after return */
}
show() prints "3", then returns 5. The second printf after return is dead code — never executes. main() stores 5 in a and prints it with %d.#include <stdio.h>
void main() {
int x = 5;
if (x > 1)
printf("a");
else if (x == 5)
printf("b");
else
printf("c");
}
x > 1 is true (5 > 1), so "a" prints and the ENTIRE if-else chain exits. Even though x == 5 is also true, it's in an else if — it's only reached if all previous conditions were false.#include <stdio.h>
int main() {
int x = 4, y = 4;
printf("%d,%d\n", ++x, y--);
printf("%d,%d\n", x, y);
return 0;
}
++x increments x to 5 BEFORE use → prints 5. y-- uses y's current value 4 THEN decrements → prints 4, but y is now 3. Second printf confirms x stayed 5, y is now 3.double celsiusToFahrenheit(double c). Formula: F = C × 9/5 + 32. Read Celsius from user, print Fahrenheit.#include <stdio.h>
double celsiusToFahrenheit(double c);
int main(void) {
double c;
printf("Enter Celsius: ");
scanf("%lf", &c);
printf("%.1f C = %.1f F\n", c, celsiusToFahrenheit(c));
return 0;
}
double celsiusToFahrenheit(double c) {
return c * 9.0 / 5.0 + 32.0; /* use 9.0 not 9 to avoid int division */
}
c * 9 / 5 — if c is int this truncates. Use 9.0 / 5.0 or cast.double area(double r) and double perimeter(double r) for a circle. Use #define PI 3.14159.#include <stdio.h>
#define PI 3.14159
double area(double r);
double perimeter(double r);
int main(void) {
double r;
printf("Radius: ");
scanf("%lf", &r);
printf("Area: %.2f\n", area(r));
printf("Perimeter: %.2f\n", perimeter(r));
return 0;
}
double area(double r) { return PI * r * r; }
double perimeter(double r) { return 2 * PI * r; }
#define PI 3.14159 at the top makes PI available everywhere — no need to pass it as a parameter.double power(double base, int exp) that computes baseexp using a loop (handles exp ≥ 0). Test with several pairs.#include <stdio.h>
double power(double base, int exp);
int main(void) {
printf("2^10 = %.0f\n", power(2, 10)); /* 1024 */
printf("3^4 = %.0f\n", power(3, 4)); /* 81 */
printf("5^0 = %.0f\n", power(5, 0)); /* 1 */
return 0;
}
double power(double base, int exp) {
double result = 1.0;
for (int i = 0; i < exp; i++)
result *= base; /* multiply by base exp times */
return result;
}
int maxOf(int a, int b) and int minOf(int a, int b). Read two integers and print both results.#include <stdio.h>
int maxOf(int a, int b);
int minOf(int a, int b);
int main(void) {
int x, y;
printf("Enter two integers: ");
scanf("%d %d", &x, &y);
printf("Max: %d\n", maxOf(x, y));
printf("Min: %d\n", minOf(x, y));
return 0;
}
int maxOf(int a, int b) { return (a > b) ? a : b; }
int minOf(int a, int b) { return (a < b) ? a : b; }
(condition) ? value_if_true : value_if_false — a compact single-expression if/else.int absVal(int n) and int isEven(int n) (returns 1 if even, 0 if odd). Test both.#include <stdio.h>
int absVal(int n);
int isEven(int n);
int main(void) {
int x;
printf("Enter an integer: ");
scanf("%d", &x);
printf("Absolute value: %d\n", absVal(x));
printf("%d is %s\n", x, isEven(x) ? "even" : "odd");
return 0;
}
int absVal(int n) { return (n < 0) ? -n : n; }
int isEven(int n) { return (n % 2 == 0) ? 1 : 0; }
int sumDigits(int n) that returns the sum of all digits. E.g. 1234 → 1+2+3+4 = 10. Use modulo and division.#include <stdio.h>
int sumDigits(int n);
int main(void) {
int n;
printf("Enter a positive integer: ");
scanf("%d", &n);
printf("Sum of digits of %d = %d\n", n, sumDigits(n));
return 0;
}
int sumDigits(int n) {
int sum = 0;
while (n > 0) {
sum += n % 10; /* last digit */
n /= 10; /* remove last digit */
}
return sum;
}
n % 10 extracts the rightmost digit. n /= 10 (integer division) chops it off. Repeat until n = 0.double simpleInterest(double p, double r, int t) → SI = P × R × T / 100. Read P, R, T and print the interest and total amount.#include <stdio.h>
double simpleInterest(double p, double r, int t);
int main(void) {
double p, r;
int t;
printf("Principal: "); scanf("%lf", &p);
printf("Rate (%%): "); scanf("%lf", &r);
printf("Time (yrs):"); scanf("%d", &t);
double si = simpleInterest(p, r, t);
printf("Interest: $%.2f\n", si);
printf("Total: $%.2f\n", p + si);
return 0;
}
double simpleInterest(double p, double r, int t) {
return (p * r * t) / 100.0;
}
int isPrime(int n) that returns 1 if n is prime, 0 otherwise. Print all primes from 2 to 50.#include <stdio.h>
int isPrime(int n);
int main(void) {
printf("Primes 2-50: ");
for (int i = 2; i <= 50; i++)
if (isPrime(i))
printf("%d ", i);
printf("\n");
return 0;
}
int isPrime(int n) {
if (n < 2) return 0;
for (int i = 2; i * i <= n; i++) /* only need to check up to sqrt(n) */
if (n % i == 0) return 0; /* found a factor — not prime */
return 1;
}
i * i <= n). If n has a factor larger than √n, the corresponding smaller factor would already have been found./* 1. Prototype — goes above main */ returnType functionName(paramType param1, paramType param2); int main(void) { returnType result = functionName(arg1, arg2); printf("Result: ...", result); return 0; } /* 2. Definition — goes after main */ returnType functionName(paramType param1, paramType param2) { /* ... your logic ... */ return someValue; }
returnType with int, double, char, etc. Replace paramType with the type of each input.void functionName(paramType param); int main(void) { functionName(arg); /* no assignment — void returns nothing */ return 0; } void functionName(paramType param) { /* do stuff — print, modify local things, etc. */ /* no return statement needed (or just: return;) */ }
main(). Pass its address with &.void doubleIt(int *n); /* * in prototype = pointer parameter */ int main(void) { int x = 5; doubleIt(&x); /* & sends the ADDRESS of x */ printf("%d\n", x); /* x is now 10 */ return 0; } void doubleIt(int *n) { *n = *n * 2; /* * dereferences: changes the value AT that address */ }
*n. To WRITE through it: *n = .... To pass an address from main: &variable.& needed.void processArray(int *arr, int n); /* or int arr[] — identical */ int main(void) { int data[] = {10, 20, 30}; int n = sizeof(data) / sizeof(int); /* number of elements */ processArray(data, n); /* no & — array name is already an address */ return 0; } void processArray(int *arr, int n) { for (int i = 0; i < n; i++) { /* arr[i] accesses each element */ } }
/* Sum */ int sum = 0; for (int i = 0; i < n; i++) sum += arr[i]; /* Product */ long product = 1; /* start at 1, not 0! */ for (int i = 1; i <= n; i++) product *= i; /* Count (how many satisfy a condition) */ int count = 0; for (int i = 0; i < n; i++) if (arr[i] > threshold) count++; /* Running max */ int max = arr[0]; /* initialize to FIRST element */ for (int i = 1; i < n; i++) if (arr[i] > max) max = arr[i];
0. Initialize product/max/min to sensible starting values (1, first element). Start loop at correct index.#include <stdio.h> int main(void) { int n; printf("How many values? "); scanf("%d", &n); int arr[n]; /* VLA — valid in C99+ */ for (int i = 0; i < n; i++) { printf("Value %d: ", i + 1); scanf("%d", &arr[i]); } /* --- process --- */ int sum = 0; for (int i = 0; i < n; i++) sum += arr[i]; printf("Sum: %d\n", sum); printf("Avg: %.2f\n", (float)sum / n); return 0; }