Advanced C Programming

Autumn 2015 :: ECE 264 :: Purdue University

This is for Fall 2015 (6 years ago)
Due 8/31



This assignment has the following goals.

  1. Learn to use the Vim text editor to efficiently move around a code file and make changes.
  2. Practice improving the style of poorly formatted code.


Before you start, you will need to set up your environment.

  1. Connect to via SSH.
    1. Windows: Download and install PuTTY (i.e., putty-0.65-installer.exe). Then, start PuTTY and enter in the Host Name field. Click Open to connect. Log in with your Purdue account.
    2. Linux or Mac: Open the console (aka "Terminal") and enter ssh .
  2. Make sure you are using the bash shell (and not csh). Most likely, you are already using bash.
    1. Enter: ps
    2. If you see bash, you're fine.
    3. If you see csh, then enter chsh -s and follow the prompts. When asked for your new shell, enter /bin/bash . Log out (exit) and log back in.
  3. Set up your bash and vim configuration files (.bashrc, .bash_profile, and .vimrc).
    1. If you don't already have one and/or don't have a preference, then enter the following commands to install starter files provided by the instructor. You can preview them here: .bashrc, .bash_profile, and .vimrc. If you are using PuTTY, you can paste these in by right-clicking the screen.
      cp -i ~ece264p0/share/.bashrc ~
      cp -i ~ece264p0/share/.bash_profile ~
      cp -i ~ece264p0/share/.vimrc ~
      chmod 600 .vimrc .bashrc .bash_profile
      The first three commands copy the files from a shared directory. The last command sets the permissions so others can't see their contents.
    2. If you already have a .bashrc file you like, then simply add the following two lines:
      export PATH=$PATH:/home/shay/a/ece264p0/share/bin
      alias gcc='gcc -g -Wall -Wshadow --std=c99 --pedantic'
      The first command tells bash to search in our shared script directory so that it can find the 264get and 264submit commands. The second command creates an alias so that simply typing gcc will automatically include options to include debug information for gdb, warn about potential problems, and use the C99 standard.
  4. Log out and log back in to let your .bashrc changes take effect.
  5. Create a new directory for your 264 files. We will assume your directory is called 264.
    mkdir 264
    cd 264
    The first command creates a directory called 264. The second command changes into it.

Go through vimtutor

Before you begin the homework, you should go through a Vim tutorial to get the basics. At the command line, just enter vimtutor and follow the instructions.

This may take an hour or two, but it will make the rest of this much easier. The Resources page has some web-based options, which look nicer but are less complete.

Get the homework files

To fetch the files for this assignment, enter 264get hw1 from bash. That should create a new directory called hw01. To see the directory enter ls . Next, enter cd hw01 to enter the directory and start working.

Do the homework

Here's the scenario: You have been given a partially-working calculator for ECE 264 grades. However, the code is very messy. First, you will fix the formatting. Next, you will complete the code. Finally, you will finish the code so that it prints out a course grade.

For this assignment, we will record the keys you type into vim. When the assignment is scored, we will play the keys back to verify if you reached the intended result. You will start with hw1_bad.c and finish with hw1_good.c.

Do not use the arrow keys or mouse. You will not receive credit if you do. Also, do not modify hw1_good.c or hw1_bad.c. You may need those.

We will give you hints in purple for some steps. For the others, you will need to use what you learned from vimtutor and/or the reference sheet. In this explanation, <esc> refers to the Escape key, <enter> refers to the Enter key, <tab> refers to the Enter key, and <space> refers to the spacebar.

Get the homework files

From bash, enter cp hw1_bad.c hw1.c to make a copy of the starter version of the file. Next, enter vim -W hw1.vim hw1.c to open it in vim.  The -W hw1.vim parameter is what makes it record your keystrokes.

  1. Fix the missing semicolon on line 3.
    1. Move to line 3. 3G
    2. Append a colon at the end. A:<esc>
  2. Indent the body (everything inside the curly braces) of the average function, which starts on line 14.
    1. Search for "average".    /average<enter>
    2. Go down one line (to get to the beginning of the body of this function). j
    3. Select the current line using visual mode. V
    4. Extend the selection to include the rest of the body of this function. jjjjj
    5. Indent everything that is selected. >
  3. Indent the body of the for loop inside the average function.
    1. Move to line 18.
    2. Indent the current line. >>
  4. Indent the bodies of the weighted_sum, weighted_average, min, and main functions, as well as any for loops inside them.
  5. Add a blank line after the #include statement at the top.
    1. Jump to the beginning of the file. gg
    2. Start a blank line below the current line. o (lowercase letter)
    3. Exit insert mode (to get back to normal mode). <esc>
  6. Add a blank line between the declarations of QUIZ_SCORES and NUM_EXAMS.
  7. Add a blank line between the declarations of EXAM_WEIGHTS and QUIZZES_WEIGHT.
  8. Add a blank line between the declarations of BONUS_POINTS and PARTICIPATION_POINTS.
  9. Add a blank line above the declaration of the average function.
    1. Search for "average".
    2. Enter a blank line above the current line. O (uppercase letter)
    3. Exit insert mode (to get back to normal mode).
  10. Ensure that there is exactly one blank line above all function declarations.
  11. In the const arrays declared at the top of the file (HOMEWORK_SCORES, HOMEWORK_WEIGHTS, QUIZ_SCORES, EXAM_SCORES, EXAM_WEIGHTS), put each number on its own line.
    1. Jump to the top of the file.
    2. Move down to line 5.
    3. Move to the beginning of the line. 0 (zero)
    4. Move right by 4 words. wwww
    5. Insert a carriage return and a tab, and then immediately exit insert mode (back to normal mode). i<enter><tab><esc>
    6. Start creating a quick macro so you don't have to do that so many times. qq
    7. Move right by words until the cursor is at the beginning of a number. www
    8. Insert a carriage return and then immediately exit insert mode (back to normal mode).
    9. Stop recording the quick macro. q
    10. Replay the macro once. @q
    11. Replay the same macro several more times. @@@@@@@@@@@@ (…and so on)
    12. Insert a carriage return just before the ending curly brace (}) and ensure that it is flush with the left side (i.e., not indented).
    13. Follow a similar procedure for HOMEWORK_WEIGHTS, QUIZ_SCORES, EXAM_SCORES, and EXAM_WEIGHTS.
  12. Right align all of the numbers.
    1. Move to the first 2-digit number in HOMEWORK_SCORES (70).
    2. Insert one space before the line beginning. I<space>
    3. Go down one line (to get to the number 80).
    4. Repeat the last action. . (period)
    5. Do likewise for the rest of the two-digit numbers in HOMEWORK_SCORES, as well as the one-digit numbers in QUIZ_SCORES.
  13. Add a comment after every number in each of the const arrays declared at the top of the file (HOMEWORK_SCORES, HOMEWORK_WEIGHTS, QUIZ_SCORES, EXAM_SCORES, EXAM_WEIGHTS), to indicate which homework, exam, or quiz they refer to.
    1. Move to the first number in HOMEWORK_SCORES.
    2. Append the text " // hw" at the end of the line. A<space><space>//<space>hw<esc>
    3. Move back to the first number in HOMEWORK_SCORES.
    4. Append the number "1" at the end of the line so that the comment reads " // hw1".
    5. Append the numbers "2" to "15" at the end of the remaining lines in HOMEWORK_SCORES.
    6. Follow a similar procedure for HOMEWORK_WEIGHTS, QUIZ_SCORES, EXAM_SCORES, and EXAM_WEIGHTS.
  14. Ensure that there is exactly one space after every comma in a function parameter list.
  15. Ensure that there is exactly one space before and after every arithmetic operator, as shown in hw1_good.c.
  16. For the very long arithmetic expressions (exam_score, and summary_score), break them into two lines but align the equals sign in the first line with the plus sign in the second line, as shown in hw1_good.c.
  17. There is a bug with the calculation of quiz_score (first line of the main function). Currently, it is calculated as just the average. It should be the average times 10. Fix this bug.
  18. There is another bug. The print_grade function is used in main() but is never defined. Add the following function just above main(): void print_grade(float summary_score) { printf("summary score: %.2f\n", summary_score); }
  19. Save. :w<enter>
  20. Modify the print_grade function so that instead of printing the summary score, it prints the letter grade. You will need an if statement (or if else) for each possible letter grade. Do not type all of these repeatedly. Instead, you will use copy-paste. (In vim parlance, these are called yank and put.)
    1. Move to the definition of the print_grade function.
    2. Move to the end of the line. $
    3. Move to the corresponding closing curly brace. %
    4. Move up one line.
    5. Delete the current line ("printf(…"). You should now be back on the closing curly brace.
    6. Add a line above this closing curly brace. This is where you will enter the code to print the letter grade.
    7. Type the following code. if(summary_score >= 93) { printf("A+\n"); }
    8. Select the ending curly brace using visual mode.
    9. Extend the selection upward to include all 3 lines of this if statement and its body.
    10. Yank (copy) the selection. y
    11. Move back to the ending curly brace of the if statement.
    12. Put (paste) the text that you previously yanked directly below the if statement. p
    13. Insert the text "else " at the beginning of this line.
    14. Change "93" to "90" and change "A+" to "A" so that you have the following: if(summary_score >= 93) { printf("A+\n"); } else if(summary_score >= 90) { printf("A\n"); }
    15. Add another copy of the else if clause and adjust the score and grade letter so that you have the following: if(summary_score >= 93) { printf("A+\n"); } else if(summary_score >= 90) { printf("A\n"); } else if(summary_score >= 87) { printf("A-\n"); }
    16. Using a similar method, copy these 9 lines to insert the code for "B+", "B" and "B-". Repeat for "C+", "C", "C-" and "D+", "D", "D-".
    17. Add the else clause.
  21. Make any other changes needed so that your hw1.c file is as close to hw1_good.c as possible.
  22. Save.
  23. Exit vim. :q<enter>

Submit (or save)

To submit, enter 264submit hw1 hw1* from inside the directory. You can submit as often as you want, even if you are not finished with the assignment. That saves a backup copy which we can retrieve for you if you ever have a problem.

Q&A about this assignment

Q:  How do I know if I have used any arrow keys?
A:  Open your hw1.vim file in vim.  The arrow keys will show up as any of the following:

Q:  What if I accidentally click the mouse in the window?
A:  Press gg right afterward to put the cursor on the top line.  Then continue.  That will make sure that accidentally repositioning the cursor with the mouse doesn't throw off the line that you are editing.

Q:  If I quit and come back, can I start where I left off?
A:  It's easiest if you can do the whole thing in one session.  If you quit, it will leave a :q (or similar) command in your hw1.vim file.  We looked into possibly filtering those out, but it gets complicated to do properly.  Editing your hw1.vim file to remove the :q<enter> is a possibility.  You might try doing :vert diffsplit hw1_good.c to see differences and fix them.  (You would open your hw1.c and then enter that command from inside Vim.)

Q:  May I edit my hw1.vim file directly?
A:  Yes.  However, the script you turn in should be able to transform hw1_bad.c into hw1_good.c .  If you can find a way to edit your script to make that work, that's fine.  However, it may be easiest to just start over.  Once you've learned the commands that this assignment uses, the whole thing shouldn't take longer than about 15 minutes. (… we hope.  Let us know if that's wrong.)

Q:  How can I test my vim script?
A:  Like this: 
cp hw1_bad.c hw1.c
vim -s hw1.vim hw1.c
diff hw1.c hw1_good.c

Q&A about Vim

Q:  What is vim?
A:  Vim is a code editor (a text editor for programming).

Q:  What's the difference between vim and vi?
A:  Typing vi gives you vim in a "compatibility mode" that simply turns off many of the newer features.  It is actually the same program.  There is no reason to type vi.  Type vim instead.

Q:  Where can I use it?
A:  Vim is almost always installed on Linux and UNIX machines.  On
Windows, you can install gVim, which gives you GUI.

Q:  Can I use the mouse with Vim?
A:  Yes.  This works in PuTTY, but may not work in other SSH programs. 
(This sample .vimrc enables this for you.  If you are using
your own .vimrc file, you need to add set mouse+=a to it.)

Q:  Can I use tabs?
A:  Yes.  To open several files using tabs, use the -p flag at the command line (e.g., vim -p file1.c file2.c …).  Within Vim, use the :tabe command to open another file in a separate tabe (e.g., :tabe file2.c).  With the sample .vimrc file, you can also just press F2 to open a new tab, [ to move to a tab to the left, and ] to move to the tab to the right.

Q:  Can I get syntax highlighting?
A:  Yes.  (The sample .vimrc file turns this on for you.)


8/27/2015 11:15pm Added Q&A about this assignment. Added a step to add the print_grade() function.
8/31/2015 12:40am Fixed typos ("It should be on line 13.", "<space> refers to Enter"). Made corrections to the hw1_good.c file, as described in an email to the class.
8/31/2015 8:05pm Fixed definition of void print_grade() in step 18.