CS1010
Lab Guidelines
CS1010 (AY2017/8 Semester 1)
School of Computing, National University of Singapore

0 Introduction

There will be weekly take-home lab assignments, each consisting of 2 to 4 exercises. The main objective of these assignments is to provide feedback for you on your own learning. As they are primarily used for formative assessment, we have kept their weightage low -- 10% of your final grade, to encourage you, especially beginners, to work on your own without the fear of losing too many marks. With this, we hope that you would be motivated to do all these programs all by yourself instead of resorting to copying or asking for help from others.

Copying others' programs or relying on others to help you on these assignments will only offer short-term reprieve. When Practical Exam (PE) time comes, your inadequancy will be exposed and the consequence would be dire.

You are advised to (1) spend some time thinking before you begin coding, (2) practise incremental coding and (3) test your programs thoroughly.

  1. Remember to spend some time thinking about the algorithm for each exercise and write out the pseudo-code on your own before you start typing in your program.

  2. Incremental coding means do NOT type in the whole long program in a single session and then compile it. Instead, type your program in bits and pieces and compile it incrementally. Try to maintain a compilable program even while you are working on it. Submitting a compilable program that partially works is better than submitting an un-compilable one; this is especially important for your PEs.

  3. You should test your program thoroughly with your own test data before submission. Do NOT use the CodeCrunch as your testing or debugging tool. As we progress, we will reduce the number of submissions.

Please note that:

1 Rules and Instructions

  1. The lab assignment is released on the CS1010 website, and its deadline given. You are to submit ALL exercises in that lab via CodeCrunch before the deadline.

  2. Deadlines are to be observed strictly. Late submission will NOT be accepted.

  3. Programs are to be submitted via CodeCrunch only. Programs submitted through other means, such as emails, will NOT be accepted.

  4. Only the final submission of each exercise will be graded.

  5. For each exercise, typically 3 sets of test data are applied to your program upon submission. After the deadline, your program will be further tested typically on 10 sets of unknown test data.

  6. If you have doubts on the task statements, you may raise them on the IVLE forum. But before that, please read through the task statements carefully first.

  7. Some labs may expressly disallow the use of certain syntax. Generally, using syntax or statements which are not yet covered either in class or in the lab handouts is strongly discouraged. The lab assignments are designed such that you should not need to do so (even though doing so may result in your program being shorter or more efficient). If the objective of the assignment is undermined, the penalty for using such forbidden syntax will be heavy. If in doubt, please ask for clarification.

  8. Before the deadline, you are NOT to post your or other's lab programs, complete or partial, on the IVLE forums or any publicly assessible online site.

  9. You are NOT to copy from others, or allow others to copy your programs. Refer to Penalty for Plagiarism below.

  10. For each lab assignment, an Attempt Mark of 1 mark is awarded, as spelt out under Grading Guidelines below. This Attempt Mark counts towards your final grade.

  11. As formative feedback, a Feedback Mark for your program will also be given and sent to you after grading. This Feedback Mark is NOT counted towards your grade. It indicates what you would have received if it was a test.

2 Penalty for Plagiarism

See NUS Plagiarism Notice.

A student who is caught copying program from others, or knowingly allowed his program to be copied, will have his Attempt Mark revoked for that lab assignment and his identity noted. In the case of a repeat offender, he will be referred to the School for disciplinary action.

Lab assignments are to be attempted individually so reason such as collaboration, intentional or arising from convenience (such as sharing of laptop), will not be accepted.

Should there be any dispute or appeal, please consult your respective lecturer.

3 Grading Guidelines

The 1 mark Attempt Mark is awarded to you for each lab assignment if you satisfy ALL the following conditions:

For your Feedback Mark, below are the grading guidelines given to the graders. Each program has a maximum of 100 marks. Unless otherwise stated. the correctness of a program constitutes 60 marks, while design andstyle make up the other 40 marks.

3.1 Correctness

CodeCrunch determines program correctness by feeding a set of test data into your program and comparing your output with the correct output. The test cases have equal weights. Therefore, if N test cases are used, then each test case is worth 60/N marks. N is usually 10.

If your program cannot be compiled (and hence it cannot be run), you will get zero mark for correctness.

Hence, each time after you edit your program, make sure you compile, run and test it. As CodeCrunch grabs your source code (.c) and not your executable code (.exe), if you didn't test it and your program contains compilation error, CodeCrunch will not be able to compile your source code, and you will get zero mark for correctness.

If you hardcode your output, you will get zero mark for correctness, even though your output may happen to be correct. (Hardcoding the output means, for example, you write "printf("100\n");" and hope that one of the test data's answer is indeed 100. Even if it is so,you won't get the mark.)

3.2 Design/Style

Style constitutes 20 marks and design constitutes another 20 marks for Lab #1. From Lab #2 onwards, style constitutes 15 marks and design 25 marks.

In general, style refers to typographical and documentation issues such as indentation and spacing, naming of variables, readability, proper comments, etc. whereas design refers to choice of algorithm, use of appropriate programming constructs, efficiency, modular programming, etc. Sometimes, when a certain item may not fit into style or design category, it is arbitrarily categorised under either one for convenience.

A negative marking scheme will be used for marking design and style. Your grader will manually check your program and deduct marks according to the points listed in this document. For some lab assignments, there will be additional guidelines which are specific to the assignment. The grader has the authority to justify and deduct marks for problems in a program which are not covered in the guidelines.

Note that the following are just general guidelines. For each lab exercise, there might be additional specific guidelines given to the grader.

Style

Design

3.3 Appeals

Should any discrepancy, dispute or queries arise in grading, the students should first approach their respective discussion leader for clarification. The discussion leader should exercise his/her good judgment in granting appeals, bearing in mind the marking consistency among other programs with similar issues. If the appeal cannot be resolved with the discussion leader, the lecturer shall be the final arbiter in deciding an appropriate resolution.

4 Typographical Style

The main goal of the recommendations here is to improve readability and thereby the understanding and maintainability of the code. Violations to this guide are allowed if they enhance readability.

4.1 Declare related variables in a common statement

For example,

// PREFERRED
double x,y,z;   // Coordinates of a particle

As opposed to:

// AVOID
double x;
double y;
double z;

4.2 Give variables descriptive names

Use descriptive names for variables so that their meanings are immediately clear when they appear in the code. For example, "int coins;" is an appropriate variable but not "int c;". Avoid using single character for variable names.

There are some exceptions, however, as shown below:

4.3 Shorten variable names with naming conventions

Despite the recommendation for descriptive names, identifiers can be short yet descriptive by using abbreviations and/or common naming conventions. For example,

// AVOID
MAXIMUM_LENGTH, numberOfElements, currentNodePointer, table_number

can be shortened without losing their descriptive form:

// PREFERRED
MAX_LEN, nElems, pcurr, table_num

4.4 Avoid negated variable or function names

Negated variables often results in hard-to-read double-negatives in an expression like !isNotError.

// AVOID
isNotError, isNotFound, isNotValid, cannotOpenFile

// PREFERRED
isError, isFound, isValid, canOpenFile

4.5 Use #define to define constants for magic numbers

Avoid direct use of magic numbers. Constant literals which have special meanings should be named and its named identifier should be used in its place. For example:

// AVOID
for (i=0; i<100; i++) {
    ...
}

// PREFERRED
#define MAX_LEN = 100; 
...
for (i=0; i<MAX_LEN; i++) {
    ...
}

4.6 Identifiers for constants should be in uppercase using underscore to separate words

MAX_ITERATIONS, MAX_LEN, GOLDEN_RATIO, COLOR_DEFAULT, PI

4.7 Use consistent indentation to emphasize block structure

Code should be properly and neatly indented to emphasize the nested logical structure of the program. An indentation of 4 spaces is recommended (8 is too wide and 2 is too cramp).

Every block that follows a for, while, if-else, switch, do-while statement must be indented from its enclosing block.

Comments within a block should follow the indentation level of its enclosing block. For example,

for (i=0; i<3; i++) {   // Trailing open-braces is OK

    // Comments should be indented too

    while (j != i)     // Leading open-braces OK as well
    {
        // More indented comments
        printf("Hello\n");
    }
}

The following are wrong ways to indent the comments.

for (i=0; i<3; i++) {   

// This comment should be indented and aligned with the while statement.

    while (j != i) {
    // This comment should be aligned with the printf statement.
        printf("Hello\n");
    }
}

4.8 Positions of open and close braces

There are two camps on the position of open braces. The following shows the "trailing open braces":

for (i=0; i<3; i++) {   // Trailing open-brace

    while (j != i) {    // Trailing open-brace
        printf("Hello\n");
    }
}

The following shows the "leading open braces". The leading open brace must be aligned with the block of the construct it is in:

for (i=0; i<3; i++) 
{  // Leading open-brace

    while (j != i) 
    {  // Leading open-brace
        printf("Hello\n");
    }
}

Both styles are acceptable, but you should be consistent and should not mixed both styles in a single program.

For close braces, they should be leading close braces aligned with the block of the construct. Close braces should NOT be trailing as that would make it hard to spot them.

4.9 Comment major code segments adequately

Major segments of code should have explanatory comments. A major segment may be a loop block or a function block.

4.10 Comment complicated logic, expressions, or algorithms

An "if" block with a complex condition or an expression that is hard to understand should have explanatory comments. For example,

// Check and reject out-of-bounds indices
if (k < 0 || k >= MAX_LEN) { 
    return -1;
}

4.11 Avoid superfluous comments

A comment such as:

i++; /* add one to i */

serves no purpose, adds clutter to a program and does more harm than good.

4.12 Blank lines

It is good to add a blank line between two functions, or two long segments of code for readability.

// This function ...
int f(int x) {
    // body
}

// This function ...
int g(double y) {
    // body
}
// Statements 1 to 10 belong to a sub-task
statement1;
statement2;
   :
statement10;

// Leave a blank line for readability
statement11;
statement12;
   :

However, guard against the use of excessive blank lines. Double blank lines should be used sparingly, if at all. Triply blank lines, or more, should not be present.

4.13 Long lines

If a line (be it a statement or a comment) is too long (more than 80 characters), do not let it run through the screen and wrap around. Instead, split it into a few lines.

    // This is not advisable
    printf("%s: name = %s; age = %d; gender = %c\n", header, player.name, player.age, player.gender);

    // This is preferred
    printf("%s: name = %s; age = %d; gender = %c\n", header;
           player.name, player.age, player.gender);

5 Design Considerations

As programs get more complex, program design becomes increasingly important. Decomposing a complex program into smaller, more manageable units and the design of the interfaces between the units are fundamental to good programming. Generally, the constituents of a program unit should be highly cohesive (5.1), and the coupling between program units should be clean and minimal (5.2). Algorithmic logic should be easy to understand (5.4). The program should also be easy to setup and its usage should be intuitive (5.3).

5.1 Build program units which are highly cohesive

(Students to note: You may skip this section for a start, and return to read this at a later point of time.)

Each function should consist of closely related elements. If a function consists of a mixed-bag of unrelated elements, it often indicates a need to modularize the code into further cohesive program units.

As a general rule, each function should do only one thing. This should be done so that the conceptual unit can be understood easily. Sometimes it will be convenient to do two things in a function because you are working on the same data. Try to resist this temptation. Make two functions if you reasonably can.

Often the naming of the function indicates its cohesiveness. Does the method only do what its name says, or does it do more than that? If you find that a complete name for one of your method is like openInputAndReadVectorAndComputeSum(..), it is time to break the multi-tasked function into its sub-constituents.

Segments of code which are repeated should be abstracted into a function. This not only results in shorter programs but also makes it easier to maintain and read. The abstracted function then forms a cohesive unit by itself.

5.2 Avoid tight coupling between program units

(Students to note: You may skip this section for a start, and return to read this at a later point of time.)

If changing one function in your program requires changing the main function, then a coupling exists between the two functions. One indicator of program quality is the amount of coupling between your program units.

Coupling indicates a dependency between source codes. Reducing this dependency improves the quality and maintainability of your program.

5.3 Avoid user-unfriendliness

Is the program particularly difficult to use?

5.4 Unnecessarily complicated logic

Simplicity is a virtue. Wherever possible, your program should be simple, compact, and easy to read. For example, long chains of nested if-else statements can often be replaced with a more compact form for evaluating the logic. If you find that the logic in your code is getting very unwieldy, rethink and rewrite it.

5.5 Use of forbidden syntax

Some labs may expressly disallow the use of certain syntax. Generally, using syntax or statements which are not yet covered either in class or in the lab handouts is strongly discouraged. The lab assignments are designed such that you should not need to do so. If the objective of the assignment is undermined, the penalty for using such forbidden syntax will be heavy.

5.6 Use of inappropriate syntax or data types

For instance, if all the inputs to a problem are integers, the program should refrain from introducing any variables of floating-point type. Similarly, it should refrain from invoking any functions which involve floating-point types.

Other examples including using while instead of for when the number of iterations is easily determined before the loop.

5.7 Gross inefficiency

Although in CS1010 we are not too concerned about order-of-growth efficiencies, any obvious inefficiencies which can easily be avoided must not be present, or they will be penalised.

5.8 Checking for data validity

It is not easy to write fool-proof and robust programs from the start. Unless otherwise stated, you may assume that the input data used to test your programs are all valid and are according to the problem specification. Hence, you do not need to write extra code to check for data validity unless otherwise stated. As we go along, we may include such requirement once you gain more programming experience.




Last updated: 15 September 2017