CSC230 Homework 2

This homework is to be done individually.

Only use the following standard library functions: getchar(), putchar(), printf(), pow(), and exit(). At some point, you will be able to use any standard library function in any program, without restrictions.  Starting off, however, I want you to program some simple functions without using standard library equivalents.

Additionally, this assignment requires implementation of a Finite State Machine (FSM) -- be sure to review the FSM packet for an overview of FSMs and an example of the Horner's rule implementation in Java. You will need to adapt the Horner's rule algorithm to read in integers and floating point numbers.

Note: this is the first semester this particular assignment is being used. Please report any unclear explanations, mistakes, or issues to the instructors.

Learning Outcomes

Program - screw_diameter.c

There are several kinds of screws in the world, without which society surely would crumble. They can be broadly separated into two categories: screws designed to fasten directly into solid material (wood, masonry, sheet metal, drywall, etc.), and screws designed to mate with corresponding female threading (as in a nut or threaded hole on a machined part). The latter category are called machine screws, and are the focus of this assignment.

To use a machine screw with a nut on the other end, one drills a hole through the materials to be fastened, with the hole diameter being slightly larger than the threads of the screw to be used, so that the screw drops in easily. Then the nut can be tightened on the other side, compressing the materials together. This hole size is called the major diameter of the screw.

There are multiple competing standards for machine screws. The most prominent are the Unified Thread Standard (which, despite the name, is basically used in just the U.S.) and the metric standard (used by the rest of the world). In the U.S. standard, screws are identified by "screw number", which is written starting with a number sign ('#', also called a pound sign, but NEVER called a 'hashtag'). For example, standard computer cases are fastened with #6 screws. In the metric standard, screws are identified by a designator starting with a capital 'M'; the number that follows is the major diameter in millimeters. For example, standard computer DVD-ROM drives are fastened with M3 screws. (Yes, this means that computer cases mix metric and U.S. fasteners...we live in a scary world.)

You will implement a program that will calculate the major diameter of machine screws for the major U.S. and metric screw standards, presenting your answer in both inches and millimeters.

Program Requirements

Program Input

The screw diameter calculator will prompt the user for a screw designation in either U.S. "screw number" format or metric "M" format. The program will begin by displaying a usage banner, then a simple "> " prompt (note the space after the arrow).

It is important to print this content EXACTLY, as we use automated grading, which is expecting this precise output. Metric/US screw hole calculator.\n Input a U.S. screw number starting with '#' or a metric designation starting with 'M'.\n > At this prompt, the user may input:

Floating Point Input

Metric designators can include a floating point number after the 'M'. A valid floating point number has the following characteristics:

If the screw diameter provided by the user is invalid (e.g., contains other characters, has more than one decimal separator, etc.) the error message "INVALID METRIC SIZE\n" is printed and the program exits with an error code of 2.

Integer Input

The U.S. screw number (after the number sign) is an integer. A valid integer has the following characteristics:

If the screw number provided by the user is invalid (e.g., contain other characters, has a decimal separator, etc.) the error message "INVALID U.S. SCREW NUMBER\n" is printed and the program exits with an error code of 3.

Valid Values

After a correctly parsable value is received, it should be checked for validity.

If a value fails these checks, "INPUT OUT OF BOUNDS\n" should be printed, and the program should exit with an error code of 4.

Major Diameter Calculation

The major diameter is the diameter to the outermost points of the threads of the screw:

The algorithm to calculate it depend on the screw standard being used.

Unified Thread Standard

The Unified Thread Standard has history going back to the railroad standardization of the 1800s and automobile development in the 1910s, being ratified in its current form in 1949. As such, it's one of those really old standards that makes no sense. To calculate the major diameter for a given screw number, use the equation:
Major diameter = Screw # × 0.013 in + 0.060 in

For example, a #5 screw has a major diameter of 5*0.013+0.060 = 0.125 inches.

Note: the constants above can be considered 'foundational', meaning that they won't be considered "magic numbers" if (a) each appears only once in your code, (b) they exist solely in this equation, and (c) the equation is documented as being part of the Unified Thread Standard.

(Side note not affecting this assignment: there's such as a thing as screw numbers less than zero, but rather than use negatives, they decided to just add more zeroes. So there's a #00 and #000 screw. These are NOT to be considered in this assignment.)

Metric Standard

The metric standard is very easy. The number after the 'M' is the major diameter in millimeters, so an M5 screw has a major diameter of 5 mm.

Output

Print the result of the calculation using the format specifier: "Major diameter: %.3f\" (%.1fmm)\n". This will round the result of your calculation to the thousandth of an inch and tenth of a millimeter.

Below are three example runs: $ ./screw_diameter Metric/US screw hole calculator. Input a U.S. screw number starting with '#' or a metric designation starting with 'M'. > 3 INVALID INPUT $ ./screw_diameter Metric/US screw hole calculator. Input a U.S. screw number starting with '#' or a metric designation starting with 'M'. > #3 Major diameter: 0.099" (2.5mm) $ ./screw_diameter Metric/US screw hole calculator. Input a U.S. screw number starting with '#' or a metric designation starting with 'M'. > M3 Major diameter: 0.118" (3.0mm)

Design

We have provided a template for you. This template does require additional functions beyond main(). We have provided the prototypes of those functions for you. You will need to finish the prototype functions, which are listed below. You may write additional functions if you feel they are needed, but you MAY NOT modify the provided function headers and you MUST implement functionality in the provided functions.

Implementation

Getting Started

Start by cloning the provided CSC230 GitHub repo in your local AFS (or development space) using the following commands:

$ unset SSH_ASKPASS
$ git clone https://<unity_id>@github.ncsu.edu/engr-csc230-summer2015/<repo_name>.git

NOTE: Do not include the < and > symbols in the url.

This will create a directory with your repo's name. If you cd into the directory, you should see directories for each of the homeworks for the class. You'll want to do all of your development in 2_homework. If you do NOT see the 2_homework directory, enter the following command to make the directory:

$ mkdir 2_homework

Next, you will need to download the hw2_starter.tgz from the website into your 2_homework directory. You can use your browser to do this if you have your home directory mounted, else you can use the following command:

$ wget

Untar using the command:

$ tar xvzf hw2_starter.tgz

You will need to copy the template file into a file with the appropriate name for automated grading:

$ cp screw_diameter_template.c screw_diameter.c

...edit screw_diameter.c, compile it, test it, etc...

You'll also need to create your own test case, which consists of an input file and an expected output file. These files are extensionless. We recommend creating them on the Common Platform since some operating systems will add extensions to files automatically. To create an extensionless file, use the command:

$ touch my_awesome_file

Then edit the file in your favorite text editor.

When you are ready to run the full suite of tests, execute:

$ chmod +x test.sh
$ ./test.sh

The first command, chmod, sets the permissions of test.sh to allow for execution. You only have to run this command once.

When you are ready to commit to your local repository, execute:

$ git add .
$ git commit -am "a meaningful message for future you"

When you are ready to submit to the remote repository for automated grading or teaching staff feedback, execute:

$ git push Note: it is totally safe and wise to do a git push every time you get a reasonable unit of functionality. This allows you to see your performance aganist the instructor tests, allows the instructors to see the evolution of your work, and provides a convenient backup snapshot of your code.

Follow the CSC230 style guidelines and comment as you create your program. Don't leave these activities to the last minute!

Hint: Keep in mind the differences between floating point and integer arithmetic, especially when considering integer division and rounding.

Console Input

We can use the Horner's rule algorithm, which incorporates a finite state machine (FSM), for reading in strings of characters and converting the input into a decimal number. See the FSM packet for an overview of FSMs and an example of the Horner's rule implementation in Java. You will need to implement the Horner's rule algorithm as part of the read_integer() and read_double() functions. Instead of processing a String you will process a line of input from the console, character by character, until the new line character ('\n') is reached. The read_integer() function considers only the integer portion of the Horner's rule implementation.

You do not need to catch cases where overflow or underflow of data types may occur with very large or very small inputs. You should let the overflow or underflow occur and then handle any additional error checking (e.g., bounds checking) after handling an entire line of input using the Horner's Rule algorithm.

Calculating Power

The C standard library includes a function for calculating power (just like the Math.pow() method in the Java API). The program can be implemented without the pow() function; the information below is if you want to use the pow() function. To learn more about the pow() function, enter the following command at the eos prompt:

$ man pow Note: This and other library functions pages are also documented here (and many other places online).

To use the pow() function, you must also include math.h:

#include <math.h>

Finally, when compiling your program, you must use the following command that will ensure that the math libraries are linked with with your code (that's what the -lm part of the command does):

$ gcc -Wall -std=c99 -lm screw_diameter.c -o screw_diameter

We have provided a Makefile that includes a command for compiling your program. To compile your program using the Makefile, execute the following command:

$ make screw_diameter

exit() Function

We will be using a new function: exit(). The exit() function is provided in stdlib.h (which means you need the statement #include <stdlib.h> in your code). The exit function will exit the program. The argument to the exit function is an integer value. A program that exits normally has an exit value of 0 (that's why the main function always returns 0). We can use non-zero exit values to signal an abnormal exit from the program. You can see the exit code from your program (or from any command run at the console) by running the command.

$ echo $?

Note that the echo $? command will only print the exit value of immediately previous command. Make sure that you run your tests using the order of the command specified in the testing section.

Magic Numbers

All "magic numbers" that you use must be defined as constants.

The definition of a magic number is a literal value used in your code that one may potentially want to change some day, or whose usage is frequent enough that naming it will add clarity. Examples from this assignment:

ValueIs it a magic number?Why?
Millimeters per inch Yes Even though it won't be changing, it may be used multiple places, and naming it adds clarity.
Constant parameters of the U.S. screw diameter formula Probably not Core values of formulas are often simply written inline, provided they are only used in a single place, their meaning is made clear, and there's no risk of them changing.
Basic mathematical values in the Horner's Rule implementation (2, 10, etc.) No You do not have to declare these as separate constants; their use is mathematically foundational and fairly obvious.

In the highly likely situation that you desire to add new constants, use a preprocessor #define macro, e.g.: #define CONSTANT_NAME 3

NOTE: Never call exit(...) without using a constant. i.e., never call exit(4) - instead use something like exit(INVALID_METRIC_RANGE).

Testing

When compiling your program, you must use the following command :

$ make screw_diameter NOTE: Running 'make clean' will remove the compiled binary and any output files.

The program output must match the provided output exactly for automated grading.  To facilitate grading the following commands will be used:

$ ./screw_diameter < input1 > actual1
$ echo $?
$ diff expected1 actual1

Note that the echo $? command will only print the exit value of immediate previous command. Make sure that you call the echo command immediately after executing your program to ensure that your exit code is correct.

A number of test cases for the screw_diameter program are provided. We have also provided a script, test.sh, that will execute all of the tests and report the results. There should be no difference between your actual output and the expected outputs.  Grading will test additional inputs and outputs, so you should test your program with inputs and outputs beyond the provided example. The test cases, testing script (e.g., test.sh), a template file, and Makefile are provided for you in hw2_starter.tgz. See the Implementation - Getting Started section for details about setting up your work environment and how to use hw2_starter.tgz.

test.sh: If your program does NOT pass the tests in test.sh then it will not be able to pass the teaching staff test cases. Use test.sh as a method to verify that at least the minimum requirements have been met for this assignment.

The details of the provided tests are:

Test ID Description Test Input Exit Code Expected Output
Test 1
Valid U.S. Screw (#10) input1 0 expected1
Test 2
Valid U.S. Screw (#0) input2 0 expected2
Test 3
Valid U.S. Screw (#12) input3 0 expected3
Test 4
Invalid U.S. Screw - negative number (#-1) input4 4 expected4
Test 5
Invalid U.S. Screw - large number (#13) input5 4 expected5
Test 6
Invalid U.S. Screw - decimal (#5.1) input6 3 expected6
Test 7
Invalid U.S. Screw - letters (#seven) input7 3 expected7
Test 8
Invalid U.S. Screw - letters (#12p4) input8 3 expected8
Test 9
Valid Metric Screw with no decimal (M3) input9 0 expected9
Test 10
Valid Metric Screw with decimal (M3.5) input10 0 expected10
Test 11
Invalid Metric Screw - zero size (M0) input11 4 expected11
Test 12
Invalid Metric Screw - negative size (M-1.3) input12 4 expected12
Test 13
Invalid Metric Screw - large size (M100.1) input13 4 expected13
Test 14
Invalid Metric Screw - two decimals (M10.1.1) input14 2 expected14
Test 15
Invalid Metric Screw - letters (M1q.4) input15 2 expected15
Test 16
Invalid Metric Screw - letters (M1.2z) input16 2 expected16
Test 17
Invalid input - letters (HOTDOGS!!!!) input17 1 expected17
Test 18
Invalid input - no prefix (10) input18 1 expected18
Test 19
Invalid input - lowercase (m2.4) input19 1 expected19

Writing Your Own Test

You will be submitting a system test for the screw_diameter program. Your test case will consist of two files: input_s and expected_s. Your test must include an input value that will cause an overflow or underflow of the screw number or metric screw size for your program. You are restricted to exit codes of 0 or 4, which implies that your input must be processed by the Horner's Rule algorithm, but the result from the overflow or underflow can be in a valid or invalid range. If you use an exit code other than 0, you must change the exit code value at line 63 of test.sh (change the 0 to a 4 as appropriate).

While your test may pass on Jenkins (see below), we will also be evaluating the content of your test case for the possibility of overflow or underflow of one of the inputs. If you do not have an input that would cause an overflow or underflow, you will not earn points for the test case.

Checking Jenkins Feedback

We have created a Jenkins build job for you. Jenkins is a continuous integration server that is used in industry to compile, build, and test applications under development. We will be using Jenkins to compile, build, and test your homework submissions to GitHub, which will provide early feedback on the completeness (does your implementation meet the requirements) and quality (does your implementation correctly implement the requirements).

Your Jenkins job is associated with your GitHub repository and will poll or query GitHub every two minutes for changes. After you have pushed code to GitHub, Jenkins will notice the change and automatically start a build process on your code. The following actions will occur:

Jenkins will record the results of each execution. To obtain your Jenkins feedback, do the following tasks:

NOTE: Jenkins will NOT execute test.sh without evidence that you have run the tests locally. We require that at least one file starting with sd_aout* is pushed to GitHub for automated testing to run.

Instructions for Submission

The following files MUST be pushed to your assigned CSC230 GitHub repository:

By submitting the actual results from the tests, you will prove that you have tested your program with the minimum set of the provided acceptance tests. Automated grading will not run on your program without at least one generated actual result file (it doesn't mean your tests have to pass, just that you've attempted the tests locally before pushing to your repo).

Additional Considerations

Follow the CSC 230 Style Guidelines.  Make sure your program compiles on the common platform and Jenkins cleanly (no errors or warnings), with the required compile options.

There are certain learning outcomes and basic software engineering skills that this assignment is assessing. The following deductions may be applied to your submission as enforcement of good software engineering practices and assignment intentions:

-15 points for any compilation warnings. Your program must compile cleanly! (if it doesn't compile, you will not receive any credit for test cases or compilation)

-60 points for using other standard library functions other than getchar(), putchar(), printf(), pow(), and exit() or for writing code such that the provided tests pass but the program isn't generic enough to handle additional tests - which we will run! This means that you circumvented the intention of the assignment and receive no points for a correct implementation.

-50 points for NOT using the Horner's Rule algorithm to read in user input and create doubles and ints.

-10 points for files (screw_diameter.c, Makefile, test.sh, and all of the actual outputs generated through testing (actual*)) that are named incorrectly or missing.

-20 points for late work, even if you submit part of the assignment on time.

Make sure that you push your code to the GitHub repository provided for you! Pushing your code to GitHub is your submission!

There is a 24 hour window for late submissions.  After the main deadline, continue to submit to GitHub. We will use the last commit to GitHub before the late deadline for grading and the timestamp of that commit will determine a deduction, if any.

Rubric

screw_diameter.c

+15 for compiling on the common platform with gcc –Wall –std=c99 -lm options

+60 for passing teaching staff test cases (all tests will be done using a diff as demonstrated above and checking the exit codes), which demonstrates a correct implementation.

+10 for a test case that causes overflow or underflow on the input for screw number or metric size (the test is in files input_s and expected_s)

+20 for comments, style, and constants

-5 for meaningless or missing comments

-5 for inconsistent formatting

-5 for magic numbers

-5 for no name in comments

Total: 105 points

Global deductions FROM the score you earn above:

-15 points for any compilation warnings. Your program must compile cleanly! (if it doesn't compile, you will not receive any credit for test cases or compilation)

-60 points for using other standard library functions other than getchar(), putchar(), printf(), pow(), and exit() or for writing code such that the provided tests pass but the program isn't generic enough to handle additional tests - which we will run! This means that you circumvented the intention of the assignment and receive no points for a correct implementation.

-50 points for NOT using the Horner's Rule algorithm to read in user input and create doubles and ints.

-10 points for files (screw_diameter.c, Makefile, test.sh, and at least one of the actual output files generated through testing (actual*)) that are named incorrectly or missing.

-20 points for late work, even if you submit part of the assignment on time.

You can not receive less than a 0 for this assignment unless an academic integrity violation occurs.