Starting from:
$35

$29

Week 1 Lab Exercise Solution

In this course, we will use git and GitHub to manage our source code. For those of you who have never used these tools before, git is a command-line tool for synchronizing source code “repositories” on different machines. GitHub, on the other hand, is a cloud service that hosts git repositories and provides some additional tools for collaboration on code, centered around git repositories. This is one of the most popular combinations of tools for managing and collaborating on source code in the software development world, so learning to use them early in your software development career will be a great benefit. In addition to helping you get started with git and GitHub, this lab will review using pointers and structs in C++.

Step 1: Download and install git on your laptop
Git is a tool you run on your computer, but you’ll need to make sure you have it downloaded and installed to be able to run it. You can download the latest version of git for any operating system here: https://git-scm.com. If you’re on MacOS, you can also install git via Homebrew, if you use it. If you’re on Linux, you can install git using your distribution’s package manager (e.g. apt or yum). If you’re working on one of the ENGR servers, you can skip this step, since those machines should already have git installed.

Step 2: Open your command line terminal
Git is a command line program, so open up your favorite command line program.

Windows
If you’re using Windows, you have a few options for the command line.

If you installed git from git-scm.com, you should have a program called Git Shell installed, which you can access from your Start menu. You can run this to get to a command line.
You can also use Power Shell, which should come already installed on Windows.
You can also use the standard Windows command prompt, which you can access by opening the Start menu and typing cmd in the Search/Run box.



Here is a list of basic commands you can use to navigate and work within any of these Windows command lines: https://community.sophos.com/kb/en-us/13195.

Unix (MacOS/Linux)
If you’re using a Unix operating system (MacOS or Linux), you can use the terminal program that comes installed with your OS. In MacOS, this is called Terminal. In Linux, this can be called Terminal or Console.




Here’s a list of basic commands you can use to navigate and work within the Unix command line: https://www.tjhsst.edu/~dhyatt/superap/unixcmd.html.

Step 3: Make sure git is installed and set some basic configs
Now that you’re at your command line, let’s make sure git is properly installed. Run the following command:




git --version




You should see your git version printed out. Now that you know git is installed, let’s set some basic but necessary git configurations. Run these two commands to make sure git knows your name and email address, so it can record this information when you commit code (using your actual name and email address in the commands):




git config --global user.name "Your Name"

git config --global user.email "your-email@somewhere.com"




You should also run this command to make sure git handles line endings correctly on your OS:




(Windows) git config --global core.autocrlf true

(MacOS/Linux) git config --global core.autocrlf input

Step 4: Create and download your code repository for this lab
In this course, we’ll use a tool called GitHub Classroom to administer assignments and most labs. For each assignment/lab, you’ll be provided with a GitHub Classroom URL that will make sure you have your own private repository for the assignment/lab. Here’s the URL for this lab:




https://classroom.github.com/a/oC3UOqv2




Following that URL will cause a few things to happen:

It will make sure you’re logged into GitHub. If you don’t have a GitHub account, it’ll guide you through creating one. IMPORTANT: If you are creating a GitHub account now, make sure to verify your email address with GitHub before proceeding.
If you’ve never used GitHub Classroom before, it will ask you to authorize the GitHub Classroom app to access some basic info from your GitHub account. It is safe to do this.
It will generate a private code repository for you that is associated with this specific lab. The code repository may contain some starter files. Once the repository is created, GitHub Classroom will provide you with a link to your lab repository on GitHub. If you click this link, you’ll be brought to a web interface that you can use to navigate the repository, examine files, and do other things.



Once you’re in your repository, navigate to the “Code” tab and click the “Clone or download” button. Copy the clone URL you see there.




Now, go back to your command line, and cd to the directory where you want to make a copy of your repository. Once you’re there, run this command, replacing REPO_URL with the clone URL you copied just a minute ago:




git clone REPO_URL




This will make a local copy of your remote repository (the one on GitHub). This local repository is where you will do your work editing, adding, and deleting files. You’ll see a little later how to “push” the changes you make in this local repository back into your remote repository on GitHub.




Note: if you have trouble cloning your repository, try using the URL you get after clicking the “Use HTTPS” link under the “Clone or download” button on GitHub. If you do this, you’ll need to make sure you enter your GitHub credentials when prompted.




Once you have your repository cloned locally, cd into the repository directory that was just downloaded (it should be called lab-1-YourGitHubUsername/) and run this command:




git status




This is a git command you can use to check the current state of your local repository. It will tell you things like the name of the branch you’re working in (no need to worry about this for now) and what files have changed since you last committed files into your repository (more on this later). We’ll see git status again in a bit.

Step 5: Write a program to print multiplication and division tables
To review some of the material you learned in CS 161, write a program that creates a dynamic 2D array of structs to store and print the multiplication and division tables for values between 1 and a number n specified by the user. Specifically, follow these steps to create the program:




Create a new file in your repository directory named muldiv.cpp. This is the file in which you will write your program.


Set your program up to read the number n as a command line argument. For example, if the user runs your program like this, you will have n = 5:

./muldiv 5

Make sure to check whether the user inputs a valid integer value, and exit the program with an error if they do not. The function atoi() will be helpful for this step, e.g.:

n = atoi(argv[1]);


Write a struct like this one to store a single entry in both the multiplication table and the division table:

struct muldiv_entry {
int mul;
float div;
};


Write a program that uses n and your struct to generate and then print the multiplication and division tables for all values between 1 and n, inclusive. For example, if the user runs your program as follows, then it should print the multiplication and division tables like below:

./muldiv 5

Multiplication Table:

1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25

Division Table:

1.00 0.50 0.33 0.25 0.20
2.00 1.00 0.67 0.50 0.40
3.00 1.50 1.00 0.75 0.60
4.00 2.00 1.33 1.00 0.80
5.00 2.50 1.67 1.25 1.00

Your program must be well modularized. Specifically, you should write and use the following functions:

struct muldiv_entry** generate_tables(int n)
This function should allocate space for an n x n array of your structs and fill it with the appropriate multiplication and division values. It should return the 2D array it creates.


void print_tables(struct muldiv_entry** tables, int n)
This function should take a 2D array as created by generate_tables() and its size and print out the multiplication and division tables like above.


void free_tables(struct muldiv_entry** tables, int n)
This function should release all of the memory allocated to a 2D array created by generate_tables(), given the array and its size as arguments. This function is important. Your program should not have a memory leak.


Now, compile your program:

g++ muldiv.cpp -o muldiv

Once your program is compiled, test it with a few different values of n to make sure it works.
Step 6: Commit your program into your local git repository
When you have your program working the way you want to, it’s a good time to commit it into your local git repository. First, run git status again to see what state your repository is in. You should see output something like this:






This is telling you git sees that you created a new file named muldiv.cpp, but that file is not yet being tracked by git. We want git to track this new file. To achieve this, run this command:




git add muldiv.cpp




Now, if you run git status again, you should see output something like this:









This is telling you the new file muldiv.cpp is staged to be part of your next commit. In other words, the next time you tell git to make a commit, the new file muldiv.cpp will then be tracked by git. Let’s do that:

git commit -m "Add new program to compute mult/div tables."




Here, we’re making a commit (that is, taking a snapshot of the changes we made to our code and adding that snapshot permanently into our local git database), and we’re using the -m option to add a message describing that commit. If you omitted the -m option and the subsequent message argument, git would open a text editor for you to type in a commit message.




You can verify that your commit worked by running the command git log, which lists all of the commits in the history of your repository. At the top of the output, you should see a commit with the message you just entered above.

Step 7: Push your program to your remote repository on GitHub
If you go back to your browser and refresh the page containing the “Code” tab in your GitHub repository, you’ll see that it still doesn’t contain the new file you created. This is because git doesn’t perform any kind of network operations unless you explicitly tell it to. The git commit command is not a network operation: it simply updates your local repository.




To update the remote repository on GitHub, you need to “push” the changes from your local repository into that remote repository. Luckily, because of the way we used git clone to create our local repository, pushing changes back to the remote repository on GitHub is easy. All you need to do is run this command:




git push




After that command finishes, you should be able to refresh the page containing your GitHub repository and see your new file there. This is a great thing! It means your file is safely stored on GitHub.

The workflow here is important to remember. This is the essential git/GitHub workflow:

Create a local git repo (in our case by copying a remote one on GitHub using git clone).
Modify (add, edit, or delete) files in your local repo.
Use git add to stage a snapshot of your changes to be committed to your local repo.
Use git commit to commit the snapshot of your changes to your local repository, making it permanent there.
Use git push to push your changes to your remote repository on GitHub.
Repeat from 2.
Step 8: Factor out your implementation and interface
Some of the functions we wrote, along with our struct, might be useful in other contexts, so let’s factor them into a more reusable form by separating the struct and function prototypes into a separate header file and the function definitions into a separate implementation file. Doing this will have other benefits, such as helping us keep our code more organized and allowing us to speed up compilation (by compiling only files that have changed since the last compilation). Follow these steps:




Create a new header file named muldiv.hpp and add to it the definition of your struct and all of your function prototypes:

struct muldiv_entry {
int mul;
float div;
};

struct muldiv_entry** generate_tables(int n);
void print_tables(struct muldiv_entry** tables, int n);
void free_tables(struct muldiv_entry** tables, int n);

Once you’ve created this header file, you can remove the definition of your struct from your .cpp file. If you have prototypes separate from your function definitions in the .cpp file, you can remove those too. Replace all those by including your new header file:

#include "muldiv.hpp"

You should still be able to compile your program here as you did before:

g++ muldiv.cpp -o muldiv


Create a new implementation file named muldiv_print.cpp. Copy your main() function from your original muldiv.cpp file, add it to this new file, and then remove it from muldiv.cpp. You’ll need to include your muldiv.hpp header file in the new file, too.

Now, you’ll need to compile both files together to be able to run them:

g++ muldiv.cpp muldiv_print.cpp -o muldiv_print

After compiling, you should be able to run your new executable:

./muldiv_print 5


After you’re happy with your new files, use git add to stage them for commit, commit them using git commit, and push them to your remote repo on GitHub using git push.


Step 9: Use a Makefile to compile your program
As our programs (and the number of source code files we use) grow, it can become painful to continually type out long g++ commands into the terminal each time we want to compile our code. Fortunately, there is a nice GNU/Unix utility called make, which allows us to write a file called a makefile to specify how to compile our code. Once we have a makefile written, compiling our code can be as simple as running the command make.




Let’s write a makefile for our program to simplify its compilation. Follow these steps:




Create a new file named Makefile. Add the following lines to this new file (note that the indentation must be a tab character):

muldiv_print:
g++ muldiv.cpp muldiv_print.cpp -o muldiv_print

Now, if you type the command make into your terminal, you should see your code be compiled.


We can go further, factoring our compilation into different stages and specifying dependencies for each compile step, which will allow the make utility to run only the compilation steps it needs to based on which files have changed. We can also use variables to make it easier to change some values in the makefile, such as the compiler we want to use or the name of the executable file generated. Modify your Makefile to look like this:

CC=g++
EXE_FILE=muldiv_print

all: $(EXE_FILE)

$(EXE_FILE): muldiv.o muldiv.hpp muldiv_print.cpp
$(CC) muldiv.o muldiv_print.cpp -o $(EXE_FILE)

muldiv.o: muldiv.hpp muldiv.cpp
$(CC) -c muldiv.cpp

Now if you run make again, you should notice your compilation happening in stages. We usually also add a makefile target for cleaning up our directory:

clean:
rm -f *.o $(EXE_FILE)

You can run that makefile target by specifying it on the command line when you run make, i.e. make clean.


Once your makefile is working well, add and commit it to your local git repo, and push it to your remote repo on GitHub.
Grading Criteria
That’s it! After you’re done with your lab, make sure you get it checked off by your TA so that you get points for it. If you don’t get your work checked off, you’ll receive a zero for the lab, and we won’t be able to change your grade, since we’ll have no way to know whether or not you were at the lab.




This lab is worth 10 points total. Here’s the breakdown:

7 points: muldiv.cpp is completed, committed, and pushed to GitHub (i.e. everything through Step 7 is complete).
2 points: code is factored into multiple implementation files and a header file and those are committed and pushed to GitHub (i.e. everything through Step 8 is complete).
1 point: compilation is specified using a makefile, which is committed and pushed to GitHub (i.e. all steps are complete).

More products