C Programming Techniques and Algorithmic Challenges
Return Statement Behavior
- A return statement may contain a numeric value or an expression. Expressions are evaluated before returning:
int sum(int x, int y) {
return x + y;
}
// Usage example
switch (op) {
case 1:
scanf("%d %d", &a, &b);
result = sum(a, b);
printf("Result: %d\n", result);
break;
}
-
For void functions, use bare
return;without values. -
Mismatched return types undergo implicit conversion to match the declared function type.
-
Execution immediately exits the function upon enocuntering return.
-
All conditional branches must contain a return path:
if (row_valid && col_valid) {
if (grid[cell] == EMPTY) {
return;
} else if (count_adjacent(grid, cell) != 0) {
grid[cell] = count_adjacent(grid, cell) + '0';
return;
}
}
Assertion Macros
The assert macro validates conditions during runtime:
#include <assert.h>
assert(condition);
Failing assertions terminate execution with diagnostic messages. Example:
#include <stdio.h>
#include <assert.h>
void process(int val) {
assert(val > 0);
// Processing logic
}
int main() {
process(5); // Valid
process(-1); // Triggers assertion
return 0;
}
Disable assertions in production by defining NDEBUG:
#define NDEBUG
#include <assert.h>
Trade-offs: Adds runtime overhead but aids debugging.
String Rotation Verification
Determine if string B is a rotation of string A.
Solution 1: Character Shifting
void rotate_chars(char* s, int shifts) {
int len = strlen(s);
shifts %= len;
for (int i = 0; i < shifts; i++) {
char first = s[0];
for (int j = 0; j < len - 1; j++)
s[j] = s[j+1];
s[len-1] = first;
}
}
Solution 2: Substring Manipulation
void rotate_buffer(char* s, int shifts) {
int len = strlen(s);
shifts %= len;
char buffer[256];
strcpy(buffer, s + shifts);
strncat(buffer, s, shifts);
strcpy(s, buffer);
}
Solution 3: Triple Reversal
void reverse_segment(char* s, int start, int end) {
while (start < end) {
char tmp = s[start];
s[start++] = s[end];
s[end--] = tmp;
}
}
void rotate_reverse(char* s, int shifts) {
int len = strlen(s);
shifts %= len;
reverse_segment(s, 0, shifts-1);
reverse_segment(s, shifts, len-1);
reverse_segment(s, 0, len-1);
}
Array Partitioning: Odds Before Evens
Algorithm:
- Initialize pointers at array boundaries
- Find first even from left, first odd from right
- Swap elements when both found
- Repeat until pointers meet
Implementation:
void partition_odds_evens(int* nums, int length) {
int left = 0, right = length - 1;
while (left < right) {
while (left < right && nums[left] % 2 == 1) left++;
while (left < right && nums[right] % 2 == 0) right--;
if (left < right) {
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
}
}
}
Pointer-Based Array Printing
#include <stdio.h>
int main() {
int numbers[] = {1,2,3,4,5};
int* ptr = numbers;
for (int i = 0; i < sizeof(numbers)/sizeof(int); i++) {
printf("%d ", *ptr++);
}
return 0;
}
Bubble Sort Optimization
Basic implementation:
void bubble_sort(int* arr, int size) {
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - 1 - i; j++) {
if (arr[j] > arr[j+1]) {
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
Optimized version with early termination:
void optimized_bubble_sort(int* arr, int size) {
for (int i = 0; i < size - 1; i++) {
int swapped = 0;
for (int j = 0; j < size - 1 - i; j++) {
if (arr[j] > arr[j+1]) {
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
swapped = 1;
}
}
if (!swapped) break;
}
}
Matrix Search in Sorted Grid
Search target in row/column-sorted matrix:
int search_sorted_matrix(int** grid, int rows, int cols, int target) {
int r = 0, c = cols - 1;
while (r < rows && c >= 0) {
if (grid[r][c] < target) r++;
else if (grid[r][c] > target) c--;
else return 1;
}
return 0;
}
Logic Puzzle: Identifying the Murderer
Four suspects with statements:
- A: "Not me"
- B: "C did it"
- C: "D did it"
- D: "C lied"
Exactly one liar exists. Solution:
#include <stdio.h>
int main() {
for (char suspect = 'A'; suspect <= 'D'; suspect++) {
int truth_count = (suspect != 'A') +
(suspect == 'C') +
(suspect == 'D') +
(suspect != 'D');
if (truth_count == 3) {
printf("Culprit: %c\n", suspect);
}
}
return 0;
}
Pascal's Triangle Generation
Standard approach:
void generate_pascal(int levels) {
int triangle[30][30] = {{1}};
for (int i = 1; i < levels; i++) {
triangle[i][0] = 1;
for (int j = 1; j <= i; j++) {
triangle[i][j] = triangle[i-1][j] + triangle[i-1][j-1];
}
}
// Output logic here
}
Space-optimized version:
void generate_pascal_optimized(int levels) {
int row[30] = {1};
printf("1\n");
for (int i = 1; i < levels; i++) {
for (int j = i; j > 0; j--)
row[j] += row[j-1];
// Output current row
}
}