Part 1: Code editors and SFTP

If you haven’t done so already, follow along with this guide on IDEs vs. code editors and getting an SFTP client set up on your computer.


Part 2: sizeof() is not how you get the length of an array

Note: what you learn in this part is important and I’ll expect you to know it in future labs, projects, and on the exam. So you need to do it, even if there’s nothing to turn in.

Let’s do an exploration about the sizes of variables in C. Head over to this exercise and do it.


Part 3: Text I/O

  1. In your private/cs0449/labs directory, you want to make a new file for this lab. You can do it with this command:

     touch abc123_lab2.c
    

    (But with your username instead of abc123. You get it by now I hope.) This will create an empty file named abc123_lab2.c.

  2. If you already have your labs directory open in your SFTP client, it will not immediately appear. You will have to refresh it (Ctrl+R or ⌘R) to get the updated list of files.
  3. Then you can edit your lab however you like - through ssh or through your SFTP client.

Here are some helper functions. Feel free to reuse these functions in future labs/projects.

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void get_line(char* buffer, int size) {
	fgets(buffer, size, stdin);
	int len = strlen(buffer);
	// this is a little more robust than what we saw in class.
	if(len != 0 && buffer[len - 1] == '\n')
		buffer[len - 1] = '\0';
}

// returns 1 if the two strings are equal ignoring case, and 0 otherwise.
// so "earth" and "Earth" and "EARTH" will all be equal.
int streq_nocase(const char* a, const char* b) {
	// hohoho aren't I clever
	for(; *a && *b; a++, b++) if(tolower(*a) != tolower(*b)) return 0;
	return *a == 0 && *b == 0;
}

What your program will do

This program will calculate how much the user weighs on various planets in our solar system. This is some CS0007 stuff for sure, but many of the steps are quite different from how you’d do them in Java. Here’s how your program will work:

  1. Ask them how much they weigh. (This is unitless because we’re working with ratios.)
  2. Ask them what planet they want to visit.
  3. If they typed exit, use break; to exit the loop (and therefore end the program).
  4. If they typed earth, say You're already there!
  5. Otherwise,
    1. Get the scaled weight for that planet using your planet_to_weight function (see below).
    2. If it returned a value less than 0, that means it’s not a planet, so say That's not a planet..
    3. Otherwise, tell them how much they’d weigh there in this format:
      • "You'd weigh %.2f there.\n"
  6. Go back to step 2.

Here’s how it looks when I interact with my program:

[thoth ~/private/cs0449/lab2]: ./lab2
How much do you weigh? 250
What planet do you want to go to? mars
You'd weigh 95.00 there.
What planet do you want to go to? JUPITER
You'd weigh 635.00 there.
What planet do you want to go to? pluto
That's not a planet.
What planet do you want to go to? earth
You're already there!
What planet do you want to go to? exit
[thoth ~/private/cs0449/lab2]:

It’s important that your program’s output matches mine, because the autograder will be somewhat picky about the output. If you add extra prompts, messages, blank lines, format the output differently etc. you may confuse the autograder and then have to spend a bunch of time just making it happy. So, don’t get crazy with the output. Just make your program work the same way as this example above.


Reading a number

First we’ll read a number, the user’s weight (sorry if that’s sensitive info… you can just type in Some Number if that makes you uncomfortable).

  1. Use the get_line function from above to ask the user for their weight.

     printf("How much do you weigh? ");
     char input[100];
     get_line(input, sizeof(input)); // notice the sizeof!
    

    We used sizeof(input) so we don’t have to repeat the 100. Also, that avoids mistakes if you change the size of the input array.

    I know, I said sizeof() doesn’t get the length of an array. But for char array variables - and ONLY for char array variables - it technically does. It’s a very limited tool, but it’s a tool nonetheless.

  2. Use sscanf to parse the number out of the string. You use it like this:

     int weight;
     sscanf(input, "%d", &weight); // DON'T FORGET THE & or it'll crash.
    

    sscanf means string scan formatted. It’s like printf backwards. It can parse values out of a string.

    How this works is by handing off a pointer to the weight variable to sscanf. The "%d" argument tells sscanf to look in the input string for an integer. sscanf converts it from text to a binary value, and it puts that value into the weight variable directly. (Or, indirectly? Through the pointer? Whatever.)

  3. Compile and run it to see if it works. Never write a whole program at once. Compile early, compile often.

    Compile like gcc -Wall -Werror --std=c99 -o lab2 abc123_lab2.c. (This is a long line, but remember that at a command line, you can use the up and down arrows on your keyboard to find previously-entered commands to run them again. So you only have to type it once.

    Then run like ./lab2. (You can print out the weight variable after the sscanf to see if it was parsed correctly, but remove that print after you’ve tested and confirmed it.)


Making a function

The const means “I only want to read the string from this variable, I promise I won’t change it.” We’ll talk about it later in the term.

Before main, make a function with this signature:

float weight_on_planet(const char* planet_name, int user_weight)

This function takes the name of a planet and a weight, and returns:

Here is a table of relative gravity strengths on the seven non-earth planets in our solar system:

Planet Gravity
Mercury 0.38
Venus 0.91
Mars 0.38
Jupiter 2.54
Saturn 1.08
Uranus 0.91
Neptune 1.19

You can’t switch on a string in C like you can in Java. Instead, you will use streq_nocase to check which planet it is, e.g.

if(streq_nocase(planet_name, "mercury")) {
	// it's mercury.
} else if // etc

The “case-insensitivity” of streq_nocase means they can type e.g. “mercury”, “Mercury”, “MERCURY” and it’ll all work the same way.

Now test that the function works before you make the loop. Call it from main with a few values and print out what it returns. See if it behaves how you expect. Test, test, test. Testing your own code BEFORE you use it will save you so much trouble.


Loopydoop

Finally you need to add the loop to main that does steps 2 to 5 in the program description from before. true is not a thing in C by default, so you have to #include <stdbool.h> at the top if you want to use it. Then you can write while(true) like you’re used to. Alternatively, you can write while(1). Because 1 is true! Sure!

In that loop, you’ll be:


Submission

We will be compiling your program with these compiler options, so make sure your program compiles with them:

gcc -Wall -Werror --std=c99 -o lab2 abc123_lab2.c

Also, this time, the autograder/submission will not be open immediately. This is so that you learn to do your own testing. I will open up the autograder a few days after the lab is released and announce when I do. This is how it will work from now on.

Once you’re ready to submit and the autograder is online, you can use your SFTP client to copy your _lab2.c file to your computer. Figure out how to do that in your SFTP client! It’s not hard!

Then just like for lab 1:

  1. Go to the canvas for this course.
  2. Click Gradescope on the left.
  3. Click on Lab 2.
  4. Drag your _lab2.c file into the Gradescope submission thingy.
  5. Wait for the autograder to complete!

If the autograder says something is wrong with your submission, fix it on thoth, re-download it to your computer , and re-submit it as many times as needed to fix the problem.

Note that future assignments may have a limited number (or rate) of resubmissions, so do not rely on the autograder to be your only method of finding and fixing problems!