Simple Workflow and Passive Debugging in XCode
This chapter begins your use of Xcode in earnest. Here’s where I introduce the problem that is the basis for all of the example code in this book.
The problem is the calculation of passer ratings. In American/Canadian football, quarterbacks advance the ball by throwing (passing) it to other players. The ball may be caught (received, a good thing) by someone on the quarterback’s own team, in which case the ball is advanced (yardage, more is better), possibly to beyond the goal line (a touchdown, the object of the game); or it may be caught by a member of the opposing team (intercepted, a very bad thing).
But those are four numbers, and everybody wants a figure-of-merit, a single scale that says (accurately or not) who is the better passer. The National Football League and the Canadian Football League have a formula for passer ratings, yielding a scale running from 0 to (oddly) 158.3. A quarterback who rates 100 has had a pretty good day.
Creating the Project
As in Chapter 2, “Kicking the Tires,” you’ll start with a command-line project. Start Xcode and click Create a new Xcode project, or select File → New → Project. . . ( N). In the New Project assistant sheet, select an OS X Command Line Tool, and name the tool passer-rating; for Language, once again choose C.
Another difference: When you are shown the get-file sheet to select the location for the new project, check the box labeled Create Git repository on, and select My Mac. Git is a version-control system, an essential part of modern development. You’ll learn all about it in Chapter 7, “Version Control,” but now is the time to start.
Again, you’ll be shown target settings, which you can ignore for now. Instead, mouse over to the Project navigator at the left side of the Workspace window, and select main.c
Delete everything in the main() function but its outer braces, and replace the body of the function so the file reads thus (keep the comments at the top of the file):
#include <stdio.h> #include "rating.h" // Yet to create; initially an error int main(int argc, const char * argv[]) { int nArgs; do { int comps, atts, yards, TDs; printf("comps, atts, yards, TDs: "); nArgs = scanf("%d %d %d %d %d", &comps, &atts, &yards, &TDs); if (nArgs == 5) { float rating = passer_rating(comps, atts, yards, TDs); printf("Rating = %.1f\n", rating); } } while (nArgs == 5); return 0; }
You’ll notice that as you type closing parentheses, brackets, and braces, the corresponding opening character is briefly highlighted in yellow.
The rating calculation itself is simple. Put it into a file of its own: Select File → New → File. . . ( N). You’ll be presented with the New File assistant sheet; see Figure 3.1. Navigate the source list on the left, and the icon array on the right thus: OS X → Source → C File.
Figure 3.1 The New File assistant sheet offers many templates you can use to start a new file. Select the category from the source list on the left, and pick the template from the array of icons on the right.
Click Next, and use the save-file sheet that appears to name the file rating (Xcode will append .c automatically).
The save-file sheet has two custom controls. The Group popup lets you place the new file in the Project navigator (the source list at the left of the project window). Roughly, groups are simply ways to organize the Project inspector list; they have no influence on how the new file will be placed on-disk. Make sure the passer-rating group is selected.
Second is Targets, a table that for now has only one row, passer-rating. A target is a group of files and settings that combine to build a product. A file that isn’t part of a target isn’t used to build anything. Make sure that passer-rating is checked.
Here’s what goes into rating.c:
#include "rating.h" static double pinPassingComponent(double component) { if (component < 0.0) return 0.0; else if (component > 2.375) return 2.375; else return component; } float passer_rating(int comps, int atts, int yds, int tds, int ints) { // See http://en.wikipedia.org/wiki/Quarterback_Rating double completionComponent = (((double) comps / atts) * 100.0 - 30.0) / 20.0; completionComponent = pinPassingComponent(completionComponent); double yardageComponent = (((double) yds / atts) - 0.3) / 4.0; // intentional bug yardageComponent = pinPassingComponent(yardageComponent); double touchdownComponent = 20.0 * (double) tds / atts; touchdownComponent = pinPassingComponent(touchdownComponent); double pickComponent = 2.375 - (25.0 * (double) ints / atts); pickComponent = pinPassingComponent(pickComponent); double retval = 100.0 * (completionComponent + yardageComponent + touchdownComponent + pickComponent) / 6.0; return retval; }
By now, you’ve missed a couple of braces, and you are tired of tabbing to get the extra level of indenting. Xcode can do this for you—it’s among the features I had you turn off in the last chapter.
Open the Preferences window (Xcode → Preferences, comma) and select the Text Editing panel. In the Editing tab, check Code completion: Automatically insert closing “}” . In the Indentation tab, check Syntax-aware indenting: Automatically indent based on syntax.
Now type an open brace in your code, at the end of a line. So what, it’s a brace. Now press Return. Xcode adds two lines: Your cursor is now at the next line, indented one level, and a matching closing brace appears on the line after that.
Finally, you’ve noticed that both main.c and rating.c refer to a rating.h, which notifies main() of the existence of the passer_rating function. Press N again, and choose Header File from the source files. Name it rating, and put this into it:
#ifndef passer_rating_rating_h #define passer_rating_rating_h float passer_rating(int comps, int atts, int yds, int tds, int ints); #endif
Click Create.