Advanced C Programming

Spring 2024 ECE 26400 :: Purdue University

This is a PAST SEMESTER (Spring 2024).
Due 2/6

Strings: mintf(…)

Goals

This assignment has the following goals:
  1. Understand number bases
  2. Understand how printed representations of values relate to in-memory representations
  3. Practice designing simple algorithms.
  4. Practice using test-driven development.

Overview

You will create a function called mintf(…) that is similar to the standard printf(…) but in place of the usual format codes, your mintf(…) will support the following format codes:

%d integer (int, short, or char), expressed in decimal notation, with no prefix.
Ex: 15 would be formatted as 15.
%x integer (int, short, or char), expressed in hexadecimal notation with the prefix "0x"; use lowercase letters for digits beyond 9
Ex: 15 (fifteen) would be formatted as 0xf.
%b integer (int, short, or char), expressed in binary notation with the prefix "0b"
Ex: 2 (two) would be formatted as 0b10.
%$ floating point number (double), interpreted as a number of US dollars to be formatted as currency ($▒.▒▒). Round to the nearest cent. For simplicity, you may assume the argument is between INT_MIN/1000 and INT_MAX/1000.
Ex #1: 768336.75 would be formatted as $768336.75.
Ex #2: 768336.50 would be formatted as $768336.50.
Ex #3: 768336.49999999 would be formatted as $768336.50.
Ex #4: 768336.50000000 would be formatted as $768336.50.
Ex #5: 768336.50000001 would be formatted as $768336.50.
Ex #6: 768336.45500000 would be formatted as $768336.46.
Ex #7: -768336.45500000 would be formatted as -$768336.46.
%s string (char* or string literal)
%c character (int, short, or char, between 0 and 127) expressed as its corresponding ASCII character
%% a single percent sign (no parameter)

For each occurrence of any of the above codes, your program shall print one of the arguments (after the format) to mintf(…) in the specified format. Anything else in the format string should be expressed as is. For example, if the format string included "%z", then "%z" would be printed. Likewise, a lone % at the end of the string would also be printed as is (e.g., example #5 below) because anything that doesn't match one of the format specifiers above should be expressed as is.

Your code will also handle \n and other backslash escapes, but you will not need to do anything special. The C compiler converts those for you. If this is confusing, just ignore it, and then try putting a \n in the format string when calling your mintf(…).

You will use your print_integer(…) from HW02. You must finish HW02 before you begin this assignment.

Prepare

Read this assignment description carefully. (We will assume you have already read the Code Quality Standards and policies on homework and academic integrity.

Next, make sure you understand each of the topics below. As with HW02, we have suggested several concise references to help you get up to speed.

variadic functions
A variadic function is any function that takes a variable number of parameters. You may have noticed how printf, unlike most C functions you have used, can take any number of additional parameters, after the initial format string. You don't need to know this deeply, but you will need to look up the syntax, and also understand how a program determines the number of arguments. This page has a good overview of variadic functions, and a working example. We have another working example in the Q&A below. (Reminder: Learn from their example but do not copy it.)
More information can be found by typing man va_arg from bash.
printf
Make sure you understand the %d, %x, %o, %s, and %c format codes. Try writing very small programs with them, and make sure you can predict the output. See pages 418, 677, and the inside back cover of your textbook or the links on the Resources page.
More information can be found by typing man 3 printf from bash.
Differences between mintf(…) and printf(…)
  • mintf(…) supports %$ but printf(…) does not.
  • mintf(…) adds a prefix ("0x") to %x but printf(…) does not.
    For example, mintf("%x", 768336) will print 0xbb950 but printf("%x", 768336) will print bb950.
  • mintf(…) supports %b but printf(…) does not.
    Some non-standard variants of C do support %b but we are concerned with standard ISO C99 in this class.
  • printf(…) supports many format specifiers that mintf(…) does not (e.g., %o, %p, %f, %e, %u, etc.).

Instructions

Start by getting the files. Type 264get hw04 and then cd hw04 from bash.

You will find only one file: mintf.h. That is the header file. It defines the signature of two of the functions you will implement: mintf(…) and print_integer(…).

You will be creating three new files: mintf.c, test_mintf.c, and expected.txt. There is no starter code (other than the header file).

mintf.c is where your mintf(…) and print_integer(…) implementations will go. Copy your print_integer(…) from HW02 into it. Copy the function signature for mintf(…) from mintf.h into mintf.c. Make sure all of the following headers are included at the top of your mintf.c. (Type these manually into your file.)

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "mintf.h"

test_mintf.c will contain a main(…) function that will test your mintf(…) and print_integer(…). It must exercise all of the functionality in those two functions. For this homework, that means that in the course of running your test_mintf.c file, every line of code in your mintf.c should be executed at some point. To do this, you simply have several mintf(…) that include all of the format codes above, including a variety of valid values, including positive integers, negative integers, 0, strings, and an empty string. It should also have a few print_integer(…) statements to test that on its own. This will give you a very simple way to know for sure if your code works.

Use test-driven development to do this assignment incrementally. See below.

expected.txt will contain the expected output from running your tests in test_mintf.c. It will be a simple text file.

To test if your code works perfectly, you will run the following:
gcc test_mintf.c mintf.c -o test_mintf
# compile your test together with your mintf.c to create an executable called test_mintf

./test_mintf > actual.txt
# run your executable and send the output to a file called actual.txt (That filename is arbitrary.)

diff expected.txt actual.txt
# compare the actual output with the expected output using the diff command

The diff command prints the differences so if you see any output at all, then your test failed. If you see no output, then it passed.

Here's a shortcut version of the above:

gcc mintf.c test_mintf.c -o test_mintf && diff expected.txt <(./test_mintf)>

The first part (gcc …) compiles the code. ▒ && ▒ means to do the first part and then, if it succeeded (i.e., no errors), do the second part. The second part (diff …) compares the contents of your expected.txt with the output from running ./test_mintf.

Use test-driven development (TDD) with these steps

For this assignment you are required to follow the TDD progression below, in order, from beginning to end. You must submit after every numbered step below. Additional submissions (i.e., between the required submissions) are fine, as long as you are following the sequence shown, in order, from beginning to end.

The goal here is for everyone to learn how to use TDD to make programming projects smoother and more efficient, while reducing your risk of long, arduous bugs. This requires a shift in thinking. It will help you, especially as assignments get more challenging (later this semester and in your future endeavors). Some may be tempted to ignore the purpose and try to game the system to get full credit anyway; please resist that temptation. Many past students have reported that TDD helped them tremendously once they got used to it.

1. Add test to test_mintf.c: empty string (not even a '\n')
Add expected output to expected.txt: (empty)
Add to implementation in mintf.c: (nothing)
Compile. Test. Debug (as needed to ensure that tests 1–1 pass and code is clean}. Submit.
expected.txt and body of main(…) in mintf.c should be empty.
2. Add test to test_mintf.c: non-empty string (ending with a '\n')
Add expected output to expected.txt: one line: the string printed by your test
Add to implementation in mintf.c: Add just enough code to your mintf(…) to make this test pass—and no more.
Compile. Test. Debug (as needed to ensure that tests 1–2 pass and code is clean}. Submit.
expected.txt will be 1 line. Body of main(…) will be ≈3 lines.
3. Add test to test_mintf.c: a string containing one format code: %s
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 3—and no more
Compile. Test. Debug (as needed to ensure that tests 1–3 pass and code is clean}. Submit.
4. Add test to test_mintf.c: a string containing one format code: %%
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 4—and no more
Compile. Test. Debug (as needed to ensure that tests 1–4 pass and code is clean}. Submit.
5. Add test to test_mintf.c: a string containing one format code: %d
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 5—and no more
Compile. Test. Debug (as needed to ensure that tests 1–5 pass and code is clean}. Submit.
6. Add test to test_mintf.c: a string containing one format code: %x
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 6—and no more
Compile. Test. Debug (as needed to ensure that tests 1–6 pass and code is clean}. Submit.
7. Add test to test_mintf.c: a string containing one format code: %b
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 7—and no more
Compile. Test. Debug (as needed to ensure that tests 1–7 pass and code is clean}. Submit.
8. Add test to test_mintf.c: a string containing one format code: %c
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 8—and no more
Compile. Test. Debug (as needed to ensure that tests 1–8 pass and code is clean}. Submit.
9. Add test to test_mintf.c: a string containing one format code: %$
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 9—and no more
Compile. Test. Debug (as needed to ensure that tests 1–9 pass and code is clean}. Submit.
10. Add test to test_mintf.c: multiple format codes.
Add expected output to expected.txt: expected output from the new test
Add to implementation in mintf.c: just enough code to pass test 10—and no more
Compile. Test. Debug (as needed to ensure that tests 1–10 pass and code is clean}. Submit.
This step might not require additional code. But don't worry about testing for it until this last step.

You might be done after completing those steps—but probably not. You should add more tests to check for bugs. Remember: TDD ≠ testing. Test-driven development is a method of development that uses tests to guide your progression. A benefit of TDD is that it results in creating some tests, but those tests are not likely to be sufficient to detect all bugs. For that, you need to switch your focus to testing (for its own sake).

For each parameter (or other input) sure you have covered all..

You may include your complete print_integer(…) from the beginning. But when creating your mintf(…), you must created it incrementally using the steps above, in the order shown.

Additional submissions—i.e., between the required submissions—are fine, and will not affect your score, as long as you are following the sequence above, in order, from beginning to end.

Requirements

  1. Your submission must contain each of the following files, as specified:
    file contents
    mintf.c functions
    print integer(int n, int radix, char✶ prefix)
    return type: void
    Print the number n to the console (stdout) in the specified number base (radix), with the prefix immediately before the first digit.
    • radix may be any integer between 2 and 36 (inclusive).
    • For values of radix above 10, use lowercase letters to represent the digits following 9. For example, print_integer(165, 16, "") should print “a5”. (The number one-hundred sixty-five would be written as “a5”) in hexadecimal, i.e., base 16.) the number "one-hundred sixty-five".
    • print_integer(…) should not print a newline ('\n' or '\r'). For example, print_integer(123, 10, ""); print_integer(-456, 10, "") should print "123-456".
    • More examples are given in HW02.
    mintf(const char ✶format, ...)
    return type: void
    Print format with any format codes replaced by the respective additional arguments, as specified above.
    • %d should work with any int between INT_MIN and INT_MAX.
    mintf.h declarations
    declaration of print_integer(…), mintf(…)
    test_mintf.c functions
    main(int argc, char✶ argv[])
    return type: int
    Test your mintf(…).
    • Your main(…) must return EXIT_SUCCESS.
    • Note: EXIT_SUCCESS is a constant symbol for 0.
    expected.txt output Expected output from running your test_mintf.c.
  2. Your test_mintf.c must exercise all functionality. For example, testing for mintf(…) should cover all format codes and negative numbers, and so forth. Likewise, testing for print_integer(…) should include any radix between 2 and 36, largest possible n, smallest possible n, and so forth.
  3. For %d, %x, and %b, your program should handle any valid int value on the system it is being run on, including 0, positive numbers, and negative numbers.
  4. Your code may not make any assumptions about the size of an int.
  5. Your test_mintf.c should work—and give the same output—with any correct mintf.c, and likewise for your mintf.c.
  6. For negative numbers, print the "-" before the prefix (e.g., "-$3.00" not "$-3.00", "-0x12ad" not "0x-12ad").
  7. Only the following external header files, functions, and symbols are allowed in your mintf.c. That means you may use printf(…) in your test_mintf.c but not in your mintf.c. You may use fputc(…) and stdout in either one (or both).
    header functions/symbols allowed in…
    limits.h INT_MAX, INT_MIN test_mintf.c
    stdarg.h va_list, va_start, va_arg, va_end, va_copy mintf.c, test_mintf.c
    stdbool.h bool, true, false mintf.c, test_mintf.c
    stdio.h fputc, stdout, fflush mintf.c, test_mintf.c
    stdio.h printf test_mintf.c
    assert.h assert mintf.c, test_mintf.c
    stdlib.h EXIT_SUCCESS, abs mintf.c, test_mintf.c
    All others are prohibited unless approved by the instructor. Feel free to ask if there is something you would like to use.
  8. Repeat: Do not call printf(…)
  9. Submissions must meet the code quality standards and the policies on homework and academic integrity.

How much work is this?

Parsing the format string may feel like a puzzle. Think it through before you start writing a lot of code. The rest will involve a modest amount of code. Expect to do plenty of testing and debugging to get this right.

The instructor's mintf(…) and print_integer(…) are 51 and 20 sloc*, respectively. cloc reports 75 sloc for the whole file.
* sloc = "source lines of code" (excluding comments and blank lines)

Examples

These are to help you understand the spec. Your test cases must be your own. Do not copy these (even with minor modifications).
1. Code: mintf("768336\n");
Output: 768336
2. Code: mintf("My favorite number is %d!\n", 768336);
Output: My favorite number is 768336!
3. Code: mintf("%d written in hex is %x.\n", 768336, 768336);
Output: 768336 written in hex is 0xbb950.
4. Code: mintf("%d written in binary is %b.\n", 768336, 768336);
Output: 768336 written in binary is 0b10111011100101010000.
5. Code: mintf("Chance of coalescent cloudburst: 0.375%\n");
Output: Chance of coalescent cloudburst: 0.375%
6. Code: mintf("Chance of coalescent cloudburst: 0.375%%\n");
Output: Chance of coalescent cloudburst: 0.375%
7. Code: mintf("%s the cat has only %d lives left.\n", "Orlicasta", 8);
Output: Orlicasta the cat has only 8 lives left.
8. Code: mintf("Orlicasta's shoes cost %$.\n", 768336.50);
Output: Orlicasta's shoes cost $768336.50.
9. Code: mintf("Orlicasta's bank balance is %$.\n", -768336.00);
Output: Orlicasta's bank balance is -$768336.00.
10. Code: mintf("Excess parameters are ignored: %d\n", 768336, 768337, 768338);
Output: Excess parameters are ignored: 768336
This should take no extra effort to code.
11. Code: mintf("Insufficient parameters may lead to undefined behavior: %d %d %d\n", 768336);
Output: Insufficient parameters may lead to undefined behavior: 768336 ⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰
You do not need to test for this.
12. Code: mintf("Mismatched parameters may lead to undefined behavior: %d\n", "Orlicasta");
Output: Mismatched parameters may lead to undefined behavior: ⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰⍰
You do not need to test for this.
These are to help you understand the spec. Your test cases must be your own. Do not copy these (even with minor modifications).

Submit

To submit HW04 from within your hw04 directory, type 264submit HW04 mintf.c test_mintf.c expected.txt

Pre-tester

The pre-tester for HW04 has been released and is ready to use.

Q&A

  1. Is an int always in decimal (base 10)?
    No. See the next question.
  2. Does my print_integer need to deal with inputs that are specified in number bases other than decimal? For example, does my print_integer need to be able to convert from hex to binary?
    An int does not have a number base. It is just a value. The base (or "radix") of a number only refers to the way it is written, i.e., in your C code, or in the output of a program you write. For example, if n is the number of fingers on two hands, you could write that as 10, 0b1010, or 0xa, but it the same quantity no matter how you write it.

    When gcc reads your code for the first time, it interprets any integer literals (raw numbers in your code) according to how you write your code. Once your code has been compiled, the base that you used to write it becomes completely moot.

    Example: To gcc, the following are equivalent and have exactly the same effect.
    int n = 65;
    printf("n can be written as %d in decimal, as 0x%x in hexadecimal, or as %c if interpreted as an ASCII character.", n, n, n);
    int n = 0x41;
    printf("n can be written as %d in decimal, as 0x%x in hexadecimal, or as %c if interpreted as an ASCII character.", n, n, n);
    int n = 0b1000001;  // non-standard, but accepted by gcc; do not use for ECE 264
    printf("n can be written as %d in decimal, as 0x%x in hexadecimal, or as %c if interpreted as an ASCII character.", n, n, n);
    They all print the following:
    n can be written as 65 in decimal, as 0x41 in hexadecimal, or as A if interpreted as an ASCII character.
  3. What if there is a '\0' in the middle of the string?
    By definition, a string ends at the first '\0', so you would stop printing characters when you see the '\0'.
  4. What if mintf is called without any optional parameters?
    That is fine and normal. For example, the following should have the same effect:
    mintf("Hello world!\n");
    printf("Hello world!\n");
  5. What's the deal with variadic functions / va_arg / va_list?
    A variadic function is any function that takes an unknown number of optional parameters. The optional parameters are represented by three dots (e.g., int foo(int n, ...)). Those dots are part of the C language. The optional arguments are accessed using va_arg. You must call va_start once in that function, before the first use of va_arg. You must call va_end once in the function, after the last use of va_arg. You must include stdarg.h at the top of the file (i.e., #include <stdarg.h>). There is no way to know from va_arg how many optional arguments there are, so you need to use some other information (in this case the format string) to know how many there are (and hence how many times to call va_arg).

    Here's an example:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>                             // - This is required in any program that uses
                                                    //   variadic functions (additional arguments).
    void print_many_numbers(int num_of_nums, ...) { // - The ... stands for any number of arguments.
        va_list more_args;                          // - Get a handle to the additional arguments.
        va_start(more_args, num_of_nums);           // - This is required to access them.  Yes, it
                                                    //   is weird.
        for(int i = 0; i < num_of_nums; i++) {      //
            int next_num = va_arg(more_args, int);  // - Get the next additional argument.
            printf("%d\n", next_num);               // - Print it.
        }                                           //
                                                    //
        va_end(more_args);                          // - This is required after you're done.
    }                                               //   Yes, this is weird (too).
    
    int main(int argc, char* argv[]) {
        print_many_numbers(4, 768336, 768337, 768338, 768339);
        return EXIT_SUCCESS;
    }
    Here is the output:
    768336
    768337
    768338
    768339
    Other examples can be found in the articles in the Resources section.
    You may copy/adapt this snippet, but doing so is not recommended; your HW04 code will be quite different. Trying to start with this code will only make a mess. A better approach, if you want to use this snippet, would be to type it into a file, make sure it works, and make some modifications until you understand it well. Then, write your mintf(…) from scratch.
  6. Should hex digits above 10 be uppercase or lowercase?
    Lowercase.
  7. The specification states, "For each occurrence of any of the above codes, your program shall print one of the arguments (after the format) to mintf(…) in the specified format." What does this mean?
    It works just like printf. For each format code (e.g., "%d", "%x", etc) other than "%%" in the format string, your mintf should take one of the optional arguments and print it in the specified format. For example, mintf("I knew that %s was %d%% Martian because of the %$ tab for breakfast.", "Mason", 99, 6780) would print "I knew that Mason was 99% martian because of the $67.80 tab for breakfast.".
  8. The "0x" prefix for hexadecimal and "0b" prefix for binary output seem somewhat arbitrary. Where do these come from?
    These prefixes mimic the formats that gcc accepts when you specify raw integers in your code. The following statements are completely identical in the eyes of gcc.
    int n = 10;
    int n = 0xa;
    int n = 0b1010; // non-standard, but accepted by gcc; do not use for ECE 264
  9. Why do we need the prefix parameter to print_integer(…)?
    In a sense, it is a convenience. When printing a negative number that requires a prefix, the prefix should go between the minus sign and the first digit. For example, mintf("%$", -12.30) should print "-$12.30" not "$-12.30". Similarly, mintf("%x", -10) should print -0xa not 0x-a. Since your mintf(…) will most likely depend on your print_integer(…), having this prefix parameter to print_integer(…) will make your mintf(…) code simpler than it would be otherwise. If this still doesn't make sense, just think through how you would structure your mintf(…). You will most likely find that the only reasonable way to do it is to have a separate function like print_integer(…).
  10. What is the relationship between print_integer and mintf?
    Your print_integer will almost certainly be used by your mintf. For that reason, you may want to write your print_integer first.
  11. Will my print_integer be called directly by external code?
    Yes.
  12. How do I handle \n?
    See the note in the assignment description about this. If your code works for everything other than \n, then it should work for \n, too. You shouldn't need to do anything special. When gcc reads your code, it will automatically interpret the \n as ASCII character 10 (newline).
  13. What radixes (number bases) must my print_integer support?
    Your print_integer should support any value for radix between 2 and 36 (inclusive). For radixes above 10, it should represent digits beyond than 9 with lowercase letters. For example, print_integer(11, 16, "") would print "b" because b is the (11-9)th lowercase letter of the alphabet. Similarly, print_integer(20, 21, "") would print "k" because k is the (20-9)th letter of the alphabet.

    This converter may help you get a sense (and test your code).
  14. What is the difference between a "radix" and a "base"?
    They are synonyms for the same thing.
  15. What should my program do if someone passes the wrong number of parameters to mintf?
    You may assume that the caller will only pass the correct number of parameters. There will be no penalty if your mintf crashes or prints garbage in case there aren't enough parameters for the given format string.
  16. What should my program do if the type of a parameter does not match the format code (e.g., mintf("%d", "birthday")?
    You may assume that the type of parameters will match the corresponding format code. There will be no penalty if your mintf misbehaves in case of such a mismatch.
  17. Should I write #include "mintf.h" (quotation marks) or #include <mintf.h> (angle brackets)?
    Use quotation marks for header files in your project. Use angle brackets for standard header files. Thus, you should start your mintf.c with this:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include "mintf.h"
  18. May we modify mintf.h?
    No.
  19. May we turn in our own mintf.h?
    Yes, you may turn it in, but that file will be ignored. We will copy your files into an empty directory and then copy our test files, including mintf.h on top. Thus, any mintf.h you submit will be overwritten.
  20. How does mintf relate to printf?
    Your mintf will have the same behavior as printf for the format codes "%d", "%c", "%s", and "%%". For "%x" your mintf is different in that yours will automatically add the "0x" prefix, whereas printf does not. For example, mintf("%x", 10) prints "0xa" whereas printf("%x", 10) prints "a". In addition, your mintf will support two format codes that printf does not support at all: "%b" and "%$".
  21. What types can I use with each format code?
    For %d, %b, %$, or %x, you would normally pass an int, although a char or short will also work. For %s, pass a string. For %c, you would normally pass a char (e.g., 'c') but an int or short will also work, as long as they are in the range of 0 to 127 (inclusive). For %%, you would not pass any argument. This is implied by the table at the top of this assignment description.

    The underlying rule is explained more explicitly here, in one of the two recommended articles. For most people, these details shouldn't be necessary. If you were thinking of trying unsigned types or long types, don't.
  22. How can I test mintf("%c", …) with values for the %c of <32 or 127 (e.g., mintf("%c", 0))?

    If it works for values of 32 to 126 (the printable ASCII characters), it will work for the others. You do not need to test it on values 0…31 or 127.
  23. Can I add my entire print_integer(…) from the beginning, even though it contains code for printing numbers in other number bases?

    Yes.
  24. What if I do the entire assignment all at once, but then comment/uncomment out sections and submit many times, to meet the requirements, without actually learning/practicing TDD?

    First and foremost, you will undoubtedly spend more time, and have a greater risk of long, arduous bugs in the process, if you try to do the assignment in that manner. To discourage such an approach, if we detect it, you will be penalized. We are trying to help you learn and get better. This will be a new way of thinking for some of you, but it is in your best interests to embrace it and learn it. Please focus on learning, and not on gaming a system that is here to help you.
  25. How will you know if I followed the sequence, in order, from beginning to end?

    We will be checking all of your submissions. Your code should not pass the later tests until it passes the earlier ones. Also, your code should get bigger (i.e., more source lines of code) with each submission. We may also look for comments, strings, or other indications that someone is trying to sidestep the intended lesson.

    As long as you are following the TDD method and the steps given—in order, from beginning to end—you should not need to think about any of this. It is only there to catch the small proportion of students who may try to avoid challenging their way of thinking about how to build. That impulse is natural, but will not help them in the long run.

  26. What if I am genuinely trying to learn/practice TDD but I make an honest mistake that results in a penalty?

    We will look at that through the regrade process. As long as you were making an earnest, good faith effort to follow the intent—and not trying to game the system—you can get full credit.
  27. Instructions (↑) warn, “You cannot go back.” What does that mean?

    If you do the whole assignment and submit it, and then go back and start from the beginning to follow the instructions, you will get the penalty?

The Q&A section of HW02 answers many more questions, including how to handle INT_MIN.

Updates

- Updates may be added here later.