From fd63d57e22c5aa445860624e8000958510925af0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 15 Aug 2024 15:20:37 -0500 Subject: [PATCH 1/4] reset work --- .../01_welcome/README.md | 13 +++ .../01_welcome/hello_world.c | 44 ++++++++ .../02_variables/README.md | 1 + .../02_variables/variables_01.c | 15 +++ .../02_variables/variables_02.c | 27 +++++ .../02_variables/variables_03.c | 24 +++++ .../03_for_statement/README.md | 1 + .../03_for_statement/for_statement_01.c | 66 ++++++++++++ .../03_for_statement/for_statement_02.c | 46 ++++++++ .../04_symbolic_constants/README.md | 2 + .../symbolic_constants_01.c | 41 +++++++ .../15_variable_names/README.md | 1 + .../15_variable_names/variable_names_01.c | 21 ++++ .../16_data_types/README.md | 3 + .../16_data_types/data_type_01.c | 48 +++++++++ .../17_constants/README.md | 3 + .../17_constants/constants_1.c | 40 +++++++ .../17_constants/constants_2.c | 45 ++++++++ .../17_constants/constants_3.c | 27 +++++ .../18_declarations/README.md | 3 + .../18_declarations/declarations_01.c | 34 ++++++ .../19_arithmetic_operators/README.md | 3 + .../arithmetic_operators_02.c | 26 +++++ .../arithmetic_operatos_01.c | 33 ++++++ .../20_relational_logical_operators/README.md | 3 + .../relational_logical_operators_01.c | 34 ++++++ .../relational_logical_operators_02.c | 28 +++++ .../21_type_conversions/README.md | 3 + .../21_type_conversions/type_conversions_01.c | 39 +++++++ .../21_type_conversions/type_conversions_02.c | 51 +++++++++ .../22_inc_dec_operators/README.md | 3 + .../inc_dec_operators_01.c | 40 +++++++ .../23_bitwise_operators/README.md | 3 + .../bitwise_operators_01.c | 45 ++++++++ .../bitwise_operators_02.c | 44 ++++++++ .../bitwise_operators_03.c | 44 ++++++++ .../bitwise_operators_04.c | 46 ++++++++ .../bitwise_operators_05.c | 61 +++++++++++ .../24_assignment_operators/README.md | 3 + .../assignment_operators_01.c | 28 +++++ .../25_conditional_expressions/README.md | 3 + .../conditional_expressions_01.c | 44 ++++++++ .../26_operator_precedence/README.md | 3 + .../operator_precedence_01.c | 102 ++++++++++++++++++ .../27_statements_and_blocks/README.md | 3 + .../statements_and_blocks_01.c | 32 ++++++ .../35_functions_basics/README.md | 3 + .../35_functions_basics/functions_basics_01.c | 43 ++++++++ .../36_non_integer_functions/README.md | 3 + .../non_integer_functions_01.c | 69 ++++++++++++ .../37_external_variables/README.md | 3 + .../external_variables.c | 57 ++++++++++ reset_directory | Bin 0 -> 17552 bytes reset_directory.c | 91 ++++++++++++++++ 54 files changed, 1498 insertions(+) create mode 100644 master_exercises_read_only/01_welcome/README.md create mode 100644 master_exercises_read_only/01_welcome/hello_world.c create mode 100644 master_exercises_read_only/02_variables/README.md create mode 100644 master_exercises_read_only/02_variables/variables_01.c create mode 100644 master_exercises_read_only/02_variables/variables_02.c create mode 100644 master_exercises_read_only/02_variables/variables_03.c create mode 100644 master_exercises_read_only/03_for_statement/README.md create mode 100644 master_exercises_read_only/03_for_statement/for_statement_01.c create mode 100644 master_exercises_read_only/03_for_statement/for_statement_02.c create mode 100644 master_exercises_read_only/04_symbolic_constants/README.md create mode 100644 master_exercises_read_only/04_symbolic_constants/symbolic_constants_01.c create mode 100644 master_exercises_read_only/15_variable_names/README.md create mode 100644 master_exercises_read_only/15_variable_names/variable_names_01.c create mode 100644 master_exercises_read_only/16_data_types/README.md create mode 100644 master_exercises_read_only/16_data_types/data_type_01.c create mode 100644 master_exercises_read_only/17_constants/README.md create mode 100644 master_exercises_read_only/17_constants/constants_1.c create mode 100644 master_exercises_read_only/17_constants/constants_2.c create mode 100644 master_exercises_read_only/17_constants/constants_3.c create mode 100644 master_exercises_read_only/18_declarations/README.md create mode 100644 master_exercises_read_only/18_declarations/declarations_01.c create mode 100644 master_exercises_read_only/19_arithmetic_operators/README.md create mode 100644 master_exercises_read_only/19_arithmetic_operators/arithmetic_operators_02.c create mode 100644 master_exercises_read_only/19_arithmetic_operators/arithmetic_operatos_01.c create mode 100644 master_exercises_read_only/20_relational_logical_operators/README.md create mode 100644 master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_01.c create mode 100644 master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_02.c create mode 100644 master_exercises_read_only/21_type_conversions/README.md create mode 100644 master_exercises_read_only/21_type_conversions/type_conversions_01.c create mode 100644 master_exercises_read_only/21_type_conversions/type_conversions_02.c create mode 100644 master_exercises_read_only/22_inc_dec_operators/README.md create mode 100644 master_exercises_read_only/22_inc_dec_operators/inc_dec_operators_01.c create mode 100644 master_exercises_read_only/23_bitwise_operators/README.md create mode 100644 master_exercises_read_only/23_bitwise_operators/bitwise_operators_01.c create mode 100644 master_exercises_read_only/23_bitwise_operators/bitwise_operators_02.c create mode 100644 master_exercises_read_only/23_bitwise_operators/bitwise_operators_03.c create mode 100644 master_exercises_read_only/23_bitwise_operators/bitwise_operators_04.c create mode 100644 master_exercises_read_only/23_bitwise_operators/bitwise_operators_05.c create mode 100644 master_exercises_read_only/24_assignment_operators/README.md create mode 100644 master_exercises_read_only/24_assignment_operators/assignment_operators_01.c create mode 100644 master_exercises_read_only/25_conditional_expressions/README.md create mode 100644 master_exercises_read_only/25_conditional_expressions/conditional_expressions_01.c create mode 100644 master_exercises_read_only/26_operator_precedence/README.md create mode 100644 master_exercises_read_only/26_operator_precedence/operator_precedence_01.c create mode 100644 master_exercises_read_only/27_statements_and_blocks/README.md create mode 100644 master_exercises_read_only/27_statements_and_blocks/statements_and_blocks_01.c create mode 100644 master_exercises_read_only/35_functions_basics/README.md create mode 100644 master_exercises_read_only/35_functions_basics/functions_basics_01.c create mode 100644 master_exercises_read_only/36_non_integer_functions/README.md create mode 100644 master_exercises_read_only/36_non_integer_functions/non_integer_functions_01.c create mode 100644 master_exercises_read_only/37_external_variables/README.md create mode 100644 master_exercises_read_only/37_external_variables/external_variables.c create mode 100644 reset_directory create mode 100644 reset_directory.c diff --git a/master_exercises_read_only/01_welcome/README.md b/master_exercises_read_only/01_welcome/README.md new file mode 100644 index 0000000..f862a4a --- /dev/null +++ b/master_exercises_read_only/01_welcome/README.md @@ -0,0 +1,13 @@ +Welcome to clings! + +clings is an interactive course to help you learn C entirely through the terminal and your text editor. + +Each exercise will due to 1 or both of the following reasons: +1. A compilation error +2. A runtime error + +For each exercise, your mission is simple: fix the errors you encounter. + +Once all errors have been fixed, the program will automatically move you to the next exercise. + +Good luck and have fun! diff --git a/master_exercises_read_only/01_welcome/hello_world.c b/master_exercises_read_only/01_welcome/hello_world.c new file mode 100644 index 0000000..596cf49 --- /dev/null +++ b/master_exercises_read_only/01_welcome/hello_world.c @@ -0,0 +1,44 @@ +// Welcome to clings! +// This first exercise is just to show you how things work. +// +// There are two ways an exercise could be failing: +// 1. Compilation Error +// 2. Runtime Error +// +// Your goal is to complete an exercise and get it to both compile and also to run with no errors +// while following the directions of the exercise. +// +// Once there are no errors and you're ready to move on, delete the "I AM NOT DONE" line. + + +// ❌ I AM NOT DONE + + +#include + +int main() +{ + char msg[] = "\033[1;32m" + " _ _ \n" + " | (_) \n" + " ___| |_ _ __ __ _ ___ \n" + " / __| | | '_ \\ / _` / __|\n" + "| (__| | | | | | (_| \\__ \\\n" + " \\___|_|_|_| |_|\\__, |___/\n" + " __/ | \n" + " |___/ \n" + "\033[0m"; + + printf("%s\n", msg); + + // Missing something here? What does the compiler say? + printf("Welcome to clings! \n") + + // This is a segmentation fault + // It's added to demonstrate a runtime failure + // For now, just delete these lines to see a successful exercise completion + int *ptr = NULL; + *ptr = 42; + + return 0; +} diff --git a/master_exercises_read_only/02_variables/README.md b/master_exercises_read_only/02_variables/README.md new file mode 100644 index 0000000..64f970c --- /dev/null +++ b/master_exercises_read_only/02_variables/README.md @@ -0,0 +1 @@ +For more information please refer to Chapter 1.2 of "The C Programming Language". diff --git a/master_exercises_read_only/02_variables/variables_01.c b/master_exercises_read_only/02_variables/variables_01.c new file mode 100644 index 0000000..6a4b2fe --- /dev/null +++ b/master_exercises_read_only/02_variables/variables_01.c @@ -0,0 +1,15 @@ +/* + * Variables in C must be declared before they are used. Typically you will see them declared at the top of a function. + * + * Take a look at the program below and figure out what primitive datatype each variable should be and assign them accordingly. +*/ + +// ❌ I AM NOT DONE + +int main() { + x = 10; + y = 1.0; + z = 'A'; + + return 0; +} diff --git a/master_exercises_read_only/02_variables/variables_02.c b/master_exercises_read_only/02_variables/variables_02.c new file mode 100644 index 0000000..736e117 --- /dev/null +++ b/master_exercises_read_only/02_variables/variables_02.c @@ -0,0 +1,27 @@ +/* + * Arithmetic in C is pretty straightforward, though there are some gotchas. + * + * If you use integers for division for example, you may lose precision in the output. + * + * The program below is using integers and is thus failing the assertion for a certain level of precision. + * + * Make changes to the program so that precision is not lost. +*/ + +// ❌ I AM NOT DONE + + +#include +#include + +#define EPSILON 0.000001 + +int main() { + int x = 100.0; + int y = 9.0; + int z = x / y; + + // DO NOT CHANGE THIS + assert(fabs(z - 11.111111) < EPSILON); + return 0; +} diff --git a/master_exercises_read_only/02_variables/variables_03.c b/master_exercises_read_only/02_variables/variables_03.c new file mode 100644 index 0000000..4fbae6e --- /dev/null +++ b/master_exercises_read_only/02_variables/variables_03.c @@ -0,0 +1,24 @@ +/* + * So what is a practical application of all of this? + * + * How about a program to convert from Fahrenheit to Celcius. + * + * The program below is not accurate enough, how can we fix that? +*/ + +// ❌ I AM NOT DONE + + +#include +#include + +#define EPSILON 0.000001 + +int main() { + int fahrenheit = 100; + int celcius = (5 / 9) * (fahrenheit - 32); + + // DO NOT CHANGE THIS + assert(fabs(celcius - 37.777779) < EPSILON); + return 0; +} diff --git a/master_exercises_read_only/03_for_statement/README.md b/master_exercises_read_only/03_for_statement/README.md new file mode 100644 index 0000000..efb0ef8 --- /dev/null +++ b/master_exercises_read_only/03_for_statement/README.md @@ -0,0 +1 @@ +For more information please refer to Chapter 1.3 of "The C Programming Language". diff --git a/master_exercises_read_only/03_for_statement/for_statement_01.c b/master_exercises_read_only/03_for_statement/for_statement_01.c new file mode 100644 index 0000000..bc7c452 --- /dev/null +++ b/master_exercises_read_only/03_for_statement/for_statement_01.c @@ -0,0 +1,66 @@ +/** LEARNING + * Your goal is to understand how the for statement works. + * + * The for statement has the following syntax: + * + * for (initialization; condition; increment) { + * statement; + * statement; + * ... + * } + * + * The for statement is equivalent to the following while statement: + * + * initialization; + * while (condition) { + * statement; + * statement; + * ... + * increment; + * } + */ + +/** EXERCISE + * Your job is to write a for statement equivalent to the following + * while statement: + * + * i = 0; // initialization + * while (i < 10) { // condition + * printf("%d\n", i); + * verify_count(&count, i); + * i++; // increment + * } + */ + +// ❌ I AM NOT DONE + +#include +#include +#include + +// DO NOT CHANGE THIS +static int track = 0, count = 0; + +// DO NOT CHANGE THIS +void verify_count (int *count, int i) { + assert(i == track++); + (*count)++; +} + +int main() { + int i = rand() % 100 + 11; // DO NOT CHANGE THIS + + // YOUR CODE HERE + for (initialization; condition; increment) { + // END YOUR CODE + printf("%d\n", i); + verify_count(&count, i); // DO NOT CHANGE THIS + } + + // BONUS: print the value of i here and try to understand why it's 10 + + // DO NOT CHANGE THIS + assert (count == 10); + return 0; +} + diff --git a/master_exercises_read_only/03_for_statement/for_statement_02.c b/master_exercises_read_only/03_for_statement/for_statement_02.c new file mode 100644 index 0000000..f3617e9 --- /dev/null +++ b/master_exercises_read_only/03_for_statement/for_statement_02.c @@ -0,0 +1,46 @@ +/* + * The provided program generates a table of + * temperatures in Fahrenheit and their corresponding + * Celsius equivalents, increasing in steps of 20 degrees from + * 0°F to 300°F. The Celsius temperature is calculated directly + * within the printf statement using a for loop. + * + * Modify the provided temperature conversion + * C program to print the Fahrenheit to Celsius c + * onversion table in reverse order, + * from 0 degrees Fahrenheit up to 300 degrees. +*/ + +// ❌ I AM NOT DONE + +#include +#include + +#define TRACK 320 + +static int track = 0; + +// DO NOT CHANGE THIS +void verify_count (int i) { + assert(i == track); + track += 20; +} + +int main() { + // YOUR CODE HERE + for (int fahr = 300; fahr >= 0; fahr -= 20) { + // END YOUR CODE + printf("%3d %6.1f\n", fahr, (5.0 / 9.0) * (fahr - 32)); + + verify_count(fahr); // DO NOT CHANGE THIS + } + + // BONUS: print the value of track here + // and try to understand why it's 320 + + // DO NOT CHANGE THIS + assert (track == TRACK); + + return 0; +} + diff --git a/master_exercises_read_only/04_symbolic_constants/README.md b/master_exercises_read_only/04_symbolic_constants/README.md new file mode 100644 index 0000000..fab7fc0 --- /dev/null +++ b/master_exercises_read_only/04_symbolic_constants/README.md @@ -0,0 +1,2 @@ +For more information please refer to Chapter 1.3 of "The C Programming Language". + diff --git a/master_exercises_read_only/04_symbolic_constants/symbolic_constants_01.c b/master_exercises_read_only/04_symbolic_constants/symbolic_constants_01.c new file mode 100644 index 0000000..eae49f3 --- /dev/null +++ b/master_exercises_read_only/04_symbolic_constants/symbolic_constants_01.c @@ -0,0 +1,41 @@ +/* + * In programming, hardcoding numbers directly into your code + * (often referred to as "magic numbers") can make the code less + * understandable and harder to maintain. + * + * Using symbolic constants can help alleviate these issues by + * providing meaningful names for these numbers. + * + * Below is a simple C program that prints a Fahrenheit-to-Celsius + * conversion table. The program currently uses magic numbers. + * Your task is to refactor this program to use symbolic constants. + * + * Example macro definition: + * #define PI 3.14159 + * + * Example usage: + * double circumference = 2 * PI * radius; +*/ + +// ❌ I AM NOT DONE + +#include + +// [TODO] DEFINE CONSTANTS LOWER, UPPER, AND STEP WITH APPROPRIATE VALUES. +#define LOWER // lower limit of the table +#define UPPER // upper limit of the table +#define STEP // step size between consecutive temperatures +// END OF THE CONSTANTS + +int main() { + int fahr; + + // [TODO] REPLACE THE MAGIC NUMBERS WITH THE SYMBOLIC CONSTANTS. + for (fahr = 0; fahr <= 300; fahr += 20) { + // END OF THE REPLACEMENT + printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32)); + } + + return 0; +} + diff --git a/master_exercises_read_only/15_variable_names/README.md b/master_exercises_read_only/15_variable_names/README.md new file mode 100644 index 0000000..120caa8 --- /dev/null +++ b/master_exercises_read_only/15_variable_names/README.md @@ -0,0 +1 @@ +For more information please refer to Chapter 2.1 of "The C Programming Language". diff --git a/master_exercises_read_only/15_variable_names/variable_names_01.c b/master_exercises_read_only/15_variable_names/variable_names_01.c new file mode 100644 index 0000000..b9809aa --- /dev/null +++ b/master_exercises_read_only/15_variable_names/variable_names_01.c @@ -0,0 +1,21 @@ +/* + * Variable naming seems pretty simple however there are some gotchas. + * + * The primary gotchas are: "reserved words" and "illegal characters". + * + * Take a look at the below exercise and identify the variables that are + * causing the compilation error. +*/ + +// ❌ I AM NOT DONE + +int main() { + // [TODO] Identify the variable(s) that is causing the compilation error. + char foo1 = 'a'; + float float = 1.0; + int bar = 1; + char 1baz = 'a'; + + return 0; +} + diff --git a/master_exercises_read_only/16_data_types/README.md b/master_exercises_read_only/16_data_types/README.md new file mode 100644 index 0000000..7a5da97 --- /dev/null +++ b/master_exercises_read_only/16_data_types/README.md @@ -0,0 +1,3 @@ +# Data types + +For more information please refer to Chapter 2.2 of "The C Programming Language". diff --git a/master_exercises_read_only/16_data_types/data_type_01.c b/master_exercises_read_only/16_data_types/data_type_01.c new file mode 100644 index 0000000..5f5a7c5 --- /dev/null +++ b/master_exercises_read_only/16_data_types/data_type_01.c @@ -0,0 +1,48 @@ +/* + * In this exercise, you will practice understanding data types and sizes in C. + * The basic data types in C include `char`, `int`, `float`, and `double`. + * You can also apply qualifiers like `short`, `long`, `signed`, and `unsigned` to these types, + * which affect their size and behavior. Understanding how these types and qualifiers + * work at a binary level is crucial for robust C programming. + * + * The provided file will not compile or run correctly until + * the user fixes the mistakes. + * (You can only delete/edit lines with // <-- Fix this line) +*/ + +// ❌ I AM NOT DONE + +#include +#include +#include +#include + + // Note: Carefully observe the output to understand the underlying behavior caused by type limits and conversions. + // |char| <= |short| <= |int| <= |long| <= |long long| + +int main() { + unsigned int negativeAsUnsigned = -5; // <-- Fix this kind of misuse + + long long veryLargeNumber = 9223372036854775807; + printf("Maximum long long value: %l\n", veryLargeNumber); // <-- Fix this line + + printf("Range of unsigned long long: 0 to %llu\n", ); // <-- Fix this line (use symbolic constant limits.h) + printf("Range of signed long long: %lld to %lld\n", ); // <-- Fix this line (use symbolic constant) + printf("Range of unsigned char: %d to %d\n", ); // <-- Fix this line (Write a number) + printf("Range of signed char: %d to %d\n", ); // <-- Fix this line (write a number) + + double floatingPointNumber = 0.999999; + int integerRepresentation = floatingPointButNotReally; // <-- Fix this line (use floatingPointNumber) + printf("Double to int casting result: %d\n", integerRepresentation); + + bool understand = false; + unsigned int plus_one = 1; + int minus_one = -1; + + if(plus_one > minus_one) { // <-- Fix this line + understand = true; + } + assert(understand); + + return 0; +} diff --git a/master_exercises_read_only/17_constants/README.md b/master_exercises_read_only/17_constants/README.md new file mode 100644 index 0000000..65ae091 --- /dev/null +++ b/master_exercises_read_only/17_constants/README.md @@ -0,0 +1,3 @@ +# Constants + +For more information please refer to Chapter 2.1 of "The C Programming Language". diff --git a/master_exercises_read_only/17_constants/constants_1.c b/master_exercises_read_only/17_constants/constants_1.c new file mode 100644 index 0000000..5fb2f68 --- /dev/null +++ b/master_exercises_read_only/17_constants/constants_1.c @@ -0,0 +1,40 @@ +/* + * A constant in programming is a value that remains unchanged throughout the + * execution of a program. + * + * This exercise focuses on defining constants correctly. The provided file will + * not compile until the user correctly defines all constants. + * (You can only delete/edit lines with // <-- Fix this line) + */ + +#include +#include +#include + +// ❌ I AM NOT DONE + +int main() { + // Correctly Define the Constants + + // Define a constant integer with the value 100 + int_const = ; // <-- Fix this line + + // Define a constant float with the value 3.14 + float_const = ; // <-- Fix this line + + // Define a constant character with the value 'A' + char_const = ; // <-- Fix this line + + // Define a constant string with the value "Hello, World!" + str_const = ; // <-- Fix this line + + // DO NOT CHANGE + assert(int_const == 100); + assert(float_const == 3.14f); + assert(char_const == 'A'); + assert(strcmp(str_const, "Hello, World!") == 0); + + printf("All constants are correctly defined!\n"); + + return 0; +} diff --git a/master_exercises_read_only/17_constants/constants_2.c b/master_exercises_read_only/17_constants/constants_2.c new file mode 100644 index 0000000..697a04f --- /dev/null +++ b/master_exercises_read_only/17_constants/constants_2.c @@ -0,0 +1,45 @@ + +/* + * This exercise focuses on using constants correctly in calculations and + * logical operations. The provided file will not compile or run correctly until + * the user fixes the mistakes. + * (You can only delete/edit lines with // <-- Fix this line) + */ + +#include +#include + +// ❌ I AM NOT DONE + +/* + * The first name in an `enum` has value 0, the next 1, and so on, unless + * explicit values are specified + */ +enum boolean { NO, YES }; + +int main() { + // Correctly Use the Constants + const int MAX_VALUE = 100; + const float PI = 3.14f; + + MAX_VALUE = 90; // <-- Fix this line + + int result = +50; // <-- Fix this line: Should be 150 (use MAX_VALUE) + float area = PI * 10 * 10; + + // Logical operation + const char FLAG_TRUE = 'T'; + const char FLAG_FALSE = 'F'; + + char flag = 'T'; + int isTrue = (flag ==) ? YES : NO; // <-- Fix this line + + // DO NOT CHANGE + assert(result == 100); + assert(area == 314.0f); + assert(isTrue == 1); + + printf("Constants used correctly in calculations and logical operations!\n"); + + return 0; +} diff --git a/master_exercises_read_only/17_constants/constants_3.c b/master_exercises_read_only/17_constants/constants_3.c new file mode 100644 index 0000000..69423c5 --- /dev/null +++ b/master_exercises_read_only/17_constants/constants_3.c @@ -0,0 +1,27 @@ +/* + * + * This exercise focuses on `enumeration constants`. + * The provided file will not compile or run correctly until + * the user fixes the mistakes. + * + */ + +// ❌ I AM NOT DONE + +#include + +// Complete the escape squences: +enum escapes { BELL =, BACKSPACE =, TAB =, NEWLINE =, VTAB =, RETURN = "\r" }; + +int main(void) { + + // DO NOT CHANGE + assert(BELL == 7); + assert(BACKSPACE == 8); + assert(TAB == 9); + assert(NEWLINE == 10); + assert(VTAB == 11); + assert(RETURN == 13); + + return 0; +} diff --git a/master_exercises_read_only/18_declarations/README.md b/master_exercises_read_only/18_declarations/README.md new file mode 100644 index 0000000..307dd62 --- /dev/null +++ b/master_exercises_read_only/18_declarations/README.md @@ -0,0 +1,3 @@ +# Declarations + +For more information please refer to Chapter 2.4 of "The C Programming Language". diff --git a/master_exercises_read_only/18_declarations/declarations_01.c b/master_exercises_read_only/18_declarations/declarations_01.c new file mode 100644 index 0000000..1f9fbc4 --- /dev/null +++ b/master_exercises_read_only/18_declarations/declarations_01.c @@ -0,0 +1,34 @@ +/* + * The provided file will not compile until the user fixes all mistakes. + * (You can only delete/edit lines with // <-- Fix this line) + */ + +// ❌ I AM NOT DONE + +#include + +int main() { + int lower = 0, upper; // <-- Fix this line + char c, line[1000]; + + lower = 10; + upper = 20; + step = 2; // <-- Fix this line + + for (int i = lower; i <= upper; i += step) { + printf("Value: %d\n", i); + } + + float eps; + const double e = 2.71828182845905; + const char msg[] = "warning: "; + + eps = 1.0e-5; + + e = 3.14; // <-- Fix this line + + printf("%s The value of e is: %f\n", msg, e); + printf("Epsilon value is: %f\n", eps); + + return 0; +} diff --git a/master_exercises_read_only/19_arithmetic_operators/README.md b/master_exercises_read_only/19_arithmetic_operators/README.md new file mode 100644 index 0000000..6858e26 --- /dev/null +++ b/master_exercises_read_only/19_arithmetic_operators/README.md @@ -0,0 +1,3 @@ +# Arithmetic operators + +For more information please refer to Chapter 2.5 of "The C Programming Language". diff --git a/master_exercises_read_only/19_arithmetic_operators/arithmetic_operators_02.c b/master_exercises_read_only/19_arithmetic_operators/arithmetic_operators_02.c new file mode 100644 index 0000000..5114918 --- /dev/null +++ b/master_exercises_read_only/19_arithmetic_operators/arithmetic_operators_02.c @@ -0,0 +1,26 @@ +/* + * Fix the program + * + */ + +#include +#include +#include + +// ❌ I AM NOT DONE + +int main() { + int a = 1; + int b = 2; + int c = 3; + int result; + + // Only add parentheses, so that result == 2 + result = b * c / a - b % c; // <-- Fix this line + + assert(result == 2); + printf("The result is %d\n", result); + + return 0; +} + diff --git a/master_exercises_read_only/19_arithmetic_operators/arithmetic_operatos_01.c b/master_exercises_read_only/19_arithmetic_operators/arithmetic_operatos_01.c new file mode 100644 index 0000000..6494475 --- /dev/null +++ b/master_exercises_read_only/19_arithmetic_operators/arithmetic_operatos_01.c @@ -0,0 +1,33 @@ +/* + * Fix this short program, which checks for a leap year. + * + * You can only delete or edit lines with the comment "// <-- Fix this line". + * Ensure the program correctly identifies leap years according to the following rules: + * 1. A year is a leap year if it is divisible by 4. + * 2. However, if the year is also divisible by 100, it is not a leap year unless it is also divisible by 400. + */ + +#include +#include +#include + +// ❌ I AM NOT DONE + +int main() { + + int year = 2024; + bool isLeap = false; + + if ((year / 4 == 0 && year % 100 == 0) || year % 400 == 0) { // <-- Fix this line + isLeap = true; + printf("%d is a leap year\n", year); + } else { + isLeap = false; + printf("%d is not a leap year\n", year); + } + + + assert(isLeap == true); + + return 0; +} diff --git a/master_exercises_read_only/20_relational_logical_operators/README.md b/master_exercises_read_only/20_relational_logical_operators/README.md new file mode 100644 index 0000000..beb743a --- /dev/null +++ b/master_exercises_read_only/20_relational_logical_operators/README.md @@ -0,0 +1,3 @@ +# Relational and logical Operators + +For more information please refer to Chapter 2.6 of "The C Programming Language". diff --git a/master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_01.c b/master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_01.c new file mode 100644 index 0000000..7475029 --- /dev/null +++ b/master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_01.c @@ -0,0 +1,34 @@ +/* + * This exercise will focus on relational operators. + * Fix the if statements so that the code correctly compares the values of a and b. + * + * + */ + +// ❌ I AM NOT DONE + +#include +#include +#include + + +int main(void) { + int a = 3; + int b = 5; + + if (a b) { + printf("equal\n"); + } else if (a b) { + printf("not equal\n"); + } else if (a b) { + printf("less than\n"); + } else if (a b) { + printf("greater than\n"); + } else if (a b) { + printf("less than or equal\n"); + } else if (a b) { + printf("greater than or equal\n"); + } + + return 0; +} diff --git a/master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_02.c b/master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_02.c new file mode 100644 index 0000000..058b3fe --- /dev/null +++ b/master_exercises_read_only/20_relational_logical_operators/relational_logical_operators_02.c @@ -0,0 +1,28 @@ +/* + * The goal of this exercise is to understand how to use logical operators. + * Fix the `evaluate_logical` function so it returns the correct value. + */ + +// ❌ I AM NOT DONE + +#include +#include +#include + +bool evaluate_logical(bool a, bool b, bool c) { + return a b c; // <-- Fix here +} + +int main() { + // Only 'a' is true, should return false + assert(evaluate_logical(true, false, false) == false); + + // etc. + assert(evaluate_logical(false, true, false) == false); + assert(evaluate_logical(false, false, true) == true); + assert(evaluate_logical(false, false, false) == false); + assert(evaluate_logical(true, true, true) == true); + + printf("All tests passed.\n"); + return 0; +} diff --git a/master_exercises_read_only/21_type_conversions/README.md b/master_exercises_read_only/21_type_conversions/README.md new file mode 100644 index 0000000..4b34cc3 --- /dev/null +++ b/master_exercises_read_only/21_type_conversions/README.md @@ -0,0 +1,3 @@ +# Type conversions + +For more information please refer to Chapter 2.7 of "The C Programming Language". diff --git a/master_exercises_read_only/21_type_conversions/type_conversions_01.c b/master_exercises_read_only/21_type_conversions/type_conversions_01.c new file mode 100644 index 0000000..f533d30 --- /dev/null +++ b/master_exercises_read_only/21_type_conversions/type_conversions_01.c @@ -0,0 +1,39 @@ +/* + * Fix the program to handle type conversions correctly + * + * In this exercise, you will correct the type conversion issues in the given program. + * The program performs arithmetic operations involving integers, floats, and doubles. + * Your task is to ensure that the calculations are correct and the results match the expected values. + * + */ + +#include +#include +#include + +// ❌ I AM NOT DONE + +int main() { + + int i1 = 1; + int i2 = 3; + + int a; + float b; + double c; + + a = i1 / i2; + b = i1 / (i2 + ); // <-- Fix here (b = 0.25) + c = i1 / i2; // <-- Fix here (c = 0.333333) + + printf("a = %d, b = %f, c = %lf\n", a, b, c); + + // DO NOT CHANGE + double tolerance = 0.000001; + assert(a == 0); + assert((b - 0.25) < tolerance); + assert((c - 0.333333) < tolerance); + + printf("All tests passed.\n"); + return 0; +} diff --git a/master_exercises_read_only/21_type_conversions/type_conversions_02.c b/master_exercises_read_only/21_type_conversions/type_conversions_02.c new file mode 100644 index 0000000..12211d4 --- /dev/null +++ b/master_exercises_read_only/21_type_conversions/type_conversions_02.c @@ -0,0 +1,51 @@ +/* + * In this exercise, you will correct the issues in the given program. + * The program should convert all lowercase letters in a string to uppercase. + * Your task is to implement the correct logic in the `to_upper` function. + * + * We will use the properties of a char. A char has a size of 1 byte (8 bits), + * so it can store numbers from -128 to 127 if signed, or 0 to 255 if unsigned. + * If plain char is signed or unsigned is machine-dependent. + * Printable characters are always positive. + * + * When you define a char, C actually stores it as an integer underneath. + * To display characters, each char is mapped to a number using the ASCII table. + * The ASCII table maps numbers from 0-127 to specific characters. + * For example, the character 'A' is mapped to the number 65, and the character 'a' is mapped to the number 97. + * We can use this mapping to our advantage to convert lowercase letters to uppercase. + * + * 1. Check if the letter is lowercase. + * 2. Convert the letter to uppercase + * + * Do not add any libraries. + */ + +#include +#include +#include + +// ❌ I AM NOT DONE +// hint: Take a look at ASCII table + +char to_upper(char c) { + // We can actually campare chars (because in memory they are just numbers) + if(c 'a' && c 'z') { // <-- 1. Fix here + // <-- 2. Fix here + } + + return c; +} + + +int main() { + char s[] = "hello, world!"; + + for(int i = 0, len = strlen(s); i < len; i++) { + s[i] = to_upper(s[i]); + } + + printf("%s\n", s); + + assert(strcmp(s, "HELLO, WORLD!") == 0); + return 0; +} diff --git a/master_exercises_read_only/22_inc_dec_operators/README.md b/master_exercises_read_only/22_inc_dec_operators/README.md new file mode 100644 index 0000000..76a38c7 --- /dev/null +++ b/master_exercises_read_only/22_inc_dec_operators/README.md @@ -0,0 +1,3 @@ +# Increment and Decrement Operators + +For more information please refer to Chapter 2.8 of "The C Programming Language". diff --git a/master_exercises_read_only/22_inc_dec_operators/inc_dec_operators_01.c b/master_exercises_read_only/22_inc_dec_operators/inc_dec_operators_01.c new file mode 100644 index 0000000..c00314b --- /dev/null +++ b/master_exercises_read_only/22_inc_dec_operators/inc_dec_operators_01.c @@ -0,0 +1,40 @@ +/* + * This program demonstrates the use of increment (++) and decrement (--) operators in C. + * The increment operator adds 1 to its operand, while the decrement operator subtracts 1. + * The unusual aspect is that these operators can be used either as prefix or postfix. + * + * Prefix (e.g., ++i): Increment/decrement first, then return the new value. + * Postfix (e.g., i++): Return the current value first, then increment/decrement. + */ + +// ❌ I AM NOT DONE + +#include +#include + +int main() { + int i = 0; + int j = 2; + int k = 0; + int l = 3; + + // Use ++/-- instead + i = i + 1; // <-- Fix here + j = j - 1; // <-- Fix here + + // DO NOT CHANGE + assert(i == 1); + assert(j == 1); + + k = (i+j)++; // <-- Fix bug + + i = l++; // <-- Fix bug + + // DO NOT CHANGE + assert(i == 4); + assert(j == 1); + assert(k == 2); + assert(l == 4); + + return 0; +} diff --git a/master_exercises_read_only/23_bitwise_operators/README.md b/master_exercises_read_only/23_bitwise_operators/README.md new file mode 100644 index 0000000..9d6b28f --- /dev/null +++ b/master_exercises_read_only/23_bitwise_operators/README.md @@ -0,0 +1,3 @@ +# Bitwise operators + +For more information please refer to Chapter 2.8 of "The C Programming Language". diff --git a/master_exercises_read_only/23_bitwise_operators/bitwise_operators_01.c b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_01.c new file mode 100644 index 0000000..246c115 --- /dev/null +++ b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_01.c @@ -0,0 +1,45 @@ +/* + * Now we will start with bitwise operators, which help you manipulate bits directly. + * Bitwise operators are essential for low-level programming and are often used in systems programming, embedded systems, and performance-critical code. + * If you do not know bitwise operators, you can learn more here: https://en.wikipedia.org/wiki/Bitwise_operations_in_C + * + * In this exercise, your task is to find the correct bitwise operator so that each result matches the expected value. + * + * Here are some common bitwise operators in C that you might need: + * - & : Bitwise AND + * - | : Bitwise OR + * - ^ : Bitwise XOR (exclusive OR) + * - ~ : Bitwise NOT (one's complement) + * - << : Left shift + * - >> : Right shift + */ + +// Hint: convert number `a` and `b` to binary. + +#include +#include +#include + + +int main(void) { + int a = 5; + int b = 2; + + int f = a 2; // <-- Fix here (hint: multiply `a` by 2^2) + assert(f == 20); // f should be 20 ... + + int e = a b; // <-- Fix here + assert(e == 7); + + int c = a b; // <-- Fix here + assert(c == 0); + + int k = -1; + int g = // <-- Fix here: (use k somehow) + assert(g == 0); + + int d = a b; // <-- Fix here + assert(d == 7); + + return 0; +} diff --git a/master_exercises_read_only/23_bitwise_operators/bitwise_operators_02.c b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_02.c new file mode 100644 index 0000000..51a6d38 --- /dev/null +++ b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_02.c @@ -0,0 +1,44 @@ +/* Now we will start with bitwise operators, which helps you manipulate bits. + * If you do not know bitwise operators look here: https://en.wikipedia.org/wiki/Bitwise_operations_in_C + * + * Let's start with simple example. + * Fix `is_even` function, which returns true if number is even. + * Of course we could use %, but we are smarter! + * Write down even and odd numbers in binary and try to find pattern, which you could use for deciding if number is even or not. + * Decide which bitwise operator would work. + * + */ + + +#include +#include +#include +#include + +void print_bits(char num) { + printf("%d: ", num); + for(long i = sizeof(num) * CHAR_BIT - 1; i >= 0; i--) { + printf("%d ", (num >> i) & 1); + } + + printf("\n"); +} + +bool is_even(int num) { + // Pay attention to operator precendence + if(num 1 == 0) { // <-- Fix here + return true; + } + + return false; +} + +int main(void) { + char num = 7; + print_bits(num); + print_bits(1); + + assert(is_even(num) == 0); + + return 0; +} diff --git a/master_exercises_read_only/23_bitwise_operators/bitwise_operators_03.c b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_03.c new file mode 100644 index 0000000..96a6b03 --- /dev/null +++ b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_03.c @@ -0,0 +1,44 @@ +/* + * Now let's try to create a bit mask that will mask out (set to 0) the lower four bits of a byte (8 bits). + * In other words, we want to keep the upper 4 bits unchanged and set the lower 4 bits to 0. + * + * Example: + * + * Let's say we have the following byte: + * i = 10111011 + * + * After applying the bit mask to clear the lower four bits, we should get: + * result = 10110000 + * + * Steps: + * 1. Create a bit mask that has 1s in the upper four bit positions and 0s in the lower four bit positions. + * 2. Apply the mask to the given byte using the bitwise AND operator. + */ + + +#include +#include +#include + +void print_bits(unsigned char num) { + printf("%3d: ", num); + for(long i = sizeof(num) * CHAR_BIT - 1; i >= 0; i--) { + printf("%d ", (num >> i) & 1); + } + + printf("\n"); +} + +int main(void) { + + unsigned char i = 0xBB; // 10111011 + print_bits(i); + + unsigned char mask = ; // <-- Fix here + i = i mask; // <-- Fix here + + print_bits(i); + assert(i == 0xB0); // 10110000 + + return 0; +} diff --git a/master_exercises_read_only/23_bitwise_operators/bitwise_operators_04.c b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_04.c new file mode 100644 index 0000000..fbbf351 --- /dev/null +++ b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_04.c @@ -0,0 +1,46 @@ +/* + * XOR Swap Algorithm + * + * The XOR (exclusive or) operator has special properties that allow us to swap two values + * without using a temporary variable. This technique is called the XOR swap. + * + * How XOR works: + * - When you XOR a bit with 0, it remains unchanged + * - When you XOR a bit with 1, it flips (0 becomes 1, and 1 becomes 0) + * - XOR is commutative: a XOR b = b XOR a + * - XOR is associative: (a XOR b) XOR c = a XOR (b XOR c) + * + * Example: + * Let a = 1010 and b = 0011 + * Step 1: a = a XOR b -> a = 1010 XOR 0011 = 1001, b = 0011 + * Step 2: b = a XOR b -> a = 1001, b = 1001 XOR 0011 = 1010 + * Step 3: a = a XOR b -> a = 1001 XOR 1010 = 0011, b = 1010 + * + * Result: The values of 'a' and 'b' have been swapped. + * + * Task: Use these properties of XOR to swap the values of 'a' and 'b' without using a temporary variable. + */ + +// ❌ I AM NOT DONE + +#include + +int main(void) { + + int a = 11; + int b = 42; + + if(a == b) return 0; + + // Fix code + a = a ^ b; + + a = a ^ b; + // Fix code + + + assert(a == 42); + assert(b == 11); + + return 0; +} diff --git a/master_exercises_read_only/23_bitwise_operators/bitwise_operators_05.c b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_05.c new file mode 100644 index 0000000..f881cfa --- /dev/null +++ b/master_exercises_read_only/23_bitwise_operators/bitwise_operators_05.c @@ -0,0 +1,61 @@ +/* + * Bit Manipulation Exercise: Swap Most Significant Bit (MSB) and Least Significant Bit (LSB) + * + * Your task is to implement the `swap_edge_bits` function, which swaps the MSB and LSB of an 8-bit unsigned char. + * + * MSB = Most Significant Bit (leftmost bit) + * LSB = Least Significant Bit (rightmost bit) + * + * Example: + * + * Input: 10000000 (decimal 128) + * Output: 00000001 (decimal 1) + * + * The function should follow these steps: + * 1. Extract the MSB, move to LSB + * 2. Extract the LSB, move to MSB + * 3. Create a mask to clear both MSB and LSB + * 4. Combine the extracted bits with the masked value + * + * This exercise demonstrates bitwise operations and manipulations on individual bits. + */ + +// ❌ I AM NOT DONE + +#include +#include +#include + +void print_bits(unsigned char num) { + printf("%3d: ", num); + for(long i = sizeof(num) * CHAR_BIT - 1; i >= 0; i--) { + printf("%d ", (num >> i) & 1); + } + + printf("\n"); +} + +// unsigned char has 8 bits +unsigned char swap_edge_bits(unsigned char num) { + unsigned char msb = ; // <-- Fix here + unsigned char lsb = ; // <-- Fix here + unsigned char mask = ; // <-- Fix here + + num = num mask msb lsb; // <-- Fix here + + return num; +} + + +int main(void) { + + unsigned char i = 128; + print_bits(i); + + i = swap_edge_bits(i); + + print_bits(i); + assert(i == 1); + + return 0; +} diff --git a/master_exercises_read_only/24_assignment_operators/README.md b/master_exercises_read_only/24_assignment_operators/README.md new file mode 100644 index 0000000..ce32e81 --- /dev/null +++ b/master_exercises_read_only/24_assignment_operators/README.md @@ -0,0 +1,3 @@ +# Assignment operators + +For more information please refer to Chapter 2.10 of "The C Programming Language". diff --git a/master_exercises_read_only/24_assignment_operators/assignment_operators_01.c b/master_exercises_read_only/24_assignment_operators/assignment_operators_01.c new file mode 100644 index 0000000..168eee1 --- /dev/null +++ b/master_exercises_read_only/24_assignment_operators/assignment_operators_01.c @@ -0,0 +1,28 @@ +/* + * This expression: + * a = a + 1 + * can be written like this: + * a += 1 + * + * The += operator is an assignment operator. + * + * Most binary operators have corresponding assignment operators. + * These can be useful for writing cleaner and more understandable code. + */ + +// ❌ I AM NOT DONE + +#include +#include + +int main() { + int a = 4; + int b = 1; + + a = a / 2; // <-- Fix here (use an assignment operator) + b = b * 3; // <-- Fix here (use an assignment operator) + + assert(a == 2); + assert(b == 3); + return 0; +} diff --git a/master_exercises_read_only/25_conditional_expressions/README.md b/master_exercises_read_only/25_conditional_expressions/README.md new file mode 100644 index 0000000..68c0d9f --- /dev/null +++ b/master_exercises_read_only/25_conditional_expressions/README.md @@ -0,0 +1,3 @@ +# Conditional expressions + +For more information please refer to Chapter 2.11 of "The C Programming Language". diff --git a/master_exercises_read_only/25_conditional_expressions/conditional_expressions_01.c b/master_exercises_read_only/25_conditional_expressions/conditional_expressions_01.c new file mode 100644 index 0000000..38fd7ba --- /dev/null +++ b/master_exercises_read_only/25_conditional_expressions/conditional_expressions_01.c @@ -0,0 +1,44 @@ +/* + * Rewrite the `to_upper` function from the previous exercise without using an `if` statement. + * Instead, use a conditional (ternary) expression. + * + * A conditional expression looks like this: + * condition ? value_if_true : value_if_false + * + * For example: + * z = (a > b) ? a : b; + * + * In this example, if `a` is greater than `b`, then `z` will be assigned the value of `a`. + * Otherwise, `z` will be assigned the value of `b`. + * + * Conditional expressions can sometimes make the code easier to read. + */ + +#include +#include +#include + +// ❌ I AM NOT DONE + +char to_upper(char c) { + // Rewrite + if(c >= 'a' && c <= 'z') { + return c - 32; + } + + return c; + // Rewrite +} + +int main() { + char s[] = "hello, world!"; + + for(int i = 0, len = strlen(s); i < len; i++) { + s[i] = to_upper(s[i]); + } + + printf("%s\n", s); + + assert(strcmp(s, "HELLO, WORLD!") == 0); + return 0; +} diff --git a/master_exercises_read_only/26_operator_precedence/README.md b/master_exercises_read_only/26_operator_precedence/README.md new file mode 100644 index 0000000..42ea96d --- /dev/null +++ b/master_exercises_read_only/26_operator_precedence/README.md @@ -0,0 +1,3 @@ +# Precedence and Order of Evaluation + +For more information please refer to Chapter 2.12 of "The C Programming Language". diff --git a/master_exercises_read_only/26_operator_precedence/operator_precedence_01.c b/master_exercises_read_only/26_operator_precedence/operator_precedence_01.c new file mode 100644 index 0000000..55c9ce4 --- /dev/null +++ b/master_exercises_read_only/26_operator_precedence/operator_precedence_01.c @@ -0,0 +1,102 @@ +/* + * This program simulates a banking system with various operations. + * It contains errors related to operator precedence, associativity, and side effects. + * + * Your task is to identify and fix the mistakes in the program. + * The program should pass all assertions when corrected. + * + * Common mistakes to look out for: + * - Incorrect operator precedence + * - Unintended side effects + * - Misuse of increment/decrement operators + * - Incorrect order of operations + * - Bitwise vs. logical operators + */ + +// ❌ I AM NOT DONE + +#include +#include + +#define MAX_ACCOUNTS 3 +#define OVERDRAFT_FEE 5 +#define INTEREST_RATE 5 +#define TRANSACTION_FEE 1 +#define VIP_THRESHOLD 1000 +#define VIP_STATUS 0x1 + +void deposit(int account, int amount); +void withdraw(int account, int amount); +void transfer(int from, int to, int amount); +void apply_interest(int account); +int calculate_fee(int account); +void update_vip_status(int account); + +int balances[MAX_ACCOUNTS] = {100, 50, 750}; +int status[MAX_ACCOUNTS] = {0, 0, 0}; // Bit flags for account status 1 - VIP, 0 - pleb + + +int main() { + // Test case 1: Deposit with complex calculation + deposit(0, 50); + assert(balances[0] == 149); + + // Test case 2: Withdraw with fee calculation + withdraw(1, 30); + assert(balances[1] == 19); + + // Test case 3: Transfer with precedence issue + transfer(2, 0, 100); + assert(balances[2] == 649 && balances[0] == 248); + + // Test case 4: Withdraw with overdraft and bitwise operation + withdraw(1, 25); + assert(balances[1] == -12); + + // Test case 5: Apply interest with precedence and type conversion + apply_interest(0); + assert(balances[0] == 260); + + // Test case 6: Update VIP status + deposit(2, 1000); + update_vip_status(2); + assert(status[2] == VIP_STATUS); + + printf("All tests passed successfully!\n"); + return 0; +} + +void deposit(int account, int amount) { + balances[account] =+ amount - calculate_fee(account); // <-- Fix here +} + +void withdraw(int account, int amount) { + int fee = calculate_fee(account); + if (balances[account] - amount < 0) { + amount + OVERDRAFT_FEE; // <-- Fix here + } + + balances[account] = (amount + fee); // <-- Fix Here +} + +void transfer(int from, int to, int amount) { + int fee = calculate_fee(from) + calculate_fee(to); + balances[from] -= (amount + fee / 2); + balances[to] += (amount + fee / 2); // <-- Fix here +} + +void apply_interest(int account) { + // Apply 5% interest + balances[account] = balances[account] * 100 + INTEREST_RATE / 100; // <-- Fix here +} + +int calculate_fee(int account) { + return status[account] & VIP_STATUS == 0 ? TRANSACTION_FEE : 0; // <-- Fix here +} + +void update_vip_status(int account) { + if (balances[account] > VIP_THRESHOLD) + status[account] |= VIP_STATUS; + else + status[account] &= ~VIP_STATUS; +} diff --git a/master_exercises_read_only/27_statements_and_blocks/README.md b/master_exercises_read_only/27_statements_and_blocks/README.md new file mode 100644 index 0000000..6e050f7 --- /dev/null +++ b/master_exercises_read_only/27_statements_and_blocks/README.md @@ -0,0 +1,3 @@ +# Statements and Blocks + +For more information please refer to Chapter 3.1 of "The C Programming Language". diff --git a/master_exercises_read_only/27_statements_and_blocks/statements_and_blocks_01.c b/master_exercises_read_only/27_statements_and_blocks/statements_and_blocks_01.c new file mode 100644 index 0000000..ce62369 --- /dev/null +++ b/master_exercises_read_only/27_statements_and_blocks/statements_and_blocks_01.c @@ -0,0 +1,32 @@ +/* + * Blocks in C are defined with the braces { }. Oftentimes these braces are required in things like for loops, but they are + * also used to put things into their own "scope". + * + * Take a look at the program below and figure out why this program is not compiling. +*/ + +// ❌ I AM NOT DONE + +#include +#include + +int main() { + int sum = 0; + + // do not get rid fo the braces + { + // could these move somewhere else? + int a = 1; + int b = 2; + int c = 3; + } + + // could this move somewhere else? + sum = a + b + c; + + + // do not change this + printf("sum: %i \n", sum); + assert(sum == 6); + return 0; +} diff --git a/master_exercises_read_only/35_functions_basics/README.md b/master_exercises_read_only/35_functions_basics/README.md new file mode 100644 index 0000000..f750eb1 --- /dev/null +++ b/master_exercises_read_only/35_functions_basics/README.md @@ -0,0 +1,3 @@ +# Basics of functions + +For more information please refer to Chapter 4.1 of "The C Programming Language". diff --git a/master_exercises_read_only/35_functions_basics/functions_basics_01.c b/master_exercises_read_only/35_functions_basics/functions_basics_01.c new file mode 100644 index 0000000..f3a8da2 --- /dev/null +++ b/master_exercises_read_only/35_functions_basics/functions_basics_01.c @@ -0,0 +1,43 @@ +/* + * Exercise: Implementing the strlen function + * + * In this exercise, you'll create your own version of the strlen function, + * which counts the number of characters in a string (excluding the null terminator). + * + * Your tasks: + * 1. Complete the my_strlen function to return the length of the input string. + * 2. Move the length calculation logic from main() into the my_strlen function. + * 3. Ensure the assert statement passes after your implementation. + * + * Tips: + * - A string in C is terminated by a null character '\0'. + * - The function should return an int (the length of the string). + */ + +// ❌ I AM NOT DONE + +#include + +// TODO: Finish the function +my_strlen(char *s) { + + return; +} +// Finish the function + + +int main(void) { + char *s = "Hello, world!"; + + // TODO: Put into my_strlen function + int len = 0; + for(int i = 0; s[i] != '\0'; i++) { + len++; + } + // Put into my_strlen function + + //DO NOT CHANGE + assert(my_strlen(s) == 13); + + return 0; +} diff --git a/master_exercises_read_only/36_non_integer_functions/README.md b/master_exercises_read_only/36_non_integer_functions/README.md new file mode 100644 index 0000000..06f3c3d --- /dev/null +++ b/master_exercises_read_only/36_non_integer_functions/README.md @@ -0,0 +1,3 @@ +# Functions Returning Non-Integers + +For more information please refer to Chapter 4.2 of "The C Programming Language". diff --git a/master_exercises_read_only/36_non_integer_functions/non_integer_functions_01.c b/master_exercises_read_only/36_non_integer_functions/non_integer_functions_01.c new file mode 100644 index 0000000..67596cc --- /dev/null +++ b/master_exercises_read_only/36_non_integer_functions/non_integer_functions_01.c @@ -0,0 +1,69 @@ +/* + * Exercise: Implementing Heron's formula for triangle area + * + * In this exercise, you'll create a function called triangle_area that + * calculates the area of a triangle given the lengths of its three sides + * using Heron's formula. + * + * Heron's formula: Area = sqrt(s * (s - a) * (s - b) * (s - c)) + * where s = (a + b + c) / 2 + * and a, b, c are the lengths of the triangle's sides. + * + * Your tasks: + * 1. Complete the triangle_area function to return the correct area. + * 2. Use the provided sqrt function for square root calculation. + * 3. Handle invalid triangles by returning -1.0 for any errors. + * 4. Make sure the assert statements pass after your implementation. + * + * Tips: + * - Check if the given side lengths can form a valid triangle. + */ + +// ❌ I AM NOT DONE + +#include +#include +#include + +// You can use this tolerance for floating-point comparisons +#define EPSILON 1e-6 + +// Implement this function +// TODO: correct return type +triangle_area(double a, double b, double c) { + // TODO: Check if all sides are positive + if () { + return ; + } + + // TODO: Check Triangle Inequality Theorem + if () { + return ; + } + + // TODO: Calculate area + + return +} + +// Helper function for comparing floating-point numbers +int double_equals(double a, double b) { + return fabs(a - b) < EPSILON; +} + +int main(void) { + + // Test cases + assert(double_equals(triangle_area(3, 4, 5), 6.0)); + assert(double_equals(triangle_area(5, 12, 13), 30.0)); + assert(double_equals(triangle_area(2, 2, 2), 1.732051)); + assert(double_equals(triangle_area(1, 1, 1.41), 0.499991)); + + // Error cases + assert(double_equals(triangle_area(1, 1, 3), -1.0)); // Invalid triangle + assert(double_equals(triangle_area(0, 4, 5), -1.0)); // Side length can't be 0 + assert(double_equals(triangle_area(-1, 4, 5), -1.0)); // Side length can't be negative + + printf("All tests passed!\n"); + return 0; +} diff --git a/master_exercises_read_only/37_external_variables/README.md b/master_exercises_read_only/37_external_variables/README.md new file mode 100644 index 0000000..fddd859 --- /dev/null +++ b/master_exercises_read_only/37_external_variables/README.md @@ -0,0 +1,3 @@ +# Using External Variables + +For more information please refer to Chapter 4.3 of "The C Programming Language". diff --git a/master_exercises_read_only/37_external_variables/external_variables.c b/master_exercises_read_only/37_external_variables/external_variables.c new file mode 100644 index 0000000..c421b13 --- /dev/null +++ b/master_exercises_read_only/37_external_variables/external_variables.c @@ -0,0 +1,57 @@ +/* + * Exercise: Understanding and Fixing External Variables + * + * In this exercise, you'll work with a simple program that uses external variables + * to keep track of a counter across multiple function calls. The program is currently + * broken and doesn't produce the expected output. + * + * Your tasks: + * 1. Identify why the counter is not incrementing correctly. + * 2. Fix the issue by correctly using external variables. + * 3. Make sure the assert statements pass after your implementation. + * + * Tips: + * - Pay attention to variable declarations and their scope. + * - Remember that external variables are defined outside of any function. + */ + +// ❌ I AM NOT DONE + +#include +#include + +// TODO: Fix the counter variable declaration + +void increment_counter() { + int counter = 0; + counter++; +} + +int get_counter() { + // TODO: Fix this function to return the correct counter value + return 0; +} + +void reset_counter() { + // TODO: Implement this function to reset the counter to 0 +} + +int main() { + assert(get_counter() == 0); + + increment_counter(); + increment_counter(); + assert(get_counter() == 2); + + increment_counter(); + assert(get_counter() == 3); + + reset_counter(); + assert(get_counter() == 0); + + increment_counter(); + assert(get_counter() == 1); + + printf("All tests passed!\n"); + return 0; +} diff --git a/reset_directory b/reset_directory new file mode 100644 index 0000000000000000000000000000000000000000..93ce35d463b4035b3c5ff166cc8112243f22809d GIT binary patch literal 17552 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 literal 0 HcmV?d00001 diff --git a/reset_directory.c b/reset_directory.c new file mode 100644 index 0000000..606d475 --- /dev/null +++ b/reset_directory.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void copy_file(const char *src, const char *dest) { + int source_fd = open(src, O_RDONLY); + int dest_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0644); + char buffer[1024]; + ssize_t bytes; + while ((bytes = read(source_fd, buffer, sizeof(buffer))) > 0) { + write(dest_fd, buffer, bytes); + } + close(source_fd); + close(dest_fd); +} + +void remove_directory_contents(const char *dir_path) { + DIR *dir = opendir(dir_path); + struct dirent *entry; + char file_path[1024]; + + if (dir == NULL) { + perror("opendir"); + return; + } + + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, entry->d_name); + + struct stat path_stat; + stat(file_path, &path_stat); + + if (S_ISDIR(path_stat.st_mode)) { + remove_directory_contents(file_path); + rmdir(file_path); + } else { + unlink(file_path); + } + } + + closedir(dir); +} +// nuke the working directory and copy the master directory to it +// need to test on each exercise + +void reset_directory(const char *master, const char *working) { + remove_directory_contents(working); + + DIR *dir = opendir(master); + struct dirent *entry; + char src_path[1024], dest_path[1024]; + + if (dir == NULL) { + perror("opendir"); + return; + } + + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + snprintf(src_path, sizeof(src_path), "%s/%s", master, entry->d_name); + snprintf(dest_path, sizeof(dest_path), "%s/%s", working, entry->d_name); + + struct stat path_stat; + stat(src_path, &path_stat); + + if (S_ISDIR(path_stat.st_mode)) { + mkdir(dest_path, 0755); + reset_directory(src_path, dest_path); + } else { + copy_file(src_path, dest_path); + } + } + + closedir(dir); +} + +int main() { + reset_directory("./master_exercises_read_only", "./exercises"); + printf("Reset complete!\n"); + return 0; +} \ No newline at end of file From b04b49e4c941d28138a836a4fc6efbe7960f7a18 Mon Sep 17 00:00:00 2001 From: Fabian <28697474+tunahorse@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:25:35 -0500 Subject: [PATCH 2/4] Update reset_directory.c --- reset_directory.c | 129 ++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 61 deletions(-) diff --git a/reset_directory.c b/reset_directory.c index 606d475..89a3e3d 100644 --- a/reset_directory.c +++ b/reset_directory.c @@ -8,84 +8,91 @@ #include void copy_file(const char *src, const char *dest) { - int source_fd = open(src, O_RDONLY); - int dest_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0644); - char buffer[1024]; - ssize_t bytes; - while ((bytes = read(source_fd, buffer, sizeof(buffer))) > 0) { - write(dest_fd, buffer, bytes); - } - close(source_fd); - close(dest_fd); + int source_fd = open(src, O_RDONLY); + int dest_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0644); + char buffer[1024]; + ssize_t bytes; + while ((bytes = read(source_fd, buffer, sizeof(buffer))) > 0) { + write(dest_fd, buffer, bytes); + } + close(source_fd); + close(dest_fd); } void remove_directory_contents(const char *dir_path) { - DIR *dir = opendir(dir_path); - struct dirent *entry; - char file_path[1024]; + DIR *dir = opendir(dir_path); + struct dirent *entry; + char file_path[1024]; - if (dir == NULL) { - perror("opendir"); - return; - } + if (dir == NULL) { + perror("opendir"); + return; + } - while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { - continue; - } - snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, entry->d_name); + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, entry->d_name); - struct stat path_stat; - stat(file_path, &path_stat); + struct stat path_stat; + stat(file_path, &path_stat); - if (S_ISDIR(path_stat.st_mode)) { - remove_directory_contents(file_path); - rmdir(file_path); - } else { - unlink(file_path); - } - } + if (S_ISDIR(path_stat.st_mode)) { + remove_directory_contents(file_path); + rmdir(file_path); + } else { + unlink(file_path); + } + } - closedir(dir); + closedir(dir); } -// nuke the working directory and copy the master directory to it -// need to test on each exercise void reset_directory(const char *master, const char *working) { - remove_directory_contents(working); + remove_directory_contents(working); - DIR *dir = opendir(master); - struct dirent *entry; - char src_path[1024], dest_path[1024]; + DIR *dir = opendir(master); + struct dirent *entry; + char src_path[1024], dest_path[1024]; - if (dir == NULL) { - perror("opendir"); - return; - } + if (dir == NULL) { + perror("opendir"); + return; + } - while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { - continue; - } - snprintf(src_path, sizeof(src_path), "%s/%s", master, entry->d_name); - snprintf(dest_path, sizeof(dest_path), "%s/%s", working, entry->d_name); + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + snprintf(src_path, sizeof(src_path), "%s/%s", master, entry->d_name); + snprintf(dest_path, sizeof(dest_path), "%s/%s", working, entry->d_name); - struct stat path_stat; - stat(src_path, &path_stat); + struct stat path_stat; + stat(src_path, &path_stat); - if (S_ISDIR(path_stat.st_mode)) { - mkdir(dest_path, 0755); - reset_directory(src_path, dest_path); - } else { - copy_file(src_path, dest_path); - } - } + if (S_ISDIR(path_stat.st_mode)) { + mkdir(dest_path, 0755); + reset_directory(src_path, dest_path); + } else { + copy_file(src_path, dest_path); + } + } - closedir(dir); + closedir(dir); } int main() { - reset_directory("./master_exercises_read_only", "./exercises"); - printf("Reset complete!\n"); - return 0; -} \ No newline at end of file + // Ask user before we nuke to be safe + printf("Are you sure you want to reset? This will delete all progress. (y/n): "); + char response; + scanf(" %c", &response); + if (response != 'y' && response != 'Y') { + printf("Reset cancelled.\n"); + return 0; + } + + reset_directory("./master_exercises_read_only", "./exercises"); + printf("Reset complete!\n"); + return 0; +} From da107596943bec2e9355a60d25f71b288f1fecf0 Mon Sep 17 00:00:00 2001 From: Fabian <28697474+tunahorse@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:35:04 -0500 Subject: [PATCH 3/4] Update reset_directory.c --- reset_directory.c | 71 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/reset_directory.c b/reset_directory.c index 89a3e3d..10f6029 100644 --- a/reset_directory.c +++ b/reset_directory.c @@ -82,17 +82,70 @@ void reset_directory(const char *master, const char *working) { closedir(dir); } +void reset_exercise(int exercise_number) { + DIR *master_dir = opendir("./master_exercises_read_only"); + DIR *working_dir = opendir("./exercises"); + struct dirent *entry; + char number_prefix[3]; + int exercises_reset = 0; + + if (master_dir == NULL || working_dir == NULL) { + perror("opendir"); + return; + } + + snprintf(number_prefix, sizeof(number_prefix), "%02d", exercise_number); + + printf("Resetting exercise(s) starting with %s...\n", number_prefix); + + while ((entry = readdir(master_dir)) != NULL) { + if (strncmp(entry->d_name, number_prefix, 2) == 0) { + char full_master_path[1024], full_working_path[1024]; + snprintf(full_master_path, sizeof(full_master_path), "./master_exercises_read_only/%s", entry->d_name); + snprintf(full_working_path, sizeof(full_working_path), "./exercises/%s", entry->d_name); + + printf("Resetting: %s\n", entry->d_name); + reset_directory(full_master_path, full_working_path); + exercises_reset++; + } + } + + closedir(master_dir); + closedir(working_dir); + + if (exercises_reset > 0) { + printf("Reset complete for %d exercise(s) starting with %s!\n", exercises_reset, number_prefix); + } else { + printf("No exercises found starting with %s.\n", number_prefix); + } +} + int main() { - // Ask user before we nuke to be safe - printf("Are you sure you want to reset? This will delete all progress. (y/n): "); - char response; - scanf(" %c", &response); - if (response != 'y' && response != 'Y') { - printf("Reset cancelled.\n"); - return 0; + // nuke or choose + int exercise_number; + printf("Enter the exercise number you want to reset ex '01' (or 0 to reset all): "); + scanf("%d", &exercise_number); + + if (exercise_number == 0) { + printf("Are you sure you want to reset all exercises? This will delete all progress. (y/n): "); + char response; + scanf(" %c", &response); + if (response != 'y' && response != 'Y') { + printf("Reset cancelled.\n"); + return 0; + } + reset_directory("./master_exercises_read_only", "./exercises"); + printf("All exercises have been reset!\n"); + } else { + printf("Are you sure you want to reset exercise(s) starting with %02d? This will delete all progress for these exercise(s). (y/n): ", exercise_number); + char response; + scanf(" %c", &response); + if (response != 'y' && response != 'Y') { + printf("Reset cancelled.\n"); + return 0; + } + reset_exercise(exercise_number); } - reset_directory("./master_exercises_read_only", "./exercises"); - printf("Reset complete!\n"); return 0; } From f16938bc457883b397981ac8d37618e54a20c383 Mon Sep 17 00:00:00 2001 From: Fabian <28697474+tunahorse@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:38:11 -0500 Subject: [PATCH 4/4] adding error handing for reset logic --- reset_directory.c | 118 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 35 deletions(-) diff --git a/reset_directory.c b/reset_directory.c index 10f6029..10b5f07 100644 --- a/reset_directory.c +++ b/reset_directory.c @@ -6,14 +6,30 @@ #include #include #include +#include void copy_file(const char *src, const char *dest) { int source_fd = open(src, O_RDONLY); + if (source_fd == -1) { + perror("Error opening source file"); + return; + } int dest_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (dest_fd == -1) { + perror("Error opening destination file"); + close(source_fd); + return; + } char buffer[1024]; ssize_t bytes; while ((bytes = read(source_fd, buffer, sizeof(buffer))) > 0) { - write(dest_fd, buffer, bytes); + if (write(dest_fd, buffer, bytes) != bytes) { + perror("Error writing to destination file"); + break; + } + } + if (bytes == -1) { + perror("Error reading from source file"); } close(source_fd); close(dest_fd); @@ -21,13 +37,12 @@ void copy_file(const char *src, const char *dest) { void remove_directory_contents(const char *dir_path) { DIR *dir = opendir(dir_path); - struct dirent *entry; - char file_path[1024]; - if (dir == NULL) { - perror("opendir"); + perror("Error opening directory"); return; } + struct dirent *entry; + char file_path[1024]; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { @@ -36,13 +51,20 @@ void remove_directory_contents(const char *dir_path) { snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, entry->d_name); struct stat path_stat; - stat(file_path, &path_stat); + if (stat(file_path, &path_stat) == -1) { + perror("Error getting file status"); + continue; + } if (S_ISDIR(path_stat.st_mode)) { remove_directory_contents(file_path); - rmdir(file_path); + if (rmdir(file_path) == -1) { + perror("Error removing directory"); + } } else { - unlink(file_path); + if (unlink(file_path) == -1) { + perror("Error removing file"); + } } } @@ -53,13 +75,12 @@ void reset_directory(const char *master, const char *working) { remove_directory_contents(working); DIR *dir = opendir(master); - struct dirent *entry; - char src_path[1024], dest_path[1024]; - if (dir == NULL) { - perror("opendir"); + perror("Error opening master directory"); return; } + struct dirent *entry; + char src_path[1024], dest_path[1024]; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { @@ -69,10 +90,16 @@ void reset_directory(const char *master, const char *working) { snprintf(dest_path, sizeof(dest_path), "%s/%s", working, entry->d_name); struct stat path_stat; - stat(src_path, &path_stat); + if (stat(src_path, &path_stat) == -1) { + perror("Error getting file status"); + continue; + } if (S_ISDIR(path_stat.st_mode)) { - mkdir(dest_path, 0755); + if (mkdir(dest_path, 0755) == -1) { + perror("Error creating directory"); + continue; + } reset_directory(src_path, dest_path); } else { copy_file(src_path, dest_path); @@ -84,16 +111,20 @@ void reset_directory(const char *master, const char *working) { void reset_exercise(int exercise_number) { DIR *master_dir = opendir("./master_exercises_read_only"); + if (master_dir == NULL) { + perror("Error opening master directory"); + return; + } DIR *working_dir = opendir("./exercises"); + if (working_dir == NULL) { + perror("Error opening working directory"); + closedir(master_dir); + return; + } struct dirent *entry; char number_prefix[3]; int exercises_reset = 0; - if (master_dir == NULL || working_dir == NULL) { - perror("opendir"); - return; - } - snprintf(number_prefix, sizeof(number_prefix), "%02d", exercise_number); printf("Resetting exercise(s) starting with %s...\n", number_prefix); @@ -121,29 +152,46 @@ void reset_exercise(int exercise_number) { } int main() { - // nuke or choose + char input[10]; int exercise_number; - printf("Enter the exercise number you want to reset ex '01' (or 0 to reset all): "); - scanf("%d", &exercise_number); + printf("Enter the exercise number you want to reset (00-99, or 0 to reset all): "); + if (fgets(input, sizeof(input), stdin) == NULL) { + fprintf(stderr, "Error reading input\n"); + return 1; + } + + // clean up input + input[strcspn(input, "\n")] = 0; + + // make sure input is g2g + if (strlen(input) > 2 || !isdigit(input[0]) || (strlen(input) == 2 && !isdigit(input[1]))) { + fprintf(stderr, "Invalid input. Please enter a number between 00 and 99, or 0.\n"); + return 1; + } + + exercise_number = atoi(input); + // nuke or choose number if (exercise_number == 0) { printf("Are you sure you want to reset all exercises? This will delete all progress. (y/n): "); - char response; - scanf(" %c", &response); - if (response != 'y' && response != 'Y') { - printf("Reset cancelled.\n"); - return 0; - } + } else if (exercise_number > 0 && exercise_number <= 99) { + printf("Are you sure you want to reset exercise(s) %02d? This will delete all progress for these exercise(s). (y/n): ", exercise_number); + } else { + fprintf(stderr, "Invalid exercise number. Please enter a number between 00 and 99, or 0 for all exercises.\n"); + return 1; + } + + char response; + scanf(" %c", &response); + if (response != 'y' && response != 'Y') { + printf("Reset cancelled.\n"); + return 0; + } + + if (exercise_number == 0) { reset_directory("./master_exercises_read_only", "./exercises"); printf("All exercises have been reset!\n"); } else { - printf("Are you sure you want to reset exercise(s) starting with %02d? This will delete all progress for these exercise(s). (y/n): ", exercise_number); - char response; - scanf(" %c", &response); - if (response != 'y' && response != 'Y') { - printf("Reset cancelled.\n"); - return 0; - } reset_exercise(exercise_number); }