CS 200: Concepts of Programming using C++ (Spring 2024 version)
Table of Contents
- WEEK 1 - JAN 22
- UNIT 00: Welcome & setup
- UNIT 01: Exploring software
- π Presentation - Exploring software (U01.PRES)
- ποΈ Reading - Exploring software (U01.READ)
- π Concept Intro - Exploring software (U01.CIN)
- π§ Tech Literacy - Exploring software (U01.TEC)
- ποΈ Nonogram - Nonogram A (U01.EXE.N)
- π§βπ« Status Update - Welcome, Setup, Exploring Software (U01.SUP)
- WEEK 2 - JAN 29
- WEEK 3 - FEB 5
- WEEK 4 - FEB 12
- UNIT 04: Control flow - Branching and looping
- π Presentation - Control flow (U04.PRES)
- ποΈ Reading - Control flow (U04.READ)
- π Concept Intro - Control flow (U04.CIN)
- π§βπ¬ Lab - Control flow (U04.LAB)
- π§ Tech Literacy - Filesystems (U04.TEC)
- ποΈ Nonogram - Nonogram C (U04.EXE.N)
- π§βπ« Status Update - Control flow (U04.SUP)
- UNIT 04: Control flow - Branching and looping
- WEEK 5 - FEB 19
- UNIT 05: Structs
- π Presentation - Structs (U05.PRES)
- ποΈ Reading - Structs (U05.READ)
- π Concept intro - Structs (U05.CIN.202401CS200)
- π§βπ¬ Lab - Structs (U05.LAB)
- ποΈ Unit 05 Debugging - Debugging review - C++ basics (U05.EXE.D)
- ποΈ Nonogram - Nonogram D (U05.EXE.N)
- π§βπ« Unit 05 Status Update - Structs (U05.SUP)
- UNIT 05: Structs
- WEEK 6 - FEB 26
- WEEK 7 - MAR 4
- WEEK 8 - MAR 11 - SPRING BREAK
- WEEK 9 - MAR 18
- WEEK 10 - MAR 25
- WEEK 11 - APR 1
- WEEK 12 - APR 8
- WEEK 13 - APR 15
- WEEK 14 - APR 22
- Additional
\newpage
Rachel Wil Sha Singh's Core C++ Course Β© 2024 by Rachel Wil Sha Singh is licensed under CC BY 4.0. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/
These course documents are written in emacs orgmode and the files can be found here: https://gitlab.com/moosadee/courses
Dedicated to a better world, and those who work to try to create one.
\newpage
This section contains each of the units we will be covering in the class, including the reading material, review, and assignment documentation. Add your own notes and highlight things as you go through!
WEEK 1 - JAN 22
UNIT 00: Welcome & setup
π °οΈ Pre-test (PRETEST.202401.CS200)
π Introductions!
β Unit 00 Setup - GitLab Username
π Presentation - Set up (U00.PRES)
ποΈ Reading - Welcome (U00.READ)
- Welcome!
It feels weird to start a collection of notes (or a "textbook") without some sort of welcome, though at the same time I know that people are probably not going to read the introduction (Unless I put some cute art and interesting footnotes, maybe.)
I think that I will welcome you to my notes by addressing anxiety.
Belonging
Unfortunately there is a lot of bias in STEM fields and over decades there has been a narrative that computer science is for a certain type of person - antisocial, nerdy, people who started coding when they were 10 years old.
Because of this, a lot of people who don't fit this description can be hesitant to get into computers or programming because they don't see people like themselves in media portrayals. Or perhaps previous professors or peers have acted like you're not a real programmer if you didn't start programming as a child
If you want to learn about coding, then you belong here.
There are no prerequisites.
I will say from my own experience, I know developers who fell in love with programming by accident as an adult after having to take a computer class for a different degree. I know developers who are into all sorts of sports, or into photography, or into fashion. There is no specific "type" of programmer. You can be any religion, any gender, any color, from any country, and be a programmer.
Figure 1: Don't be like Gatekeeper Baby. You can begin coding at any age!
Challenge
Programming can be hard sometimes. There are many aspects of learning to write software (or websites, apps, games, etc.) and you will get better at it with practice and with time. But I completely understand the feeling of hitting your head against a wall wondering why won't this work?! and even wondering am I cut out for this?! - Yes, you are.
I will tell you right now, I have cried over programming assignments, over work, over software. I have taken my laptop with me to a family holiday celebration because I couldn't figure out this program and I had to get it done!!
All developers struggle. Software is a really unique field. It's very intangible, and there are lots of programming languages, and all sorts of tools, and various techniques. Nobody knows everything, and there's always more to learn.
Just because something is hard doesn't mean that it is impossible.
It's completely natural to hit roadblocks. To have to step away from your program and come back to it later with a clear head. It's natural to be confused. It's natural to not know.
But some skills you will learn to make this process smoother are how to plan out your programs, test and verify your programs, how to phrase what you don't know as a question, how to ask for help. These are all skills that you will build up over time. Even if it feels like you're not making progress, I promise that you are, and hopefully at the end of our class you can look back to the start of it and realize how much you've learned and grown.
Learning
First and foremost, I am here to help you learn.
My teaching style is influenced on all my experiences throughout my learning career, my software engineer career, and my teaching career.
I have personally met teachers who have tried to scare me away from computers, I've had teachers who really encouraged me, I've had teachers who barely cared, I've had teachers who made class really fun and engaging.
I've worked professionally in software and web development, and independently making apps and video games. I know what it's like to apply for jobs and work with teams of people and experience a software's development throughout its lifecycle.
And as a teacher I'm always trying to improve my classes - making the learning resources easily available and accessible, making assignments help build up your knowledge of the topics, trying to give feedback to help you design and write good programs.
As a teacher, I am not here to trick you with silly questions or decide whether you're a real programmer or not; I am here to help guide you to learn about programming, learn about design, learn about testing, and learn how to teach yourself.
Roadmap
When you're just starting out, it can be hard to know what all you're going to be learning about. I have certainly read course descriptions and just thought to myself "I have no idea what any of that meant, but it's required for my degree, so I guess I'm taking it!"
Here's kind of my mental map of how the courses I teach work:
- CS 200: Concepts of Programming with C++
- You're learning the language. Think of it like actually learning a human language; I'm teaching you words and the grammar, and at first you're just parroting what I say, but with practice you'll be able to build your own sentences.
- CS 235 Object-Oriented Programming with C++
- You're learning more about software development practices, design, testing, as well as more advanced object oriented concepts.
- CS 250 Basic Data Structures with C++
- You're learning about data, how to store data, how to assess how efficient algorithms are. Data data data.
In addition to learning about the language itself, I also try to sprinkle in other things I've learned from experience that I think you should know as a software developer (or someone who codes for whatever reason), like
- How do you validate that what you wrote actually works? (Spoilers: How to write tests, both manual and automated.)
- What tools can you use to make your programming life easier? (And are used in the professional world?)
- How do you design a solution given just some requirements?
- How do you network in the tech field?
- How do you find jobs?
- What are some issues facing tech fields today?
Something to keep in mind is that, if you're studying Computer Science as a degree (e.g., my Bachelor's degree is in Computer Science), technically that field is about "how do computers work?", not about "how do I write software good?" but I still find these topics important to go over.
That's all I can really think of to write here. If you have any questions, let me know. Maybe I'll add on here.
\vspace{0.2cm}
- What is this weird webpage/"book"?
In the past I've had all my course content available on the web on separate webpages. However, maintaining the HTML, CSS, and JS for this over time is cumbersome. Throughout 2023 I've been adapting my course content to emacs orgmode documents, which allows me to export the course content to HTML and PDF files. I have a few goals with this:
- All course information is in one singular place
- At the end of the semester, you can download the entire course's "stuff" in a single PDF file for easy referencing later on
- Hopefully throughout this semester I'll get everything "moved over" to orgmode, and in Summer/Fall 2024 I can have a physical textbook printed for the courses, which students can use and take notes in so as to have most of their course stuff in one place as well
- It's important to me to make sure that you have access to the course content even once you're not my student anymore - this resource is available publicly online, whether you're in the course or not. You can always reference it later.
I know a lot of text can be intimidating at first, but hopefully it will be less intimidating as the semester goes and we learn our way around this page.
\vspace{0.2cm}
- What kind of tools are needed to make programs?
To write software, we need to write instructions - the program source code is the list of instructions. This means we need some kind of text editor program.
To turn the program instructions into stuff humans can read into stuff computers can read (that is, binary, or an executable file), we need a compiler program.
These are the two things that are needed at minimum, but there are plenty more tools to help us be more effective at our jobs. For instance, if you use the default "Notepad" on Windows it's going to be a bunch of black text on a white background. If you use a text editor meant for code, however, you'll get syntax highlighting - which color-codes different commands, helping us read the code more clearly.
#include <iostream> using namespace std; int main() { cout << "Hello, world!" << endl; return 0; }
(If this doesn't show up in color, just pretend it does and that it makes it easier to read.)
Since we'll be writing a lot of different programs and referring back to these programs throughout the semester you will also want to keep things organized and backed up. There is special software that software developers use to keep track of their code changes over time, called source control or version control. We will be using the Git version control system in this course, though we are going to stick to the web interface view for this introductory course.
- Review questions:
- What kind of program is needed to convert human-readable code into computer binary executables?
- Computer CPUs only understand what "language"?
- What kind of program is used by professionals to store their code and keep track of changes?
We will explore more about how computers work later on, but for now, let's get our tools set up!
After the reading, complete the assignment: π Unit 00 Concept Intro - Welcome/setup (U00.CIN)
\newpage
π§βπ¬ Lab - Set up (U00.LAB)
- Overview:
- Students will set up a GitLab account, be given access to a repository, and practice uploading files. Additionally, students will also set up a Compiler and Text Editor and practice Compiling and Running some example C++ code.
- Turn-in:
- 1. A set of screenshots with certain steps completed:
- For WINDOWS users:
- The MinGW bin folder directory on your hard-drive.
- Your Updated Environment Variables pointing to MinGW.
- ALL STUDENTS:
- The cs200 folder unzipped on your hard-drive.
- Building the
test-program.cpp
usingg++
from the PowerShell or other Shell/Terminal. - Running the
a.out
program using./
in the PowerShell or other Shell/Terminal.
- For WINDOWS users:
- 2. A link (URL) to your
u00_Welcome
folder in your repository.
- 1. A set of screenshots with certain steps completed:
- Creating a GitLab account
1. Go to the sign up page: Start by going to https://gitlab.com/users/sign_up and fill out the form to create your account.
Fill out your first and last name, a username, email address, and password. Note that if you want to maintain your privacy you might use an alternative email/name, but make sure to let the instructor know who you are!
2. Navigate to your profile page: After registering, going to https://gitlab.com/ should take you to a "Projects" page. You will be able to view your repositories here later on. On the right-hand sidebar, click on your profile image (it might be some default picture), then click on the top section to go to your profile.
3. Bookmark your profile page: Once you're on your profile page, the URL will look something like this:
https://gitlab.com/YOURUSERNAME
Take note of this URL and bookmark this page. You may also need to give this link to the instructor for further setup. - Accessing your GitLab repository
Make sure the instructor knows your GitLab profile name. For example:
https://gitlab.com/YOURUSERNAME
. They will set up your class repository, where you will be able to upload your code for the semester.Why are we using a repository? Using source control software such as git is an important tool of software developers in the real world. Now is a great chance for us to get practice working with source control before entering the real world. Plus, it has these benefits:
- Back up your source code to a server so you can access it anywhere and don't lose your code! (And you can refer back to it once the semester ends, for future class reference! :)
- Your instructor can view your repository and code from their own machine, which helps with debugging issues!
Once you're given access to your repository you'll be able to find it at a URL like
https://gitlab.com/users/YOURUSERNAME/contributed
, though you might want to bookmark the repository link as well!A repositoroy link looks like this:
https://gitlab.com/rsingh13-student-repos/GROUP_NAME/REPOSITORY_NAME
- the instructor will create the repository for you and have a basic structure set up, and then you can upload your work for each assignment.Your starting repository will probably look different from this one - this is just a past example! :)
- Downloading the starter code templates
Once you have access to your repository, you will see that it already has folders and files created within it. These are the starter code items that we will be using throughout the semester.
Click on the blue Code button, and at the bottom of the dropdown select the zip button.
After the zip file is downloaded, make sure to extract it to your hard drive.
Task: Take a screenshot of the cs200 folder extracted on your hard drive.
This is to show me that you were able to download and unzip the folder correctly.
- Setting up the compiler
IF YOU'RE ON A MAC COMPUTER, use this video for a guide on how to install
g++
and build a basic C++ program.If you're using a school lab computer they will already have the software we need set up. Use these instructions for setting up the programs on your own computer.
- Installing a C++ compiler on Windows:
On Windows we're going to use the MinGW compiler to build our C++ programs into executable (.exe) files.
\vspace{0.2cm}
1. Go to https://sourceforge.net/projects/mingw/ and click Download.
2. Save the install file to your computer and run it.
3. On the first page, click the "Install" button.
4. Choose a path to install the compiler. You can leave the other items as the defaults.
5. It will download some needed items. Click "Continue" once it's done.
6. On the main installer page, click the checkbox next to the "mingw32-gcc-g++" option.
7. Then, click on the "Installation" dropdown menu and select "Apply Changes".
8. It will ask "Okay to proceed?". Click "Apply" to continue. Once all the changes are done, click "Close". You can then close the MinGW Installation Manager.
9. Next, go to the path where MinGW was installed (by default, it's
C:\MinGW
). Go into the "bin" folder, and then select the address bar to turn it into text. Copy this path. This is the directory where the MinGW compiler program resides.10. Next, click on the Windows start bar and type in "Environment" and look for the option "Edit the system environment variables".
11. In the System Properties screen, click on the "Environment Variables…" button.
12. Highlight the Path field and then click the "Edit…" button.
13. Paste your MinGW bin path into this editor then click "OK". You can then close out of the rest of the windows.
Next we will build and run an example program. Skip the next setups for Linux and Mac to find the next section, "Build and run a test program".
\vspace{1cm}
- Installing a C++ compiler on Linux:
From your package manager install the g++ package.
Next we will build and run an example program. Skip the next setup for Mac to find the next section, "Build and run a test program".
\vspace{1cm}
- Installing a C++ compiler on Mac:
TODO: DOCUMENT MAC COMPILER SETUP PROCESS
Task: Take a screenshot of the MinGW bin directory in your Windows Explorer (Windows users only).
This is to show me that you were able to install the compiler correctly.
Task: Take a screenshot of your updated Environment Variables (Windows users only).
This is to show me that you were able to configure the runnable program correctly.
- Installing a C++ compiler on Windows:
- Build and run a test program
Within the project folder, in the
u00_Welcome
you'll find the filetest-program.cpp
- we are going to build and run it to make sure that the compiler setup was a success.In Windows, hold the SHIFT key and right-click in the empty space of the folder. Select "Open PowerShell window here".
To use the MinGW compiler to build our .cpp file, use the command:
g++ test-program.cpp
. By default, this will generate an executable file named a.exe.Task: Take a screenshot of you building the program in the Shell using
g++
.This is to show me that you were able to build the program correctly.
If the build is successful, it won't display any additional information but it will return you to the prompt. To run the program, use:
./a.exe
and hit ENTER. It will show a little greeting:Task: Take a screenshot of you running the program using the
./a.exe
command (or a.out for Linux/Mac).This is to show me that you were able to run the program correctly.
- Setting up a code editor
If you're using a school lab computer they will already have the software we need set up. Use these instructions for setting up the programs on your own computer.
You can use any code editor that you'd like to use. In my example screenshots, I will be using Geany (https://www.geany.org/) but you may have other preferences. VSCode (https://code.visualstudio.com/) is another popular option though it is a Microsoft product.
\vspace{0.5cm}
Once you've installed a text editor, open the
test-program.cpp
file in the text editor. You will see some basic C++ code. Change theworld
text to say something else, like your name.After any changes are made to source code you must recompile the program for the executable file to show the updates. So, if you run
g++ test-program.cpp
again, next time you run the program with./a.exe
you'll get updated text: - Uploading your work to your repository
Task: Edit the
test-program.cpp
file and paste in your changes to this file.Finally, we are going to upload our updates to the GitLab repository. First, navigate to the file from the GitLab webpage view. Click on the
test-program.cpp
file here.Next, you can click on the "Edit" dropdown menu. Select "Edit single file".
Copy your updated code from your text editor and paste it into this web editor so it will have your latest changes. Scroll down afterwards and click the "Commit" button.
The file will be updated.
Task: Upload your screenshots into the
u00_Welcome
folder in your repository.To upload a file to a folder in your repository, click on the "+" button next to the current folder path, and then select "Upload file".
Select the file to upload, add a comment about the file, and click Upload file.
Your file will now be in the repository.
Task: Copy the URL of the
u00_Welcome
folder in your repository.You will turn this in on Canvas.
- Turning in your work on Canvas
To turn in your work on Canvas, first go to your GitLab repository and copy the URL that belongs to the file(s) you edited.
In Canvas, locate the assignment with the matching name. Click on the "Start Assignment" button.
Next, make sure you're on the Website URL tab. Paste in the file's URL that you just copied, then click "Submit Assignment".
I will then grade the assignment. In this case, it's just a "Complete/Incomplete" grade, but with most assignments I'll mark the amount of points you've earned based on some criteria. You are welcome to submit fixed code afterwards as well.
UNIT 01: Exploring software
π Presentation - Exploring software (U01.PRES)
ποΈ Reading - Exploring software (U01.READ)
- A brief history of software
A computer needs to be told how to do everything. If you were writing a program totally from scratch, you would have to tell it how to load a bitmap file, how to draw a rectangle, how to detect mouse clicks, how to animate a transition, and everything else.
However, software has been evolving for decades now, and a lot of these features are already implemented in libraries. Libraries are sets of pre-written code meant for other programs to import and use.
With some of the first computers, the only commands you could program in directly mapped to the hardware on the machine (machine code / assembly). Later, developers such as Grace Hopper worked on ways to write code that lets you fit multiple machine-code-pieces into one command that was more human-readable, leading to early languages like COBOL.
Many of these "higher-level" languages (higher-level meaning further from the hardware; more abstracted) eventually will get turned into machine code through a process called compiling.
// Example C++ program #include <iostream> using namespace std; int main() { cout << "Hello, world!" << endl; return 0; }
And here is the corresponding assembly code:
// Corresponding assembly code ;5 : { 0x5555555551a9 endbr64 0x5555555551ad push rbp 0x5555555551ae mov rbp,rsp ;6 : cout << "Hello, world!" << endl; 0x5555555551b1 lea rsi,[rip+0xe4c] # 0x555555556004 0x5555555551b8 lea rdi,[rip+0x2e81] # 0x555555558040 <std::cout@@GLIBCXX_3.4> 0x5555555551bf call 0x555555555090 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt> 0x5555555551c4 mov rdx,rax 0x5555555551c7 mov rax,QWORD PTR [rip+0x2e02] # 0x555555557fd0 0x5555555551ce mov rsi,rax 0x5555555551d1 mov rdi,rdx 0x5555555551d4 call 0x5555555550a0 <std::ostream::operator<<(std::ostream& (*)(std::ostream&))@plt> ;8 : return 0; 0x5555555551d9 mov eax,0x0 ;9 : } 0x5555555551de pop rbp 0x5555555551df ret
Compiled languages aren't the only variety - Java runs in a Java Virtual Machine, and Python is a scripting language that runs via a Python executable. But we're focusing on C++ here.
The point is, modern software is built on top of many layers: high-level languages that compile down to machine code, pre-written libraries of code that handle common features for the programmers so they don't have to reinvent the wheel.
- What is a program?
Since a computer needs to be told how to do everything, a computer program is a list of very specific instructions on how to execute some task (or tasks, for larger programs).
Figure 2: Inputs and Outputs
- Inputs:
Some programs don't take any input and just run a set of pre-defined instructions. Most programs do take some form of input, however, whether that's when the program first starts up or during its runtime.
Inputs could include things like passing in a filename to a program (e.g., please open this file) or other pieces of data, or getting keyboard input, gamepad input, mouse input, touch screen input, or receiving signals via the network or internet.
- Outputs:
Programs also often will return some form of output, but this is also optional. If a program doesn't return output, maybe the user just wants to tell the program to do a job, but doesn't need confirmation that the job was done (these are usually called background processes).
Outputs could be something like displaying a message box, changing text on the screen, playing a sound, or writing out a text file.
Figure 3: Variables
- Variables:
Our program may also use variables to store data during its execution. Variables are locations in memory (RAM) where we can store numbers, text, or more complex objects like an image. We give variables a name to reference it by, such as
userName
orcartTotal
, and we can do math operations on it, as well as write it to the screen or read new values into it from the user. - Branching and looping:
Figure 4: Branching
We can also change the instructions our program runs based on some condition we set. For example, if
bankBalance < 0
then maybe we display an error message. Otherwise, we can withdraw someamount
of money from thebankBalance
.Figure 5: Looping
We may also want to take advantage of looping to do a set of instructions repeatedly, possibly with some variables changing each time through the loop. An example for this could be to loop over all of a student's
assignmentGrades
, adding up all the points so we can find an average. - Example programs
Area calculator
This program asks the user to enter a width and a height and then calculate the area of the rectangle with the given information.
cout << "Width: "; // Display message cin >> width; // Get user input cout << "Height: "; // Display message cin >> height; // Get user input area = width * height; // Do math cout << "Area: " << area << endl;
Recipe program
This program asks the user how many batches of a recipe they'd like to make. Then, it adjusts the ingredient amounts for each ingredient and displays the updated ingredient list to the screen.
cout << "How many batches? " // Display message cin >> batches; // Get user input flour = 2.75 * batches; // Calculate amounts bakingSoda = 1 * batches; butter = 1 * batches; whiteSugar = 1.5 * batches; eggs = 1 * batches; vanilla = 1 * batches; cout << flour << " cups flour" << endl; cout << bakingSoda << " tsp baking soda" << endl; cout << butter << " cups butter" << endl; cout << whiteSugar << " cups white sugar" << endl; cout << eggs << " eggs" << endl; cout << vanilla << " tsp vanilla" << endl;
ATM - Withdrawing money
This program asks the user how much they'd like to withdraw from their account. If the withdraw amount is more than their account balance, then an error message is displayed. Otherwise, the amount is withdrawn from their bank account.
cout << "Withdraw: "; // Display message cin >> withdrawAmount; // Get user input if ( withdrawAmount > bankBalance ) cout << "Error! Not enough money." << endl; else bankBalance = bankBalance - withdrawAmount;
- Inputs:
- C++ Programs
Each programming language is a little different in how it looks, but whether you're using C++, Java, C#, Python, or many other languages, you'll still encounter branching with if statements, looping, functions, and classes (though older languages may not have classes at all, like C!).
main()
: The starting point
With C++, Java, and C#, programs must begin in a function called `main()`. The compiler (that turns the program into machine code) is always expecting `main()` to be there and to begin running the program at the top of it.
- Basic C++ syntax
In C++, Java, C#, and other C-like languages, there are some basic rules of syntax you should know about:
- Lines of code:
A code statement ends with a semi-colon. Statements are single commands like
cout
(console-out) to display text to the output,cin
(console-in) to read input from the keyboard, declaring variables, assigning variables, or doing math operations. - Variable names:
There are some rules for naming variables in C++. Generally, you can use any upper or lower case letters, numbers, and underscores in variable names - no spaces allowed. Beyond that, variables cannot begin with a number, and you cannot use a keyword (such as
if
) as a variable name. - Code blocks:
There are certain types of instructions that contain additional code. If statements, for example, contain a set of instructions to execute only if its condition evaluates to `true`. Any time an instruction contains other instructions, we use opening and closing curly braces
{}
to contain this internal code. Additionally, with these instructions, they do not end with semicolons. - Comments:
It is often useful to add comments to programs to specify what is going on in the code. There are two ways to add comments in C++. Generally, you can use any upper or lower case letters, numbers, and underscores in variable names - no spaces allowed. Beyond that, variables cannot begin with a number, and you cannot use a keyword (such as
if
) as a variable name. - Whitespace and code cleanliness:
Generally, C++ doesn't care if multiple commands are on one line or several lines. The compiler is going to compile it all either way. You should, however, care about the code's readability to humans. Add enough new lines to separate sections of a program, use consistent indentation, and give variables descriptive names.
When writing code inside of a code block, you should always tab forward internal code by one tab:
if ( order == "dessert" ) { // One tab forward cout << "Order: dessert" << endl; if ( have_cake ) { // One more tab forward cout << "You get cake!"; } else { // One more tab forward cout << "Sorry, we're out of dessert!"; } }
- Lines of code:
- Diagnosing, testing, and debugging
Figure 6: Debugging
Software is an amorphous, intangible thing of arbitrary complexity. It's bad enough when you're working alone, but once you get other people involved at varying skill levels (and varying levels of writing clean code), the amount of potential issues can quickly skyrocket.
There are techniques to writing software that can help you validate your own logic and check for errors before they occur, as well as tools to help you diagnose and debug issues, as well as error messages to also help give hints to what's going wrong. All of these things are important to becoming a good software developer.
- Synax, Runtime, and Logic errors
- Syntax errors:
The best type of error you can get is a syntax error, even though it may feel bad to get them. Syntax errors are when you have a typo or have otherwise miswritten a statement in the code, and the compiler doesn't know what to do with it. It will then display a build error telling you what it needs. Diagnosing syntax error messages can be confusing at first: often the compiler doesn't know exactly what's wrong, just what it's expecting. But, the good thing about syntax errors is that your program won't run if it can't build - that means you must fix these errors before continuing. It also means that these errors can't just be hidden in the code, like other error types.
- Logic errors:
Another type of error that's much harder to track down are logic errors. Logic errors can be errors in formulas, bad if statement conditions, or other things that don't do what the programmer was intending to do (again, either because of a typo, or not quite understanding the program flow, or for other reasons). Logic errors don't show up in the error list, but can cause your program to crash down the line - or worse, never crash but create bad output. Because it's not crashing, you may assume everything is working fine, but incorrect output can cause problems.
- Runtime errors:
When a logic error causes the program to crash while it's running, it is called a runtime error.
- Syntax errors:
- Debugging
At some point, you will need to debug a program that builds and runs, but something is just wrong. Perhaps it crashes, or perhaps it just doesn't do what you expect it to. We will learn about how to use debugging tools in IDEs like Visual Studio and Code::Blocks later on. Some of the tools included in a debugger are:
- Breakpoints: You can set these in your code and when the program reaches that part it will pause execution. Then, you can investigate the values of different variables, and also keep stepping forward line-by-line to observe changes and program flow.
- Watch windows: You type in variable names in these windows and it will show you the variable values at different points in the program (using breakpoints).
- Call stack: This will show which functions have been called up until where you're paused in the program. This can be handy to see how the program flows between different functions.
- Output here, there, everywhere:
A common, though somewhat unsophisticated debugging technique, is to add output statements at various points in your program to essentially "trace" the program flow - what is getting executed? What is displayed before the program crashes? This technique takes more cleaning up after you're done, and is only so helpful, but it can be a good way to see how your program is running.
- Testing
Programs need to be tested. Starting off, you will probably be manually running the program, entering inputs, and checking outputs. However, this gets tedious after a while and you'll probably start entering gibberish as inputs and assuming everything works if it outputs something. Manual testing is good to do, but it is easy to become sloppy. You can also write code to automatically test certain things for you. This will become more relevant to us once we're working with functions in C++.
The main idea behind testing is that programs or functions will be taking some sort of inputs, and given those inputs you have some expected outputs or results. If the actual outputs don't match the expected outputs, then there is something wrong.
We will cover testing techniques more later on.
- Coding techniques for newbies
When you're first starting with C++, it can feel like your code just never works. It can be good to adopt a few of these practices while you're still new, to minimize errors and frustration:
- Compile often: Get into the habit of using keyboard shortcuts to build your code after every few lines - especially when you're first starting out. If you write two lines of code and get a syntax error, it's much easier to diagnose than if you write a whole program and then build.
- Search for syntax error messages: Most of these messages have been posted about before on boards like Stack Overflow. Reading through these can help give you insight into what the error means, and common ways to fix them.
- Comment things out: If you have a lot of code but can't get it compiling and aren't sure what to do, you can comment out large chunks of the program until it builds again. Then, bit by bit, uncomment out different regions until you find what's causing the build error.
These practices can help you become a more efficient and effective programmer, especially when you're first starting out. Debugging and testing are essential skills for any programmer, and learning them early can save you a lot of time and frustration in the long run.
Review questions:
- Programs take in __ and return __.
- Variables are used to…
- Branching is used to…
- Loops are used to…
- Synax, Runtime, and Logic errors
π Concept Intro - Exploring software (U01.CIN)
π§ Tech Literacy - Exploring software (U01.TEC)
- Early personal computers
Before the 1980s computers were mostly owned and operated by the government, universities, and large corporations. During the 1980s, companies began selling computers, such as the Apple ][, Vic-20, Acorn, ZX Spectrum, and more. These computers were small, usually hooked into a home television set, and were interacted with through a keyboard - mice weren't standard early on. Additionally, often these computers didn't have a hard drive for long-term data storage - and just a very rudimentary operating system. Programs were on floppy disk, casette tape, or even cartridge, and data also had to be stored externally.
Early \(5 \frac{1}{4}\) floppy disks had a capcity of only 360 KB to 720 KB, with smaller \(3 \frac{1}{2}\) inch floppy diskettes storing aronud 1.44 MB. (Numbers pulled from https://en.wikipedia.org/wiki/Floppy_disk). How big is this?
Well, with 1 B (one bit), you can store two possible values: 0 or 1. A byte is eight bits, which can store 00000000 to 11111111, so numeric values between 0 and 255. If you were storing a series of text, one of 26 letters, you could use several bytes in a row to represent a sentence.
HELLO
becomes72 69 76 76 79
using the ASCII standard (number codes to represent letters and other things)- Converting the ASCII values to binary gives us
01001000 00100000 01000101 00100000 01001100 00100000 01001100 00100000 01001111
We don't usually measure file size in Bytes anymore - usually we use Kilobytes KB (1 KB = 1024 B), Megabytes MB (1 MB = 1024 KB), Gigabytes (1 GB = 1024 MB), and Terabytes (1 TB = 1024 GB).
Here's a comparison of common storage medium capacities:
Floppy disk Diskette CD DVD Blu-Ray 360 KB 1.44 MB 700 MB 4.7 GB 50 GB Beyond the lack of storage space, graphics modes were low resolution and only offered a few colors, if any. Often these computers also only had a speaker capabale of playing certain tones at certain frequencies - not recorded wave files. And since it was the early days of computing at home there wasn't really a standard to follow as far as interface design goes.
The programs we'll be writing for this course will be similar to these early day programs - specifically, text-based programs with few (if any) colors.
- Computers before the Mouse
Figure 7: A screenshot of a Vic-20 screen. Screenshot taken from the VICE VIC20 emulator. 3583 bytes free.
Average people began being able to afford personal desktop computers during the 1980s. These computers usually had hookups for average television sets. The computers weren't very powerful, so the low resolution of a TV generally worked fine. With a computer like the Commodore Vic-20, it was able to display 22 columns of text (wide) and 23 rows of text (tall). Some computers had slightly higher resolutions, but these were still quite far from high resolution screens we know today.
These computers did not have hard-drives to store data in the long-term. Instead, users often had to buy a floppy disk drive (or two!) or a casette tape reader. They could also sometimes read in programs from cartridges, similar to old video game systems. Input for these old computers were mostly the keyboard, and perhaps a joystick for playing games. With all of these constraints, software had to be small and low resolution.
- Early GUIs and the Mouse
Figure 8: Original Apple Macintosh desktop sample, unattributed ()
Figure 9: Screenshot of Microsoft Windows 1.0 operating environment showing MS-DOS Executive and other applications, screenshot taken by Remember the dot. ()
Early Graphical User Interfaces (or GUIs) began popping up in the late 80s and early 90s, most notably with the Apple Macintosh and Microsoft Windows. The mouse was becoming part of a standard computer setup, and these operating systems provided a cursor (the little arrow pointer) to show where you're pointing to on the screen. This allowed everyday users to be able to work with their computer's software and configuration without having to memorize text commands or referring back to a manual.
At this point hard drives were also more common, though still very tiny compared to today's systems. In the screenshot of Windows 1.0 above, it lists "Disk Space Free" as "30024K", which is basically about 30 MB.
We still had constraints around low resolution, low memory, and low long-term storage, and programs were small and still pretty simple.
- Smart Phones and Touch-based input
Desktop PCs were the main way to use computers throughout the 90s and 2000s, but in the late 2000s Smart Phones launched and a new design language was being created - touch screen-only devices. (RIP my Samsung Messager with a physical keyboard.) While touchscreens had existed before, often they were interacted with via a stylus.
Designing around pressing the screen with a finger meant having to reimagine how we do our core operations, from mouse to finger. How do we scroll a page? (No mouse wheel…) How do we select an option? (With a mouse we'd single or double click, but double tap didn't catch on…)
The widespread use of smartphones even affected how we designed webpages. No more pages full of text content that you navigate with the precision of a mouse, now pages evolved to fluidly fit whatever screen you were on, text links became buttons with clearly clickable regions, and expandable "burger" menus became more commonplace.
Figure 10: Burger button
Throughout the past two decades, memory and storage space continued to increase in capacity while getting cheaper, many tasks and much of our storage has been offloaded onto "cloud" servers elseware, and so many programs utilize the internet in order to perform its core functionality. For better or worse.
- Discussion board
Tech Literacy Assignment:
- Look at some files on your computer or phone. Write down the sizes of some file types.
What kind of file type were you looking at, and how big was it?
Some example file formats are:
- A text document written in a program like Word or LibreOffice Write (.docx, .odt files).
- A .jpg of a photograph.
- A video file.
- Play at least two of the following games for at least a few minutes:
- Games:
- Zork: https://www.pcjs.org/software/pcx86/game/infocom/zork1/
- The Oregon Trail: https://www.pcjs.org/software/pcx86/game/other/1990/oregon_trail/
- Lode Runner: https://www.scullinsteel.com/apple2/#lode_runner (IJKL to move, U and O to dig holes)
- Rogue: https://www.pcjs.org/software/pcx86/game/other/1985/rogue/
- Games:
- Answer the following questions:
- Give an example of a phone app that you use.
- Give an example of desktop software that you use.
- Note which of the two games above you tried out.
- Judge the user experience of each: Are they easy to navigate? Are the programs fast and responsive? Are there any noticable delays while using each program?
- Choose one of the programs (phone app/desktop software/old games) and give a couple of examples of how you might improve the user interface, or overall user experience.
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3771248
\newpage
- Look at some files on your computer or phone. Write down the sizes of some file types.
What kind of file type were you looking at, and how big was it?
Some example file formats are:
ποΈ Nonogram - Nonogram A (U01.EXE.N)
How to play: Each cell in the grid of squares can either have a X (or blank) or be filled in. The filled in boxes create the pixels of an image. Each row and each column have one or more numbers. This specifies how many pixels are in that row/column. The number given is how many unbroken pixels will show up together. Two numbers separated by a space, e.g., "1 1", will have at least one empty spot between them.
Hint: Among Us
Hint: Star
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3742032
π§βπ« Status Update - Welcome, Setup, Exploring Software (U01.SUP)
WEEK 2 - JAN 29
UNIT 02: Command line
π Presentation - Command line programs (U02.PRES)
π§ Tech Literacy - Command Line programs (U02.TEC)
- A brief history of interfacing with computers
Early computers were a shared resource, with one mainframe computer shared by many people at a university, business, or elseware. People often wrote programs on paper punchcards using dedicated hardware separate from the computer itself. (See: 1964 IBM 029 Keypunch Card Punching Demonstration (CuriousMarc))
Figure 11: By Pete Birkinshaw from Manchester, UK - Used Punchcard, CC BY 2.0,
Similarly, early computers didn't necessarily utilize video screens or monitors for output. Since the computer was shared, you might drop off your batch of cards for your program and come back later for the result output. If you think about it, a paper-based printout was probably the most cost-effective way for this. (See: YouTube: The IBM 1401 Mainframe Computer Wishes you a Merry Christmas (CuriousMarc) - Feeding a mainframe punchcards and getting printed output)
Even when video monitors were available for these mainframe computers, the computers were still a shared resource being used by multiple people sharing computer time. In cases like these, users would work at a terminal. These look like what we think of as computers, with a video display and a keyboard, but they don't do any processing on their own. These terminals were connected to the mainframe computer, allowing users in other locations to interact with it via a simple text interface.
Figure 12: By IBM - https://digitaltmuseum.no/011015240147/22-0-ibm-modell-360-370, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=113477774
Even as Personal Computers began taking root in households in the 1980s, only rudimentary graphics were available (if any), such as drawing large blocks with some basic colors, or drawing pixels at specific positions on a low resolution screen. For daily use, typed commands were still largely how people interacted with the operating system of their computer, and for many of their programs as well.
Figure 13: A photo of a Vic-20 BASIC program displayed on a CRT television.
If a program did offer some kind of graphical user interface, at the time there were no standards and programs by different developers would often have wildly different interfaces, keyboard shortcuts, and styles.
- Who uses command line programs these days?
In a way, there are still challenges around different types of interfaces. We have computers running different operating systems like Windows, Mac OS, Linux, and Unix, we have smartphones running their own operating systems as well. Beyond that, people might install different types of software or configure their personal computers differently. Under the surface, however, there is still some form of command line, though the commands may differ between a Windows PowerShell and a Linux/UNIX Bash system. So, what do these non-GUIs offer in utility?
- Consistency
- Sometimes I try to help out a person on a Mac computer, though I have almost no experience
with that operating system. Often, I find it more comfortable to navigate through the Mac Terminal
to utilize the UNIX-like commands that are in common with Linux - such as
ls
to list files and folders in a directory. Rather than have to learn a GUI for a system I'll never use on my own, I can interact with it with a "common tongue" - the command line. :) - Scriptability
- Think of the effort it takes to automate doing anything with a GUI - you'll need some kind of program or library that allows moving the mouse to some (x,y) position, hit mouse clicks, type keys, etc. And even then, windows in a GUI might move around. It's much easier to write a program script to automate running commands from a command line instead - it's just text commands!
- Speed
- Command lines generally can be more responsive than a GUI. I find that even on computers that
aren't too old, Windows slogs along. Command lines don't necessarily use your computer's graphics card to make the
windows semi-transparent and animate when they perform some operation. And in some cases it can be faster to type
something like
mkdir cs200 cs235 cs250
to create three folders than to go through the steps to move mouse to "File", move mouse to "New Folder", click, type "cs200", repeat twice more. - Portability
- Being able to navigate a command line also makes it much easier to access remote computers. While you can run a computer remotely and work with the graphical operating system, it's still usually pretty sluggish. Instead, you could SSH into a computer and work with it from the command line and quickly perform some operations that you need, which could be remotely launching a build, restarting a server, or even writing some notes.
Most average computer users aren't using the command line in their personal lives, but it is still a hugely useful tool for people who work in IT and software. With IT, imagine you have to configure 20 computers per classroom, for all the classrooms in a building - would it be easier to manually go configure those computers from their GUIs, or to write a script and run that script on each computer?
- Why Computer Science courses don't (usually) teach GUI creation
- GUI libraries change over time
- Java and C# have both gone through various different systems for creating GUIs, such as WPF for old Windows programs, Swing for Java-based programs. But eventually they go out of date and stop being used.
- C++ isn't "owned" by a company like Microsoft or Oracle
- so there's no company to package some kind of UI library as the de-facto standard for C++ GUI development. There are open source tools (wxWidgets, Qt) and proprietary tools, but who knows what any given company uses for their software - if they even write desktop software at all anymore, anyway. Most things are HTML/CSS/JS based now. :)
- The study of Computer Science is more about how computers work rather than the design of front-ends.
- Adding a GUI layer on top of learning core C++ or about data structures can make the course content less focused and make it hard to understand the important parts on its own.
- Command line programs on your own computer
If you're on Windows open up the PowerShell. If you're on Mac open up the Terminal. If you're on Linux open up your favorite Terminal emulator or whatever. :) Let's look at some basic programs that might be useful.
ping URL
- Theping
program allows us to send multiple packets to some URL. I usually just use this to see if my internet has gone down or if a site is just down. I still, by habit, useping yahoo.com
even though I haven't used Yahoo in years. (FYI: Use CTRL+C to end a command line program if it continues looping.)
rachelwil@rachelwil-GF63-Thin-9SC:~$ ping yahoo.com PING yahoo.com (98.137.11.163) 56(84) bytes of data. 64 bytes from media-router-fp74.prod.media.vip.gq1.yahoo.com (98.137.11.163): icmp_seq=1 ttl=49 time=60.6 ms 64 bytes from media-router-fp74.prod.media.vip.gq1.yahoo.com (98.137.11.163): icmp_seq=2 ttl=49 time=63.1 ms 64 bytes from media-router-fp74.prod.media.vip.gq1.yahoo.com (98.137.11.163): icmp_seq=3 ttl=49 time=85.4 ms 64 bytes from media-router-fp74.prod.media.vip.gq1.yahoo.com (98.137.11.163): icmp_seq=4 ttl=49 time=69.7 ms ^C --- yahoo.com ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3004ms
mkdir FOLDER1 FOLDER2 FOLDER3
- Themkdir
(make-directory) program allows you to create 1 or more folders within the directory that you're currently in.ls
- Thels
(list) program shows you all the files and folders in the directory that you're currently in.pwd
- Thepwd
(present working directory) program shows you the path of the directory that you're currently in.
rachelwil@rachelwil-GF63-Thin-9SC:~/test-folder$ mkdir folderA folderB folderC rachelwil@rachelwil-GF63-Thin-9SC:~/test-folder$ ls folderA folderB folderC rachelwil@rachelwil-GF63-Thin-9SC:~/test-folder$ pwd /home/rachelwil/test-folder
Commands that you can use from the terminal can also be called from C++ by using the
system()
function. - See also
- YouTube: Tomorrow's World: Home Computer Terminal 20 September 1967 (BBC) - Using a teletype terminal to communicate with a remote computer
- YouTube: What are Dumb Terminals? (The 8-Bit Guy)
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3742323
UNIT 03: C++ basics
π Presentation - C++ basics (U03.PRES)
ποΈ Reading - C++ basics (U03.READ)
- An empty C++ program
The bare-minimum C++ program looks like this:
int main() { return 0; }
No matter what all is in your program, your compiler is going to expect that a
main
function exists, and this function acts as the starting point of a C++ program.The opening curly-brace
{
and closing curly-brace}
denote the start and end of themain
function. The curly-braces and any code within is known as a code-block. Program instructions will go within this code-block.At the end of the
main
function we havereturn 0;
. In this context, it means "return (exit) the program with a status of 0", with that basically meaning "return with no errors". If you ran into an error while the program was running, you might do something likereturn 123;
instead, to mark the area with an "error code" (123), which you can then find in the code.For our programs starting off, we will be putting our instruction code after the opening curly-brace
{
and before thereturn 0;
, but the code given above is the absolute, bare-minimum required to write a C++ program.Review:
- What function is the starting point of every C++ program?
- What is a code-block?
- What command means the program ended with no errors?
- An introduction to syntax
Context: What is syntax?
syntax, noun
The way in which linguistic elements (such as words) are put together to form constituents (such as phrases or clauses)
From the Merriam-Webster Dictionary.
C++, Java, C#, and other "C-like" languages follow similar syntax rules.
Lines of code: A code statement ends with a semi-colon. Statements are single commands, like using
cout
("console out") to display text to the screen, assigning a value to a variable, and other simple operations.string state; // Variable declaration cout << "Enter state: "; // Display text to screen cin >> state; // Getting input from keyboard cout << state << endl; // Displaying text to the screen
Code blocks: There are certain types of instructions that contain additional code. If statements, for example, contain a set of instructions to execute only if the condition given evalutes to
true
. Any time an instruction contains additional instructions, we use opening and closing curly braces{ }
to contain this internal code. Note that an if statement and other structures that contain code don't end with a semicolon;
.Comments: Comments are notes left in the code by humans for humans. They can help us remember what our code was doing later on, or help guide someone else reading through our code. There are two ways we can write comments in C++.
If we use
//
then all text afterwards will be a comment. This is a single-line comment.If we use
/*
then all text will be a comment, only ending once we reach a*/
. This is a multi-line comment.string state; // Variable declaration /* Next we're going to search for this state in the list of all states that match xyz criteria... */
Review:
- When should a line of code end with a semicolon
;
, and when will it have a code block{}
instead? - How do you write a single-line comment?
- How do you write a multi-line comment?
- Syntax errors and logic errors
Syntax errors are errors in the language rules of your program code. This include things like typos, misspellings, or just writing something that isn't valid C++ code, such as forgetting a
;
at the end of some instructions.Although they're annoying, syntax errors are probably the "best" type of error because the program won't build while they're present. Your program won't build if you have syntax errors.
Logic errors are errors in the programmer's logic. This could be something like a wrong math formula, a bad condition on an if statement, or other things where the programmer thinks thing A is going to happen, but thing B happens instead.
These don't lead to build errors, so the program can still be run, but it may result in the program crashing, or invalid data being generated, or other problems.
- Minimizing bugs and debugging time
- Write a few lines of code and build after every few lines - this will help you detect syntax errors early.
- DON'T write the "entire program" before ever doing a build or a test - chances are you've written in some syntax errors, and now you'll have a long list of errors to sift through!
- If you aren't sure where an error is coming from, try commenting out large chunks of your program until it's building again. Then, you can un-comment-out small bits at a time to figure out where the problem is.
- When should a line of code end with a semicolon
- Review questions
- What are syntax errors?
- What are logic errors?
- Variables and data
We use variables in programming as places to temporarily store data so that we can manipulate that data. We can have the user write to it via the keyboard, we can use files to write data to variables, we can do math operations or modify these variables, and we can print* them back out to the screen or a text file.
(*Printing here meaning "display on the screen"; not to a printer. Holdover from ancient times when computers' outputs came via the printers.)
When we're writing programs in C++, we need to tell our program what the data type of each variable is, and give each variable a variable name (aka identifier). When a variable is declared, a space in RAM is allocated to that variable and it can store its data there. That data can be manipulated or overwritten later as needed in the program.
- Data types
In C++, when we want to create a variable we need to tell the compiler what the data type of the variable is. Data types specify what is stored in the variable (whole numbers? numbers with decimal values? text? true/false values?). Each data type takes up a different amount of space in memory.
Data type Values Size Example code char single symbols - letters, numbers, anything 1 byte char currency = '$';
boolean true
orfalse
1 byte bool savedGame = false;
integer whole numbers 4 bytes int age = 100;
float numbers w/ decimals 4 bytes float price = 9.95;
double numbers w/ decimals 8 bytes double price = 1.95;
string any text, numbers, symbols, any length variable string password = "123secure";
Of these, notice that the string data type doesn't have a fixed size. This is because technically, behind-the-scenes, a string is really just an array (or list) of char data types. The C++ standard library contains a string library that handles a lot of text-related functionality like find.
Floats and doubles both store numbers with fractional (decimal) parts, but a double takes up double the memory in RAM, allowing to store more accurate fractional amounts. A float has 6 to 9 digits of precision and a double has 15 to 18 digits of precision .(From https://www.learncpp.com/cpp-tutorial/floating-point-numbers/)
Boolean data types store true and false values, but will also accept integer values when assigned. It will convert a value of 0 to false and any other number to true.
- Data types
- Declaring variables and assigning values to variables
Variable declaration
When we're declaring a variable, it needs to follow one of these formats:
DATATYPE VARIABLENAME;
DATATYPE VARIABLENAME = VALUE;
DATATYPE VARIABLENAME1, VARIABLENAME2, VARIABLENAME3;
DATATYPE VARIABLENAME1 = VALUE1, VARIABLENAME2 = VALUE2;
The data type goes first, then the variable name/identifier, and if you'd like, you can also assign a value during the same step (though this is not required).
Once a variable has been declared, you don't need to declare it again. This means you don't need to re-specify its data type when you're using it. Just address the variable by its name, and that's all.
Code that uses integers to figure out how many candies each kid should get:
// Declaring variables and assigning values int totalCandies = 10; int totalKids = 5; int candiesPerKid = totalCandies / totalKids; // Reusing the same variables later on totalCandies = 100; totalKids = 10; candiesPerKid = totalCandies / totalKids;
Code to display the price plus tax to the user:
float price = 9.99; float tax = 0.11; // Text output to the screen. Can do math within! cout << "Please pay " << (price + price * tax);
Variable assignment
VARIABLENAME = LITERAL;
- Stores the LITERAL value in VARIABLENAME.VARIABLENAME1 = VARIABLENAME2;
- Copies the value from VARIABLENAME2 to VARIABLENAME1.
When assigning a value to a variable, the variable being assigned to always goes on the left-hand side ("LHS") of the equal sign =. The = sign is known here as the assignment operator.
The item on the right-hand side ("RHS") will be the value stored in the variable specified on the LHS. This can be a literal (a hard-coded value) or it can be a different variable of the same data type, whose value you want to copy over.
Assigning literal values to variables:
price = 9.99; // 9.99 is a float literal state = "Kansas"; // "Kansas" is a string literal operation = '+'; // '+' is a char literal
Copying student13's value to the bestStudent variable:
bestStudent = student13;
- Naming conventions
You can name a variable anything you'd like, but it can only contain numbers, underscore (
_
), and upper- and lower-case letters in the name. Variable names can begin with the underscore or a letter, but they cannot start with a number. And definitely NO spaces are allowed in a variable name!Additionally, a variable name cannot be a keyword in C++, a name reserved for something else in the language, such as
void
,if
,int
, etc.Everything in C++ is case sensitive, which means if you name a variable
username
, it will be a different variable from one nameduserName
(or if you type "userName" when the variable is called "username," the compiler will complain at you because it doesn't know what you mean).One common way variables are named are using camelCasing, where each subsequent word in a variable's name is capitalized:
int howManyCookies; string mySecurePassword; float howMuchStudentLoansIHave;
Another common way you might see variables named in C++ is using underscores to split up words:
int how_many_cookies; string my_secure_password; float how_much_student_loans_i_have;
I just want you to be consistent with your style, though you can choose either one of these styles.
- Unsigned data types
Sometimes it doesn't make sense to store negative values in a variable - such as speed (which isn't directional, like velocity), the size of a list (can't have negative items), or measurement (can't have negative width). You can mark a variable as unsigned to essentially double its range (by getting rid of the negative side of values). For instance, a normal int can store values from -2,147,483,648 to 2,147,483,647, but if you mark it as unsigned, then your range is 0 to 4,294,967,295.
- Modern C++:
auto
In C++11 (from 2011) and later, you can use the keyword
auto
as the "data type" in your variable declaration that includes an assignment statement. When you useauto
, it uses the assigned value to automatically figure out the variable's data type, so you don't have to explicitly define it:auto price = 9.99; // it's a double! auto price2 = 2.95f; // it's a float! auto player = '@'; // it's a char! auto amount = 20; // it's an int!
- Basic operations on variables
Now that you have variables available in your program to play with, what can you even do with them?
- Outputting variable values
Using the
cout
(console-out) statement, you can display text to the screen with string literals:cout << "Hello, world!" << endl;
But you can also display the values stored within variables, simply by using the variable's name:
cout << myUsername << endl;
(We will cover more about input and output next part)
- Inputting variable values
We can use the
cin
(console-in) statement to get the user to enter something on the keyboard and store that data into a variable:cin >> favoriteColor;
- Math operations
With variables with numeric data types (ints, floats, doubles), we can do arithmetic with the +, -, *, and / operators.
cout << "Sum: " << num1 + num2 + num3 << endl;
Operations:
Symbol Description +
Addition -
Subtraction *
Multiplication /
Division Make sure to put the result somewhere! When you do a math operation and you want to use the result elsewhere in the program, make sure you're storing the result in a variable via an assignment statement! If you just do this, nothing will happen:
totalCats + 1;
You can use an assignment statement to store the result in a new variable:
newCatTotal = totalCats + 1;
Or overwrite the variable you're working with:
totalCats = totalCats + 1;
Compound operations: There are also shortcut operations you can use to quickly do some math and overwrite the original variable. This works with each of the arithmetic operations:
cpp
// Long way: totalCats = totalCats + 5; // Compound operation: totalCats += 5;
- String operations
Strings have some special operations you can do on them. You can also see a list of functions supported by strings here: C++ String Reference (We will cover more with strings in a later part).
Concatenating strings: You can use the
+
symbol to combine strings together. When used in this context, the + sign is called the concatenation operator.string type = "pepperoni"; string food = "pizza"; // Creates the string "pepperoni pizza" string order = type + " " + food;
Letter-of-the-string: You can also use the subscript operator
[ ]
(more on this when we cover arrays) to access a letter at some position in the string. Note that in C++, the position starts at 0, not 1.string food = "pizza"; char letter1 = food[0]; // Stores 'p' char letter2 = food[1]; // Stores 'i' char letter3 = food[2]; // Stores 'z' char letter4 = food[3]; // Stores 'z' char letter5 = food[4]; // Stores 'a'
- Outputting variable values
- Named constants
Whenever you find yourself using a literal value in your assignment statements, you may want to think about whether you should replace it with a named constant instead.
A named constant looks like a variable when you declare it, but it also has the keyword const - meaning that the value can't change after its declaration.
Named constant declaration format:
const CONSTNAME = LITERAL;
- Stores the LITERAL value in CONSTNAME.Let's say you wrote a program and hard-coded the tax rate:
// Somewhere in the code... checkoutPrice = cartTotal + ( cartTotal * 0.0948 ); // Somewhere else in the code... cout << 0.0948 << " sales tax" << endl;
Then the tax rate changes later on. You would have to go into your program and search for "0.0948" and update all those places!
Instead, it would have been easier to assign the tax rate ONCE to a named constant and referred to that instead:
// Beginning of program somewhere... const SALES_TAX = 0.0948; // Somewhere in the code... checkoutPrice = cartTotal + ( cartTotal * SALES_TAX ); // Somewhere else in the code... cout << SALES_TAX << " sales tax" << endl;
If you ever find yourself using the same literal multiple times in your program, then perhaps consider replacing it with a named constant.
Named constant naming convention: In C++, it is customary to give your named constants names in ALL CAPS, using underscores (
_
) to separate words.
- Interactivity and Output in C++
Most programs feature interactivity in some way or another. This can involve moving a mouse around, clicking on things, tapping on a touch screen, using a gamepad's joysticks and buttons, but we'll be primarily interacting with our C++ programs through keyboard input. Feedback from our C++ programs will come in the form of text output to the screen, as we are writing terminal programs.
We will also delve into reading from and writing to text files (or other file formats) later on. But for now, let's focus on the terminal/console.
- Outputting Information with
cout
The
cout
command (pronounced as "c-out" for "console-out") is used to write information to the screen. This can include outputting a string literal:cout << "Hello, world!" << endl;
or a variable's value:
cout << yourName << endl;
or stringing multiple things together:
cout << "Hello, " << yourName << "!" << endl;
In C++, we use the output stream operator
<<
to string together multiple items for our output.
- Newlines with endl
The
endl
command stands for "end-line" and ensures there is a vertical space between thatcout
statement and the next one. For example, if we write twocout
statements without endl like this:cout << "Hello"; cout << "World";
the output will be:
HelloWorld
If we want to separate them on two different lines, we can write:
cout << "Hello" << endl; cout << "World";
And our output will be:
Hello World
Remember that in C++, a statement ends with a semicolon ;, so you can split your
cout
statement across multiple lines, as long as you're chaining items together with<<
and only adding a;
on the last line:cout << "Name: " << name << "Age: " << age << "State: " << state << endl;
- Inputting Information with
cin
When we want the user to enter a value for a variable using the keyboard, we use the
cin
command (pronounced as "c-in" or "console-in").For variables like int and float, you will use this format to store data from the keyboard into the variable:
- Using
cin >>
for variables
cin >> VARIABLENAME;
You can also chain cin statements together to read multiple values for multiple variables:
cin >> VARIABLENAME1 >> VARIABLENAME2 >> ETC;
- Strings and
cin >>
When using
cin >>
with a string variable, keep in mind that it will only read until the first whitespace character, meaning it can't capture spaces or tabs. For example:string name; cin >> name;
If you enter "Rachel Singh", name will contain "Rachel". To capture spaces, you need to use a different function.
- Using
getline(cin, var);
for Strings
You can use the getline function to capture an entire line of text as a string. This is useful when you want to capture spaces and multiple words. For example:
string name; getline(cin, name);
- Mixing
cin >> var;
andgetline(cin, var);
If you mix
cin >> var;
andgetline(cin, var);
, you might encounter issues with the input buffer. To avoid this, usecin.ignore();
beforegetline(cin, var);
if you usedcin >> var;
before it.int number; string text; cin >> number; cin.ignore(); getline( cin, text );
- Escape Sequences
There are special characters, called escape sequences, that you can use in your
cout
statements:Character Description \n
newline (equivalent to endl
)\t
tab \"
double quote Example code:
cout << "\"hello\nworld\"" << endl;
Output:
"hello world"
Example code:
cout << "A\tB\tC" << endl; cout << "1\t2\t3" << endl;
Output:
A B C 1 2 3
Example code:
cout << "He said \"Hi!\" to me!" << endl;
Output:
He said "Hi!" to me!
- Using
- Outputting Information with
- Review questions
- What is the output stream operator?
- What is the input stream operator?
π Concept Intro - C++ basics (U03.CIN)
π§βπ¬ Lab - C++ basics (U03.LAB)
- Assignment
- This assignment has several small C++ programs that you will implement, following along with the instructions.
- Goals
- Practice with creating C++ programs
- Practice with declaring and using variables
- Practice with using
cout
to display text - Practice with using
cin
to get input
- Turn-in
- Once finished, you will upload your code to GitLab, and submit the URL to the Unit 03 folder. Canvas link: https://canvas.jccc.edu/courses/68294/modules/items/3901100
- Starter code
Make sure that you have already downloaded the starter code off your repository. If you don't already have it downloaded, click on the blue "Code" button, and select "zip" to download the source code.
Make sure to extract the zip file on your computer.
The program files we're going to use are in the u03CPPBasics folder. There are several different folders within:
. ├── graded_program │ └── program.cpp ├── practice1_greeting │ └── greetings_v1.cpp ├── practice2_arguments │ └── greetings_v2.cpp ├── practice3_calc │ └── calc.cpp ├── practice4_cinstream │ └── perimeter.cpp └── practice5_getline └── pet.cpp
Rules:
- You can score up to 100% just by turning in the
graded_program
item. - If you turn in the practice programs as well, you will earn extra credit points.
- Doing the practice programs are recommended.
practice1_greeting
:This program starts off partially written:
// PROGRAM: Console output practice // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // TODO: Update the placeholder text below, NAME, COLOR, and SOMETHING, with your own text. cout << "Hello, I'm: NAME" << endl; cout << "My favorite color is: COLOR" << endl; cout << "This semester I hope to learn about... SOMETHING" << endl; // Return 0 means quit program with no errors, in this context. return 0; }
There are certain comments marked
TODO
that have instructions. For this assignment, you'll do the following:- Replace
NAME
with your name - Replace
COLOR
with your favorite color - Replace
SOMETHING
with something you'd like to learn about
After you've substituted the text, we're going to build and run the program.
Open up the terminal, or power shell, within the
practice1_greeting
folder.((TODO: ADD IMAGE))
Build the program with
g++ greetings_v1.cpp
Then run the program with
./a.exe
$ g++ greetings_v1.cpp $ ./a.exe Hello, I'm: Rachel My favorite color is: Purple This semester I hope to learn about... Cmake :)
practice2_arguments
:Starter code:
// PROGRAM: Variable assignment practice // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // TODO: Update the variables below to use your own text. string name = "NAME"; string color = "COLOR"; string learn_about = "SOMETHING"; // You don't have to update anything here now, these output statements are using // the variables to get their data from! cout << "Hello, I'm: " << name << endl; cout << "My favorite color is: " << color << endl; cout << "This semester I hope to learn about... " << learn_about << endl; // Return 0 means quit program with no errors, in this context. return 0; }
This second program is similar to the first one, except that we're using variables to store your name, favorite color, and something you'd like to learn.
Substitute the following in this code:
- Replace
NAME
with your name - Replace
COLOR
with your favorite color - Replace
SOMETHING
with something you'd like to learn about
Afterwards, build and run the program to make sure it still runs:
$ g++ greetings_v1.cpp $ ./a.exe Hello, I'm: Rachel My favorite color is: Purple This semester I hope to learn about... Cmake :)
practice3_calc
:Starter code:
// PROGRAM: Variable arithmetic practice // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // Declaring variables float num1, num2; // Ask the user to enter num1 cout << "Please enter num1: "; // Display prompt cin >> num1; // Get input from keyboard // Ask the user to enter num2 cout << "Please enter num2: "; // Display prompt cin >> num2; // Get input from keyboard // Declaring more variables float sum, difference, product, quotient; // TODO: Assign the variable `sum` the value of `num1` plus `num2`. // TODO: Assign the variable `difference` the value of `num1` minus `num2`. // TODO: Assign the variable `product` the value of `num1` times `num2`. // TODO: Assign the variable `quotient` the value of `num1` divided by `num2`. cout << endl; // Adding more space cout << "ARITHMETIC:" << endl; cout << "SUM: " << num1 << " + " << num2 << " = " << sum << endl; cout << "DIFFERENCE: " << num1 << " - " << num2 << " = " << difference << endl; cout << "PRODUCT: " << num1 << " * " << num2 << " = " << product << endl; cout << "QUOTIENT: " << num1 << " / " << num2 << " = " << quotient << endl; // Return 0 means quit program with no errors, in this context. return 0; }
For this program, there are two float variables declared:
num1
andnum2
. The program already contains somecin
statements to get values into unm1 and num2.There are also four "results" float variables declared:
sum
,difference
,product
, andquotient
. Under teach comment that saysTODO
, write down a math operation:- Add
num1
andnum2
and store the result in thesum
variable. - Subtract
num1
andnum2
and store the result in thedifference
variable. - Multiply
num1
andnum2
and store the result in theproduct
variable. - Divide
num1
andnum2
and store the result in thequotient
variable.
Remember that assignment statements are written in this form:
VARIABLE = VALUE;
After implementing it, build and test the program. If the math comes out wrong, then try to investigate your code and see if you can find a logic error.
$ g++ calc.cpp $ ./a.exe Please enter num1: 5 Please enter num2: 10 ARITHMETIC: SUM: 5 + 10 = 15 DIFFERENCE: 5 - 10 = -5 PRODUCT: 5 * 10 = 50 QUOTIENT: 5 / 10 = 0.5
practice4_cinstream
:Starter code:
// PROGRAM: Console input and variable arithmetic practice // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // TODO: Declare a float variable for `width`. // TODO: Declare a float variable for `length`. // TODO: Use `cout` to display a prompt - tell the user - "Enter a width: " // TODO: Use `cin` to get keyboard input, store in `width` variable. // TODO: Use `cout` to display a prompt - tell the user - "Enter a length: " // TODO: Use `cin` to get keyboard input, store in `length` variable. // TODO: Declare a float variable `perimeter`, assign it the result of `2 * width + 2 * length`. // TODO: Declare a float variable `area`, assign it the result of `width * length`. // TODO: Use `cout` to display "Perimeter:", and then the value of the `perimeter` variable. // TODO: Use `cout` to display "Area:", and then the value of the `area` variable. // Return 0 means quit program with no errors, in this context. return 0; }
For this program you will do all the steps to create variables to store a rectangle's width and length, display messages to the screen, get input from the keyboard, do the math, and display the result. You can always look at the previous programs for reference as well.
The steps are:
- Declare a float variable named
width
- Declare a float variable named
length
- Display a message to the user, saying "Enter a width:"
- Get input from the keyboard, store the result in the
width
variable - Display a message to the user, saying "Enter a length:"
- Get input from the keyboard, store the result in the
length
variable - Declare a float variable named
perimeter
, assign it the result of2 * width + 2 * length
- Declare a float variable named
area
, assign it the result ofwidth * length
- Display "Perimeter:" and then the value of the
perimeter
variable - Display "Area:" and then the value of the
area
variable
$ g++ perimeter.cpp $ ./a.out Enter a width: 4 Enter a length: 3 Perimeter: 14 Area: 12
practice5_getline
:Starter code:
// PROGRAM: cin and getline practice // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <iomanip> // Library for text formatting, has `setw`, `left`.` #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // ------- GET USER INPUT ------- cout << "---- PET 1 ----" << endl; // Declaring variables string pet1_name; int pet1_age; string pet1_animal; string pet1_breed; // Ask the user to enter information... cout << "Name: "; // Display prompt getline( cin, pet1_name ); // Get string input cout << "Age: "; // Display prompt cin >> pet1_age; // Get int input cin.ignore(); // Flush the input buffer cout << "Animal: "; // Display prompt getline( cin, pet1_animal ); // Get string input cout << "Breed: "; // Display prompt getline( cin, pet1_breed ); // Get string input cout << endl << "---- PET 2 ----" << endl; // TODO: Create variables `name2`, `age2`, `animal2`, `breed2`, based on the previous example. // TODO: Ask the user to enter the name, age, animal, and breed for pet 2. // ------- DISPLAY RESULTS ------- cout << left; // Set left alignment cout << endl; // Add more spacing const int COL1 = 7; const int COL2 = 20; const int COL3 = 7;; const int COL4 = 15; const int COL5 = 15; cout << "Collected information:" << endl << endl; cout << setw( COL1 ) << "PET#" << setw( COL2 ) << "NAME" << setw( COL3 ) << "AGE" << setw( COL4 ) << "ANIMAL" << setw( COL5 ) << "BREED" << endl; cout << string( 80, '-' ) << endl; // Pet 1: cout << setw( COL1 ) << "1"; cout << setw( COL2 ) << pet1_name; cout << setw( COL3 ) << pet1_age; cout << setw( COL4 ) << pet1_animal; cout << setw( COL5 ) << pet1_breed; cout << endl; // TODO: Display information for pet 2 // Return 0 means quit program with no errors, in this context. return 0; }
This program uses the
getline
function to get names of pets and store them in string variables. Pet 1 is already taken care of, you just need to do the same thing for Pet 2.At the end of the program, Pet 1's information is displayed in a table, using the
setw
functions to set up columns. Follow the same formatting, and display all the information for Pet 2 as well.$ g++ pet.cpp $ ./a.out ---- PET 1 ---- Name: Cyrus Age: 15 Animal: Dog Breed: Maltese ---- PET 2 ---- Name: Kabe Age: 8 Animal: Cat Breed: Unknown Collected information: PET# NAME AGE ANIMAL BREED -------------------------------------------------------------------------------- 1 Cyrus 15 Dog Maltese 2 Kabe 8 Cat Unknown
graded_program
:Starter code:
// - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - STUDENT CODE -----------------------------------------------------------// const string YOURNAME = "Your Name, Spring 2024"; // TODO: Update this to your name! int StudentCode( int guest_count, int pizza_slices ) { // The variable `guest_count` has an UNKNOWN NUMBER in it. // The variable `pizza_slices` has an UNKNOWN NUMBER in it. // TODO: Create an integer variable `slices_per_person`. // TODO: Calculate how many slices of pizza each guest gets (slices divided by guests). // Assign the result to the `slices_per_person` variable. // TODO: Use `cout` to display "Total guests:", and then the value from the `guest_count` variable. // TODO: Use `cout` to display "Total slices of pizza:", and then the value from the `pizza_slices` variable. // TODO: Use `cout` to display a message of how many slices of pizza each guest gets // TODO: Use the `return` keyword to return the amount of slices (e.g., `return slices_per_person;`). return -1; // erase this line of code!! }
There's a lot of extra code in this program, but you don't have to worry about anything below the
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !! DON'T MODIFY ANYTHING BELOW THIS POINT! !! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Basically, I've added some automated testing to test out the program, but you can also test it out manually.
Within the program code, labeled
StudentCode
, we have two variables already made:int guest_count
andint pizza_slices
. (These are within the parentheses above. We'll learn more about functions later.)Beneath each
TODO
item, you'll add additional code. You'll need to do the following:- Declare an integer varaible named
slices_per_person
. - Calculate how many slices of pizza each guest gets, assign the result to the
slices_per_person
variable. (the math here ispizza_slices / guest_count
.) - Display "Total guests:" and then the
guest_count
variable. - Display "Total slices of pizza:" and then the
pizza_slices
variable. - Display "Each guest gets", then the
slices_per_person
, then "slices of pizza". - Return the
slices_per_person
variable.
In our previous programs, main() had
return 0;
at the end. For this special function, instead we're going to return the result of our math operation. It will look like this:return slices_per_person;
. This should go before the closing curly brace}
.Now you can build the program. I've added
-o PizzaParty.exe
to the end here so that the generated program is named PizzaParty.exe.$ g++ program.cpp -o PizzaParty.exe
You can run the program, but it will complain about "NOT ENOUGH ARGUMENTS!"
$ ./PizzaParty.exe argCount is 1; NOT ENOUGH ARGUMENTS! Run tests: ./PizzaParty.exe test Run as program: ./PizzaParty.exe guest_count pizza_slices
With some of the special code I added, we can add additional information when running this program. Basically, we either have to run it and provide a
guest_count
andpizza_slices
:$ ./PizzaParty.exe 20 100 Total guests: 20 Total slices of pizza: 100 Each guest gets 5 slices of pizza RESULT: 5
Or we run it with the
test
option and it will run automated tests to check your work:$ ./PizzaParty.exe test 2024-01-U03-P1-TEST; STUDENT: Your Name, Spring 2024 Total guests: 50 Total slices of pizza: 100 Each guest gets 2 slices of pizza [PASS] TEST 1, StudentCode(50, 100) = 2 Total guests: 10 Total slices of pizza: 75 Each guest gets 7 slices of pizza [PASS] TEST 2, StudentCode(10, 75) = 7
The automated tests run the PizzaParty program a couple of times, first with 50 guests and 100 slices pizza, then with 10 guests and 75 slices of pizza. It checks the results that get
return
-ed from the StudentCode function, and if the math is right, it will show those tests as[PASS]
. If the math isn't correct, it will show[FAIL]
instead.
- You can score up to 100% just by turning in the
- Turning in your work:
On your GitLab page, go into the
u03_CPPBasics
folder, and then into whichever program folder you want to update:Click on your program's .cpp file to open it, then click "Edit" and "Single file":
In your code editor on your computer, select all the text (you can use CTRL+A for select all) and copy it all (CTRL+C).
Back in the GitLab web editor, select all (CTRL+A) and then paste your changes (CTRL+V).
After you've updated all the files you want to edit,
go back to the
c03_CPPBasics
folder and copy the URL of this page.On Canvas, you will submit this URL to turn in the assignment:
ποΈ Nonogram - Nonogram B (U03.EXE.N)
How to play: Each cell in the grid of squares can either have a X (or blank) or be filled in. The filled in boxes create the pixels of an image. Each row and each column have one or more numbers. This specifies how many pixels are in that row/column. The number given is how many unbroken pixels will show up together. Two numbers separated by a space, e.g., "1 1", will have at least one empty spot between them.
Hint: Happy
Hint: Cat
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3901116
π§βπ« Status Update - Command line, C++ basics (U03.SUP)
WEEK 3 - FEB 5
Project 1
π» Project 1 (PROJ1)
----------------------------------------------------- -- R E C I P E P R O G R A M -- ----------------------------------------------------- -------------------------------------------------------------------------------- Recipe 1: Tiger Butter Candy From https://butterwithasideofbread.com/tiger-butter-fudge/ INGREDIENTS * 11 oz Vanilla chips * 0.5 cup Creamy peanut butter * 0.5 cup Semi-sweet chocolate chips -------------------------------------------------------------------------------- Recipe 2: White Chocolate Peppermint Pretzels From https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/ INGREDIENTS * 35 chips Pretzel * 12 oz White chocolate melting wafers * 0.5 cup Crushed candy canes ################################################################################ # THE END # ###########
- About
For this project, we are going to review what we've learned so far to create a basic Recipe Program.
We'll be using the following skills:
- Creating a .cpp source code file
- Using
g++
to build our .cpp code - Using
./
to run our built program - Declaring and using variables
- Using
cout
to display text and variables to the screen - Using
cin
to get input from the user - Doing basic arithmetic
We will cover the steps to do this in several parts. Just like writing real-world programs, we do so iteratively - we start basic, and continue adding features over time.
- How to be successful at projects
- Your program should always build. Don't continue writing features if you have build errors. WORKING CODE THAT IS INCOMPLETE IS BETTER THAN "COMPLETE" BUT BROKEN CODE THAT DOESN'T EVEN RUN.
- Implement one feature at a time. Test after implementing one feature. Work on small chunks at a time.
- If you get stuck, you should seek solutions, such as:
- Asking a tutor - The campus has tutors via the Academic Achievement Center.
- Asking the instructor - You can email me, you can ask me in class, you can schedule a one-on-one time to meet via Zoom or in person.
- Looking at example code from class videos and the example code repository.
- CS 200 topics quick reference
Use this as a reference while working through your program. You might copy/paste these notes elseware or print them out to keep them handy.
Terminal commands
Command What it does cd FOLDERNAME
Moves you into the FOLDERNAME. cd ..
Moves you out of the current folder. ls
View a LiSt of files and folders in the current directory. g++ FILENAME
Build a C++ file, turning source code into an executable file. Creates "a.exe" or "a.out". ./a.exe
Runs the executable file named "a.exe". C++ instructions
Instruction What it does DATATYPE VARNAME;
Declare a variable with some datatype and name. int my_int;
Declare an integer variable named my_int
.float my_float;
Declare a float variable named my_float
.string my_string;
Declare a string variable named my_string
.my_int = 10;
Assign a value of 10 to the my_int
variable.my_float = 9.99;
Assign a value of 9.99 to the my_float
variable.my_string = "Hello!";
Assign a value of "Hello!" to the my_string
variable.cout << "Hello!";
Displays "Hello!" to the screen. cout << my_string;
Displays the value of the my_string
variable to the screen.cout << endl;
Adds a new line before the next cout display. cin >> my_float;
Gets keyboard input, stores in my_float
variable.
- Setup
- Make sure your computer is setup!
Before we get started, you need the following things:
- MinGW (Windows), XCode(Mac), or g++ (Linux) installed on your computer. View the π§βπ¬ Unit 00 Lab - Set up (U00.LAB.202401CS200) assignment for a reminder on setting up your tools.
- A good code editor, such as Geany (https://www.geany.org/) - This is what I'll be using in my screenshots.
- Creating a PROJECTS folder
- Open your operating system's File Explorer.
TODO add screenshots
- Locate the folder where you are currently storing your course files (e.g., "rsingh13-cs200").
- Create a new folder named "PROJECTS".
- Creating our .cpp source code file
- Open up your code editor, such as Geany.
- In Geany's dropdown menu, select File, then New.
- This will create a new empty file for us.
- Before we get started, let's save the file. Go to File, then Save As…
- Navigate to your "PROJECTS" folder, and save this file with the name "project1.cpp".
Now we can get started on our program.
- Make sure your computer is setup!
- Gathering data for the program
For this program you will need to find two simple recipes online. I looked up "three ingredient desserts" to find some. Make sure to keep the pages open, we will need the information, as well as the URL to be able to cite our sources.
These are the recipes I used:
- https://butterwithasideofbread.com/tiger-butter-fudge/
- https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/
You can use the same recipes if you'd like, or find other ones. I would just suggest finding something with only a few ingredients.
- Recipe program version 1 - just
cout
statements
For version 1 we're only going to use
cout
statements to display all the recipe information.Start with the following empty C++ program:
#include <iostream> #include <string> using namespace std; int main() { cout << "RECIPE PROGRAM" << endl; // ADD YOUR CODE IN HERE cout << "THE END" << endl; return 0; }
The program output should look like this:
RECIPE PROGRAM -------------------------------------------------------------------------------- Recipe 1: Tiger Butter Candy From https://butterwithasideofbread.com/tiger-butter-fudge/ INGREDIENTS * 11 oz Vanilla chips * 0.5 cup Creamy peanut butter * 0.5 cup Semi-sweet chocolate chips -------------------------------------------------------------------------------- Recipe 2: White Chocolate Peppermint Pretzels From https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/ INGREDIENTS * 35 chips Pretzel * 12 oz White chocolate melting wafers * 0.5 cup Crushed candy canes THE END
Make sure that the program output is easy to read and well organized. Some tips:
- Give enough spacing between chunks of information, such as INGREDIENTS being spaced away from the URL and the "THE END".
- Use lines of dashes or other symbols to show a physical separation between regions.
- Make sure that the text itself is readable:
11 oz Vanilla chips
is good, but11ozVanilla chips
is bad.
Task: Implement version 1 of the Recipe Program. This version should only have
cout
statements to display all of the information. Check with the instructor to make sure you're on the right track if unsure.
- Building and running your program
While working through the program, you should be building your program periodically to check for syntax errors. Additionally, you should also run the program here and there to make sure the output looks correct.
To build your program, open up the terminal from within the folder where your project1.cpp file is.
Build the program:
g++ program1.cpp
Run the program:
./a.exe
(or a.out on Linux/Mac)
- Backing up your work before continuing
Backing up your work periodically is important, whether you need to step back after encountering big errors and see what changed since last time, or just making sure your work isn't lost in case of a power outage. We will back up our current version of the code on our GitLab page.
- Go to your GitLab repository and click on the "PROJECTS" folder.
- No files are here yet. Click on the "+" button, then click "Upload new file".
- Locate your project1.cpp file on your computer. You can either click-and-drag it to the dotted box, or click on the dotted box to locate the file via the file browser.
- Add a commit message like "Project 1 version 1". Then click the "Upload file" button to finish.
Now you can return to your code editor (like Geany) and start on version 2.
- Recipe program version 2 - variables
- Creating variables
For version 2 we're going to add in variables. We will need a lot of variables to store all of the recipe information! Make sure your variables are clear and descriptive so that your code is easy to read.
Here is a table of all the variables you will need. I am also including the values I used for the recipes I used, but you can change the variable values to your own recipes.
Variable name Data type My variable values RECIPE 1 recipe1_name
string "Tiger Butter Candy" recipe1_url
string "https://butterwithasideofbread.com/tiger-butter-fudge/" recipe1_ingredient1_amount
float 11 recipe1_ingredient1_name
string "Vanilla chips" recipe1_ingredient1_unit
string "oz" recipe1_ingredient2_amount
float 0.5 recipe1_ingredient2_name
string "Creamy peanut butter" recipe1_ingredient2_unit
string "cup" recipe1_ingredient3_amount
float 0.5 recipe1_ingredient3_name
string "Semi-sweet chocolate chips" recipe1_ingredient3_unit
string cup" RECIPE 2 recipe2_name
string "White Chocolate Peppermint Pretzels" recipe2_url
string "https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/" recipe2_ingredient1_amount
float 35 recipe2_ingredient1_name
string "Pretzel" recipe2_ingredient1_unit
string "chips" recipe2_ingredient2_amount
float 12 recipe2_ingredient2_name
string "White chocolate melting wafers" recipe2_ingredient2_unit
string "oz" recipe2_ingredient3_amount
float 0.5 recipe2_ingredient3_name
string "Crushed candy canes" recipe2_ingredient3_unit
string cup" Variables need to be declared before they're used in a C++ program, so I would suggest that you create the variables at the top of the program:
#include <iostream> #include <string> using namespace std; int main() { // DECLARE VARIABLES HERE cout << "RECIPE PROGRAM" << endl; // DISPLAY RECIPE INFORMATION HERE cout << "THE END" << endl; return 0; }
(Note: You're not starting from scratch with this version, the above code is just an example of where each section of the program should go.)
- Updating your
cout
statements
Now that we have variables set up, you'll need to update your
cout
statements to use these variables instead of the hard-coded information from v1.For example, in version 1, display the recipe name and url might look like this:
cout << " Recipe 1: Tiger Butter Candy" << endl << endl; cout << " From https://butterwithasideofbread.com/tiger-butter-fudge/" << endl << endl;
And the update for version 2 might look like this:
cout << " Recipe 1: " << recipe1_name << endl; cout << " From " << recipe1_url << endl << endl;
Do this for all your recipe information - name, url, ingredient amount, name, and unit.
Make sure your program still looks nice afterwards, it should still be readable and clear. The output should look the same, we haven't changed the interface yet, just how the data is stored in the program.
Make sure you're building and running the program to test as you go!
- Backing up your work before continuing
Backing up your work periodically is important, whether you need to step back after encountering big errors and see what changed since last time, or just making sure your work isn't lost in case of a power outage. We will back up our current version of the code on our GitLab page.
- Go to your GitLab repository and click on the "PROJECTS" folder.
- Our "project1.cpp" file should be here. Click on it.
- Click on the "Edit" button, then click "Edit single file".
- Copy your C++ code from your "project1.cpp" file on your computer, and paste it into this editor window on GitLab. At the bottom of this page, add a commit message like "Project 1 version 2". Then click the "Commit changes" button to finish.
Now you can return to your code editor (like Geany) and start on version 3.
- Creating variables
- Recipe program version 3 - arithmetic
For this final version we are going to ask the user how many batches they'd like to make. The user can enter something like 1 for a normal batch, 0.5 for half batch, 2 for double batch, and so on.
We will do this at the start of the program so that, once the recipes are displayed, we can update the ingredient amounts to show an updated value.
#include <iostream> #include <string> using namespace std; int main() { // CREATE A batches VARIABLE // ASK THE USER HOW MANY BATCHES THEY WANT TO MAKE // GET THEIR INPUT AND STORE IT IN THE batches VARIABLE // DECLARE VARIABLES HERE cout << "RECIPE PROGRAM" << endl; // DISPLAY RECIPE INFORMATION HERE // MULTIPLY EACH INGREDIENT AMOUNT BY THE batches VARIABLE cout << "THE END" << endl; return 0; }
- How many batches?
At the top of the program, we'll want to do the following:
- Declare a new float variable. Its name should be
batches
. - Display a message to the user using the
cout
command. Ask: How many batches to make? - Get input from the keyboard using the
cin >>
command. Store the user's answer in thebatches
variable.
- Declare a new float variable. Its name should be
- Updating ingredient amounts
Further down in the program where you're displaying all the ingredient's information, you'll need to update your amounts shown to now be multiplied by the
batches
variable.For example, in version 2, an ingredient display might have looked like:
cout << recipe1_ingredient1_amount << " " << recipe1_ingredient1_unit << " of " << recipe1_ingredient1_name << endl;
And the update for version 3 might look like this:
cout << recipe1_ingredient1_amount * batches << " " << recipe1_ingredient1_unit << " of " << recipe1_ingredient1_name << endl;
Do this for all the ingredient amounts.
- Program output
Once implemented, your program should look something like this:
How many batches would you like to make? 2 ----------------------------------------------------- -- R E C I P E P R O G R A M -- ----------------------------------------------------- -------------------------------------------------------------------------------- Recipe 1: Tiger Butter Candy From https://butterwithasideofbread.com/tiger-butter-fudge/ INGREDIENTS * 22 oz Vanilla chips * 1 cup Creamy peanut butter * 1 cup Semi-sweet chocolate chips -------------------------------------------------------------------------------- Recipe 2: White Chocolate Peppermint Pretzels From https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/ INGREDIENTS * 70 chips Pretzel * 24 oz White chocolate melting wafers * 1 cup Crushed candy canes ################################################################################ # THE END # ###########
It doesn't have to match exactly and you can customize the style as you'd like, as long as it remains readable.
- Backing up your work before continuing
Once again, back up your work to GitLab:
- Go to your GitLab repository and click on the "PROJECTS" folder.
- Click on your "project1.cpp" file.
- Click on the "Edit" button, then click "Edit single file".
- Copy and paste your code from "project1.cpp" on your computer into the editor on GitLab.
- Add a "commit message" like "Project 1 FINAL VERSION".
- Click "Commit changes" to finish.
We're not done with GitLab yet, let's look around before finishing up the assignment.
- How many batches?
- Exploring your file's history
- From your file's page on GitLab, click on the "History" button.
- This shows a list of all the changes you've made to this file, including those commit messages that describe what was updated.
- Click on your "Project 1 version 2" update. You'll see lines of code marked in green (for added) or red (for removed). This can be useful to see what all changed since your last updates.
- Turning in the assignment
- On the GitLab webpage go to your "project1.cpp" file. Copy the URL of this file.
- On Canvas, locate the "π» Project 1 (PROJ1.202401CS200)" assignment. Click on "Start Assignment".
- Paste the URL to your "project1.cpp" file on GitLab and click "Submit Assignment" to complete the assignment.
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3907325
WEEK 4 - FEB 12
UNIT 04: Control flow - Branching and looping
π Presentation - Control flow (U04.PRES)
ποΈ Reading - Control flow (U04.READ)
- Boolean expressions
In order to start writing questions that a computer can understand, we need to understand boolean expressions.
A math expression looks like this:
\[ 2 + 3 \]
A boolean expression is a statement that result in either true or false:
"it is daytime."
"the user saved the document"
"the user's age greater than 12 and less than 20"
if ( i_have_not_been_fed && it_is_6_am ) { MakeLotsOfNoise(); }
Logic in computer programs are based around these types of questions: something that can only be true or false. Statements include:
Is [boolean variable] true?
x
Is [boolean variable] false?
!x
Are two variables equal?
x == y
Are two variables not equal?
x != y
Is x less than y?
x < y
Is x less than or equal to y?
x <= y
Is x greater than y?
x > y
Is x greater than or equal to y?
x >= y
For the first two, we can check the value of a boolean variable. The rest of them, we can use any data type to compare if two values are equal, greater than, less than, etc.
a
andb
can be replaced with variables and/or values…if ( age < 18 ) { ... } if ( my_state == your_state ) { ... } if ( word1 < word2 ) { ... } if ( document_saved == true ) { ... } if ( document_saved == false ) { ... }
Note: When using \(<\) and \(>\) with strings or chars, it will compare them based on alphabetical order - if they're both the same case (both uppercase or both lowercase).
- And, Or, and Not operators
We can also combine boolean expressions together to ask more sophisticated questions.
- Not operator:
!
If we're checking a boolean variable, or a boolean expression, and we happen to want to execute some code for when that result is false, we can use the not operator…
Using with boolean variable *documentSaved:*
// Just checking documentSaved = true if ( documentSaved ) { Quit(); } // Checking if documentSaved = false with the not operator if ( !documentSaved ) { Save(); Quit(); }
Using with boolean expressions *( age >= 21 ):*
// If the age is not 21 or over... if ( !( age >= 21 ) ) { NoBeer(); }
- And operator:
&&
When using the and operator, we can check to see if all boolean variables/expressions are true. The full question of "is this and this and this true?" only results to true if all boolean variables/expressions are true. If even one of them are false, then the entire statement is false.
if ( wantsBeer && isAtLeast21 ) { GiveBeer(); }
To break it down, the customer would only get beer if they want beer AND if they are over 21. If they don't want beer but are 21 or over, they don't get beer. If they want beer but are under 21, then they don't get beer.
- Or operator:
||
For an or operator, we can check to see if at least one boolean variable/expression is true. If at least one item is true, then the whole statement is true. The only way for it to be false is when each boolean variable/expression is false.
if ( isBaby || isSenior || isVet ) { GiveDiscount(); }
In this case, discounts are given to babies, seniors, and vets. A customer wouldn't have to be all three to qualify (and clearly, couldn't be all three at the same time!). If the customer is not a baby and not a senior and not a vet, then they don't get the discount - all three criteria have to be false for the entire expression to be false.
- Not operator:
- Truth tables
We can use truth tables to help us visualize the logic that we're working with, and to validate if our assumptions are true. Truth tables are for when we have an expression with more than one variable (usually) and want to see the result of using ANDs, ORs, and NOTs to combine them.
- Truth table for NOT:
On the top-left of the truth table we will have the boolean variables or expressions written out, and we will write down all its possible states. With just one variable \(p\), we will only have two states: when it's true, or when it's false.
On the right-hand side (I put after the double lines) will be the result of the expression - in this case, "not-p" \(!p\). The not operation simply takes the value and flips it to the opposite: true \(\to\) false, and false \(\to\) true.
p
!p
T F F T
- Truth table for AND:
For a truth table that deals with two variables, \(p\) and \(q\), the total amount of states will be 4:
- \(p\) is true and \(q\) is true.
- \(p\) is true and \(q\) is false.
- \(p\) is false and \(q\) is true.
- \(p\) is false and \(q\) is false.
p
q
p && q
T T T T F F F T F F F F This is just a generic truth table. We can replace the values with boolean expressions in C++ to check our logic.
For example, we will only quit the program if the game is saved and the user wants to quit:
game_saved
want_to_quit
game_saved && want_to_quit
T T T T F F F T F F F F The states are:
gameSaved
is true andwantToQuit
is true: Quit the game. βgameSaved
is true andwantToQuit
is false: The user doesn't want to quit; don't quit. βgameSaved
is false andwantToQuit
is true: The user wants to quit but we haven't saved yet; don't quit. βgameSaved
is false andwantToQuit
is false: The user doesn't want to quit and the game hasn't been saved; don't quit. β
- Truth table for OR:
Generic form:
p
q
p β q
T T T T F T F T T F F F Again, if at least one of the expressions is true, then the entire expression is true.
Example: If the store has cakes OR ice cream, then suggest it to the user that wants dessert.
hasCake
hasIcecream
hasCake
βhasIceCream
T T T T F T F T T F F F The states are:
hasCake
is true andhasIcecream
is true: The store has desserts; suggest it to the user. βhasCake
is true andhasIcecream
is false: The store has cake but no ice cream; suggest it to the user. βhasCake
is false andhasIcecream
is true: The store has no cake but it has ice cream; suggest it to the user. βhasCake
is false andhasIcecream
is false: The store doesn't have cake and it doesn't have ice cream; don't suggest it to the user. β
- Truth table for NOT:
- DeMorgan's Laws
Finally, we need to cover DeMorgan's Laws, which tell us what the opposite of an expression means.
For example, if we ask the program "is a \(>\) 20?" and the result is false, then what does this imply? If \(a > 20\) is false, then \(a \leq 20\) is true… notice that the opposite of "greater than" is "less than OR equal to"!
- Opposite of
a && b
a
b
a && b
!( a && b )
!a β !b
T T T F F T F F T T F T F T T F F F T T If we're asking "is \(a\) true and is \(b\) true?" together, and the result is false, that means either:
- \(a\) is false and \(b\) is true, or
- \(a\) is true and \(b\) is false, or
- \(a\) is false and \(b\) is false.
These are the states where the result of
a && b
is false in the truth table.In other words,
!( a && b )
\(\equiv\)!a β !b
If \(a\) is false, or \(b\) is false, or both are false, then the result of
a && b
is false.
- Opposite of
a β b
:
a
b
a β b
!( a β b )
!a && !b
T T T F F T F T F F F T T F F F F F T T If we're asking "is \(a\) true or \(b\) true?", if the result of that is false that means only one thing:
- Both \(a\) and \(b\) were false.
This is the only state where the result of
a || b
is false.In other words,
!( a β b )
\(\equiv\)!a && !b
a β b
is false only if \(a\) is false AND \(b\) is false.
- Opposite of
- Summary
In order to be able to write if statements or while loops, you need to understand how these boolean expressions work. If you're not familiar with these concepts, they can lead to you writing logic errors in your programs, leading to behavior that you didn't want.
- Branching
Branching is one of the core forms of controlling the flow of the program. We ask a question, and based on the result we perhaps do this code over here or maybe that code over there - the program results change based on variables and data accessible to it.
We will mostly be using if / else if / else statements, though switch statements have their own use as well. Make sure to get a good understanding of how each type of branching mechanism "flows".
- If statements
If statements (usually the general term encompassing if / else if / else as well) are a way we can ask a question and respond: If \(a\) is less than \(b\) then… or if \(a\) is greater than \(c\) then… Otherwise do this default thing…
Let's look at some examples while ironing out how it works.
- If statements
For a basic if statement, we use the syntax:
// Do things 1 if ( CONDITION ) { // Do things 1-a } // Do things 2
The CONDITION will be some boolean expression. If the boolean expression result is true, then any code within this if statement's code block (what's between \* and \*) will get executed. If the result of the expression is false, then the entire if statement's code block is skipped and the program continues.
Example:
cout << "Bank balance: " << balance; if ( balance < 0 ) { cout << " (OVERDRAWN!)"; } cout << " in account #" << accountNumber << endl;
Output with
balance = -50
Bank balance: -50 (OVERDRAWN!) in account #1234
Output with
balance = 100
Bank balance: 100 in account #1234
- The special message "OVERDRAWN!" only gets displayed when the balance is less than 0.
- The following
cout
that gives the account number is displayed in all cases.
- If statements
- If/Else statements
In some cases, we will have code that we want to execute for the false result as well. For an if/else statement, either the if code block will be entered, or the else code block will be.
NOTE: The else statement NEVER has a CONDITION.
// Do things 1 if ( CONDITION ) { // Do things 1-a } else { // Do things 1-b } // Do things 2
The else block is executed when the if check fails. If the CONDITION is false, we can use DeMorgan's Laws to figure out what the program's state is during the else.
Example:
cout << "Enter your age: "; cin >> age; if ( age < 18 ) { result = "can't vote"; } else { result = "can vote"; } cout << "Result: " << result << endl;
If the
age
is less than 18, it will set theresult
variable to "can't vote". If that boolean expression is false, that meansage
is \(\geq\) 18, and then it will set theresult
to "can vote". Finally, either way, it will display "Result: " with the value of theresult
variable.
- If/Else if/Else statements
In some cases, there will be multiple scenarios we want to search for, each with their own logic. We can add as many else if statements as we want - there must be a starting if statement, and each else if statement will have a condition as well.
We can also end with a final else statement as a catch-all: if none of the previous if / else if statements are true, then else gets executed instead. However, the else is not required.
// Do things 1 if ( CONDITION1 ) { // Do things 1-a } else if ( CONDITION2 ) { // Do things 1-b } else if ( CONDITION3 ) { // Do things 1-c } else { // Do things 1-d } // Do things 2
Example:
cout << "Enter grade: "; cin >> grade; if ( grade >= 90 ) { letterGrade = 'A'; } else if ( grade >= 80 ) { letterGrade = 'B'; } else if ( grade >= 70 ) { letterGrade = 'C'; } else if ( grade >= 60 ) { letterGrade = 'D'; } else { letterGrade = 'F'; } cout << "Grade: " << letterGrade << endl;
With this example, I'm first checking if the grade is 90 or above. If it is, then I know the letter grade is
'A'
.However, if it's false, it will go on and check the next else if statement. At this point, I know that since
grade >
90= was FALSE, that meansgrade < 90
. Since the next statement checks ifgrade >
80=, if this one is true I know thatgrade < 90 AND grade >
80=.
- If statements
- While loops
While loops look a lot like if statements…
while ( CONDITION ) { // Do stuff repeatedly }
except that they will continue looping while their condition is true. Once the condition results in false, then the loop will stop and the program will continue after the while loop's code block.
Warning!: Because a while loop will keep going until the condition is false, it is possible to write a program where the condition never becomes false, resulting in an infinite loop!
The while loop's condition is another boolean expression - a statement that will be true or false.
- Example: Counting up
The following while loop will increase a variable by 1 each time and display it to the screen.
int num = 1; while ( num < 10 ) { cout << num << "\t"; num++; // add 1 to num }
Output:
1 2 3 4 5 6 7 8 9
- Example: Validating user input
Sometimes you want to make sure what the user entered is valid before continuing on. If you just used an if statement, it would only check the user's input once, allowing them to enter something invalid the second time. Use a while loop to make sure that the program doesn't move on until it has valid data.
cout << "Enter a number between 1 and 10: "; cin >> num; while ( num < 1 || num > 10 ) // out of bounds! { cout << "Invalid number! Try again: "; cin >> num; } cout << "Thank you" << endl;
Output:
Enter a number between 1 and 10: 100 Invalid number! Try again: -400 Invalid number! Try again: -5 Invalid number! Try again: 5 Thank you
- Example: Program loop
In some cases, you'll have a main menu and want to return the user back to that menu after each operation until they choose to quit. You could implement this with a basic boolean variable:
bool done = false; while ( !done ) { cout << "Option: "; cin >> option; if ( option == "QUIT" ) { done = true; } } cout << "Bye" << endl;
- Do… while loops
A do…while loop is just like a while loop, except the condition goes at the end of the code block, and the code within the code block is always executed at least one time.
do { // Do this at least once } while ( CONDITION );
For example, you might want to always get user input, but if they enter something invalid you'll repeat that step until they enter something valid.
do { cout << "Enter a choice: "; cin >> choice; } while ( choice > 0 );
- Special commands
- continue
Sometimes you might want to stop the current iteration of the loop, but you don't want to leave the entire loop. In this case, you can use
continue;
to skip the rest of the current iteration and move on to the next.int counter = 10; while ( counter > 0 ) { counter--; if ( counter % 2 == 0 ) // is an even number? { continue; // skip the rest } cout << counter << " odd number" << endl; }
Output:
9 odd number 7 odd number 5 odd number 3 odd number 1 odd number
- break
In other cases, maybe you want to leave a loop before its condition has become false. You can use a
break;
statement to force a loop to quit.while ( true ) // Infinite loop :o { cout << "Enter QUIT to quit: "; cin >> userInput; if ( userInput == "QUIT" ) { break; // stop looping } }
- continue
- Switch statements
Switch statements are a special type of branching mechanism that only checks if the value of a variable is equal to one of several values. Switch statements can be useful when implementing a menu in a program, or something else where you only have a few, finite, discrete options.
In C++, switch statements only work with primitive data types, like integers and chars - not strings.
switch ( VARIABLE ) { case VALUE1: // Do thing break; case VALUE2: // Do thing break; default: // Default code }
With a switch statement, each case is one equivalence expression. The
default
case is executed if none of the previous cases are.case VALUE1: // is equivalent to... if ( VARIABLE == VALUE1 ) {
case VALUE2: // is equivalent to... if ( VARIABLE == VALUE2 ) {
default: // is equivalent to... else {
The default case is not required, just like how the else clause is not required in an if statement.
The
break;
statementThe end of each case should have a
break;
statement at the end. If thebreak
is not there, then it will continue executing each subsequent case's code until it does hit a break.This behavior is "flow-through", and it can be used as a feature if it matches the logic you want to write.
Example: Perhaps you are implementing a calculator, and want to get an option from the user: (A)dd, (S)ubtract, (M)ultiply, or (D)ivide. You could store their choice in a
char
variable calledoperation
and then use theswitch
statement to decide what kind of computation to do:switch ( operation ) { case 'A': // if ( opreation == 'A' ) result = num1 + num2; break; case 'S': // else if ( operation == 'S' ) result = num1 - num2; break; case 'M': // else if ( operation == 'M' ) result = num1 * num2; break; case 'D': // else if ( operation == 'D' ) result = num1 / num2; break; } cout << "Result: " << result << endl;
Note: If you're declaring a variable within a case statement, you need to enclose your case with curly braces
{ }
, otherwise you'll get compiler errors:switch ( operation ) { case 'A': { float result = num1 + num2; cout << "Result: " << result << endl; } break; }
- Review questions:
- A boolean expression can be…
- What do each of these expressions represent?
b
!b
a =
b=a > b
a = b
- What are each of the following operators?
&&
||
!
- When does the expression
a && b
evaluate totrue
?false
? - When does the expression when
a || b
evaluate totrue
?false
? - An if statement's code block will be executed when the if statement's condition evaluates to…
- A while loop's code block will continue executing while the while loop's condition evaluates to…
π Concept Intro - Control flow (U04.CIN)
π§βπ¬ Lab - Control flow (U04.LAB)
What we're gonna do:
- Practice with if statements
- Practice with switch statements
- Practice with for loops
Using the command line:
Navigate to your folder using the cd
(change directory) command:
$ cd FOLDERNAME
View what files are in the current folder using the ls
(list) command:
$ ls graded_program_1 practice2_ifelse practice5_switch graded_program_2 practice3_ifelseif practice6_while_program practice1_if practice4_operators
Build your source code using the g++
compiler:
g++ SOURCE.cpp
Run your program using ./
(Linux/Mac) or .\
(Windows):
- Windows:
.\a.exe
- Linux/Mac:
./a.out
practice1_if
: If statement
// PROGRAM: Practice if statements // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types #include <iomanip> // Library for formatting; `setprecision` using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { cout << fixed << setprecision( 2 ); // Format floats like USD // TODO: Create three float variables: `balance`, `withdraw`, and `remaining`. // TODO: Use `cout` to prompt the user to enter information and `cin` to get information from the keyboard. // Get user's input for `balance` (their current bank balance) and `withdraw` (how much to withdraw from bank). // TODO: Calculate the `remaining` balance after the withdraw with `remaining = balance - withdraw;` // TODO: Display "Remaining balance: $" and the `remaining` variable. // TODO: If `remaining` is less than 0, then also display "(OVERDRAWN)". // Return 0 means quit program with no errors, in this context. return 0; }
Program inputs: initial balance, withdraw amount
Variable | Description |
---|---|
withdraw |
How much money the user wishes to withdraw from their account |
balance |
How much money is currently in their bank account |
Program outputs: remaining balance
Scenario | Output | Criteria |
---|---|---|
1. | Balance: $-160 (OVERDRAWN) |
Updated balance is less than 0 |
2. | Balance: $20 |
Updated balance is 0 or greater |
Program logic:
- Create three float variables for the following:
- Initial balance (
balance
) - Withdraw amount (
withdraw
) - Remaining balance (
remaining
)
- Initial balance (
- Ask the user to enter their initial balance and the withdraw amount. Store their responses in your created variables.
- Calculate the remaining balance, which will be
balance - withdraw
. Store the result in your remaining balance variableremaining
. - Display the remaining balance to the screen.
- If the remaining balance is less than 0, then also display "OVERDRAWN".
Example output:
Withdrawing $200 from a $40 balance:
Enter your current balance: $40 Enter how much to withdraw: $200 Remaining balance: $-160.00 (OVERDRAWN)
Withdrawing $80 from a $100 balance:
Enter your current balance: $100 Enter how much to withdraw: $80 Remaining balance: $20.00
practice2_ifelse
: If/else statement
// PROGRAM: Practice if/else statements // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // TODO: Create an integer `number` variable. Ask the user to enter a value for the number. // TODO: If number is greater than 0, then display "Positive number". Otherwise, display "Negative or zero". // Return 0 means quit program with no errors, in this context. return 0; }
Program inputs:
Variable | Description |
---|---|
number |
Some integer value |
Program outputs:
Scenario | Output | Criteria |
---|---|---|
1. | positive |
The number passed in is greater than 0 |
2. | zero or negative |
The number passed in is 0 or below |
Program logic:
Given the number
passed into the program, use an if/else statement to determine
whether it is either (A) POSITIVE or (B) ZERO OR NEGATIVE. Return either "positive"
or "zero or negative"
.
Tips:
- You don't need an "else if" statement here; the
else
executes if theif
statement is false… The opposite of \(x > y\) is \(x \leq y\).
Example output:
Passing in a 6:
Enter a number: 6 Positive number
Passing in a 0:
Enter a number: 0 Negative or zero
Passing in a -5:
Enter a number: -5 Negative or zero
practice3_ifelseif
: If/else if/else statement
// PROGRAM: Practice if/else if statements // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // TODO: Create an int variable named `charge`. // TODO: Use `cout` to tell the user to enter their battery charge %. // TODO: Use `cin` to get their input and store it in the `charge` variable. // TODO: Use if/else if/else statements to decide which battery image to draw. // 90% and above: [****]; 75% and above: [***-]; 50% and above: [**--]; 25% and above: [*---]; below 25%: [----] // Return 0 means quit program with no errors, in this context. return 0; }
Program inputs:
Variable | Description |
---|---|
charge |
What % charge someone's phone has |
Program outputs:
Scenario | Output | Criteria |
---|---|---|
1. | Battery drawing | A "drawing" of the battery based on the % charge |
Program logic:
DESCRIPTION
- Create a variable to store the user's battery
charge
. - Ask the user to enter how much charge their phone battery has,
and store their response in the
charge
variable. - Use if and else if statements to decide which image to draw.
Charge % | Drawing |
---|---|
90% and above | [****] |
75% and above | [***-] |
50% and above | [**--] |
25% and above | [*---] |
Below 25% | [----] |
Tips:
- You can use an "else" statement for the last case - if none of the if or else if statements are triggered, then else will catch any other results.
Example output:
Half battery:
Enter the battery charge: %50 Image: [**__]
Full battery:
Enter the battery charge: %95 Image: [****]
practice4_operators
: Logic operators AND and OR
// PROGRAM: Practice using logic operators // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // TODO: Create two boolean variables, `has_paper` and `printer_on`. // TODO: Display the message "Is the printer on? (0) off, (1) on: "; // TODO: Use `cin` to get keyboard input and store it in `printer_on`. // TODO: Display the message "Does the printer have paper? (0) no paper, (1) has paper: "; // TODO: Use `cin` to get keyboard input and store it in `has_paper`. // TODO: If has_paper is true and printer_on is true then display "CAN PRINT!" // Otherwise, display "CANNOT PRINT!". // Return 0 means quit program with no errors, in this context. return 0; }
Program inputs:
Variable | Description |
---|---|
has_paper |
Whether the printer has paper |
printer_on |
Whether the printer is on |
Program outputs:
Scenario | Output | Criteria |
---|---|---|
1. | Can print? | Only displays "can print" if printer is on and has paper. Otherwise, displays "cannot print". |
Program logic:
- Create variables for
has_paper
andprinter_on
, these should be boolean variables. - Ask the user to answer yes (1) or no (0) for each of the variables ("Is the printer on?", "Does it have paper?")
- Use an if statement with the AND operator (
&&
) with the condition: If the printer is on AND it has paper… Then display "CAN PRINT!" - Use an else statement in response… When the above isn't true, then display "CANNOT PRINT!"
Tips:
- The logical opposite of
a && b
is!a || !b
Example output:
No power, no paper:
Is the printer on? (0) off, (1) on: 0 Does the printer have paper? (0) no paper, (1) has paper: 0 CANNOT PRINT!
Yes power, yes paper:
Is the printer on? (0) off, (1) on: 1 Does the printer have paper? (0) no paper, (1) has paper: 1 CAN PRINT!
No power, yes paper:
Is the printer on? (0) off, (1) on: 0 Does the printer have paper? (0) no paper, (1) has paper: 1 CANNOT PRINT!
Yes power, no paper:
Is the printer on? (0) off, (1) on: 1 Does the printer have paper? (0) no paper, (1) has paper: 0 CANNOT PRINT!
practice5_switch
: Switch statement
// PROGRAM: Practice using switch statements // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { // TODO: Create two string variables, `english` and `translated`. Initialize `english` to "cat". // TODO: Create a character variable named `language`. Ask the user to enter a language letter, // and store their response in this variable. // TODO: Use a switch statement to look at the `language` chosen. // In case of 'e', set `translated` to "kato". // In case of 's', set `translated` to "gato". // In case of 'm', set `translated` to "mao". // In case of 'h', set `translated` to "billee". // For the default case, set `translated` to "?" // TODO: Display the `english` word and then `translated` word.` // Return 0 means quit program with no errors, in this context. return 0; }
Program inputs:
Variable | Description |
---|---|
language |
Which language to translate the word to |
Program outputs:
Scenario | Output | Criteria |
---|---|---|
1. | Translated word | "kato", "gato", "mao", "billee", or "?" |
Program logic:
- Create two string variables,
english
andtranslated
. Initializeenglish
to "cat". - Create a char variable called
language
. Ask the user to enter a language letter and store their response in this variable. - Use a switch statement to look at the
language
char. Based on its value, settranslated
to one of the values below. - After the switch statement, display the
english
word and thetranslated
word to the screen.
Letter | Language | Translation |
---|---|---|
'e' | Esepranto | "kato" |
's' | Spanish | "gato" |
'm' | Mandarin Chinese | "mao" |
'h' | Hindi | "billee" |
Others | "??" |
Tips:
- Unfortunately we can't use accented characters directly in our program, it may work on certain systems automatically (Linux, Mac?) but not everything (Windows). Usually, we need to include special libraires to work with extended letter sets.
Example output:
Esperanto translation:
(e)speranto, (s)panish, (m)andarin, (h)indi Enter a language letter: e cat = kato
Hindi translation:
(e)speranto, (s)panish, (m)andarin, (h)indi Enter a language letter: h cat = billee
Practice: While loop - program loop
// PROGRAM: Practice creating a program loop with while // - INCLUDES ---------------------------------------------------------------// #include <iostream> // Library that contains `cout` commands #include <string> // Library that contains `string` types using namespace std; // Using the C++ STanDard libraries // - PROGRAM CODE -----------------------------------------------------------// int main() { bool running = true; int choice; while ( running ) // Keep program running until `running` is false. { // Display MENU cout << "-- MAIN MENU --" << endl; cout << "1. Display my favorite book" << endl; cout << "2. Display my favorite movie" << endl; cout << "3. Display my favorite game" << endl; cout << "4. Exit program" << endl << endl; // GET USER SELECTION cout << "SELECTION: "; cin >> choice; cout << "You chose " << choice << endl; // PERFORM OPERATION // TODO: Use a switch statement or an if statement here. // Option 1: Display your favorite book. // Option 2: Display your favorite movie. // Option 3: Display your favorite game. // Option 4: Set `running` to false, which will cause the program to quit. // Any other inputs: Display "unknown command!" cout << endl; } cout << endl << "GOODBYE" << endl; // Return 0 means quit program with no errors, in this context. return 0; }
Description:
This program continues running while the running
variable is set to true
.
This allows the user to select multiple options without having to re-run the program.
The program contains a main menu of commands they can select from, and will do something different for each command.
Program logic:
Use if/else if statements or a switch statement to investigate the value of the choice
variable.
Do different operations based on what its value is…
choice value | output |
---|---|
1 | Display your favorite book |
2 | Display your favorite movie |
3 | Display your favorite game |
4 | Set running to false |
others | Display "Unknown command!" |
Example output:
-- MAIN MENU -- 1. Display my favorite book 2. Display my favorite movie 3. Display my favorite game 4. Exit program SELECTION: 1 You chose 1 Masters of Doom -- MAIN MENU -- 1. Display my favorite book 2. Display my favorite movie 3. Display my favorite game 4. Exit program SELECTION: 2 You chose 2 The Lost Skeleton of Cadavra -- MAIN MENU -- 1. Display my favorite book 2. Display my favorite movie 3. Display my favorite game 4. Exit program SELECTION: 3 You chose 3 Divinity Original Sin 2 -- MAIN MENU -- 1. Display my favorite book 2. Display my favorite movie 3. Display my favorite game 4. Exit program SELECTION: 4 You chose 4 GOODBYE
Graded Program 1: Grade
char StudentCode( float points_possible, float my_score ) { char letter_grade = 'F'; // TODO: Create a float for `grade_percent`. Calculate the percent with `my_score` divided by `points_possible` times 100. // TODO: Use if/else if/else statements to determine value for `letter_grade` based on the `grade_percent`; // 89.5 and above = A, 79.5 and above = B, 69.5 and above = C, 59.5 and above = D, below that is F. // TODO: Display grade information, including `my_score`, `points_possible`, `grade_percent`, and `letter_grade`. // TODO: Return the `letter_grade` as the result. return letter_grade; }
Program inputs:
Variable | Description |
---|---|
points_possible |
The amount of points an assignment is worth |
my_score |
The amount of points the user earned on the assignment |
Program outputs:
Scenario | Output | Criteria |
---|---|---|
1. | Corresponding letter grade | 'A', 'B', 'C', 'D', or 'F' |
Program logic:
- Create a float to store the
grade_percent
. The calculation is \[g = \frac{s}{p} \cdot 100\], where \(g\) is the grade percent, \(s\) is the user's score, and \(p\) is points possible. - Use if/else if statements to determine the letter grade. Use the table below for the data.
- Display the grade information, such as
my_score
,points_possible
,grade_percent
, and the letter grade. - At the end, make sure you have
return letter_grade;
to return the result.
Automated tests:
When you run the program it will ask if you want to run the AUTOMATED TESTS or the PROGRAM. You can run the automated tests to check your work, and run the program to manually check your work.
Example output:
Program output:
1. Run AUTOMATED TESTS 2. Run PROGRAM >> 2 Enter points possible: 80 Enter your score: 75 GRADE INFORMATION My score ......... 75.00 Points possible ...80.00 Grade % ...........93.75 Letter grade ......A RESULT: A
Graded Program 2: Raise
int StudentCode( float starting_salary, float raise_per_year, int years ) { float updated_salary = starting_salary; cout << "Starting salary: $" << starting_salary << endl; int current_year = 1; // TODO: Use a loop, you need to create a counter variable that goes from 1 to `years`. // Within the loop, calculate the updated salary with // `updated_salary = updated_salary + ( updated_salary * raise_per_year );` // Use `cout` to display the year (counter) and the `updated_salary` each iteration. // Make sure to add 1 to current_year each iteration through the loop. // TODO: Return the `updated_salary` as the result. return updated_salary; }
Program inputs:
Variable | Description |
---|---|
starting_salary |
The salary the user currently has |
raise_per_year |
The raise they get per year (as a decimal amount… percent/100) |
years |
The amount of years to calculate their updated salary |
Program outputs:
Scenario | Output | Criteria |
---|---|---|
1. | updated_salary |
The salary after years years' worth of raise_per_year . |
Program logic:
- Create a while loop. The condition is: Continue looping while the
current_year
is less than or equal toyears
. Within the loop do the following:- Calculate the year's adjusted salary:
\[u = u + ( u \cdot r )\]
Where \(u\) is the updated salary and \(r\) is the raise per year.
Each update we want to overwrite the
updated_salary
to match the current year's updates. - Display the
current_year
andupdated_salary
. - Increment
current_year
by 1 before the end of the while loop.
- Calculate the year's adjusted salary:
\[u = u + ( u \cdot r )\]
Where \(u\) is the updated salary and \(r\) is the raise per year.
Each update we want to overwrite the
- After the loop is over, make sure
return updated_salary;
is returned.
Tips:
- "Increment VARIABLENAME" means to add 1 to the variable, and replace the variable's value with that update.
- Short way:
a++;
will add 1 toa
- Long way:
a = a + 1;
will do the same thing.
- Short way:
Use the automated tests to validate your work, and run the program manually to test further.
Example output:
1. Run AUTOMATED TESTS 2. Run PROGRAM >> 2 Enter starting salary: 30000 Raise per year: %3 Enter how many years to project: 5 Starting salary: $30000.00 Year: 1, Salary: $30900.00 Year: 2, Salary: $31827.00 Year: 3, Salary: $32781.81 Year: 4, Salary: $33765.26 Year: 5, Salary: $34778.22 RESULT: $34778.00
- Turning in your work
- Go to your GitLab webpage.
- Select the folder for this unit in the main view. Locate the file you want to update and click on it.
Click on the blue "Edit" button, then click "Edit single file".
- COPY your work off your computer and PASTE it into the web editor on GitLab. Scroll to the bottom of the page and click "Commit changes" to finish up.
Go back to the unit folder and COPY the URL for this unit.
- On Canvas, locate the assignment. Click "Start assignment".
Paste the copied URL into the box and click "Submit assignment".
π§ Tech Literacy - Filesystems (U04.TEC)
- Before computers
Figure 14: Photo by Mike: https://www.pexels.com/photo/depth-of-field-photography-of-file-arrangement-1181772/
Before computers were widely available to businesses and at home, long-term storage of information was often stored in physical folders organized by some method (alphabetical, purpose, etc.).
Within each folder there would be files, such as contracts, filled out forms, and so on. Anything we do on a computer now had to be done on paper before.
While working on a file, people would work at their desk - on their desktop. That's where work in progress items would go.
If you haven't noticed the similarity yet, a lot of computer terminology about navigating our computers come from these office environments. When computers were first created, there was a lot of things named based on real-world items, as a way to give an "analogy" for what the software did.
- Files and folders
- Files
On our computers we we files where we store data. This can be any type of data - text, images, video, music files, code files, and so on.
Each file at least has a name and a size associated with it, and usually files are given different extensions to help the Operating System understand what kind of file it is.
File extension File type .mp3 Music file .csv Comma-separated value table .jpg JPEG image file (good for photos) .png PNG image file (good for low color images) .html HTML document (opened by web browsers) Files have contents - the data it is storing within. For a plain text file, it'd just be text information:
For an image file, its contents is data about the image itself - what color is at each position.
Some file types are technically plaintext, but the way their contents are written signify different things. An HTML webpage can be opened in a text editor:
And a C++ program's code can be opened in a text editor:
These are both plaintext files, but we put ".html" at the end to specify a basic HTML webpage, or ".cpp" at the end to specify that this file is C++ source code.
When you double-click a file to open it, the Operating System may look at the file extension (.html, .cpp, .mp3, etc.) to figure out which program to open it with: A music player won't do much good with a .html file, and an image viewer won't know how to read a .mp3 file.
- Folders
A folder represents a location on your hard drive. A folder can contain files adn other folders as well. The folders within a folder are called subfolders.
All together, all the folders on your computer make up a tree structure…
Diagram of an example filesystem:
A screenshot of several folders opened up on my computer:
Folders are also known as directories, so when we talk about what directory we're working in, that means what folder are we currently working in.
- Files
- The directory tree
- Paths to documents
As we traverse deeper into our filesystem tree, we grow and grow our path. The path is the string that shows the sequence of folders to follow to get to where we're currently at. The path is similar to a URL to get to a website. Both use slashes like "/" to separate between "folders".
On a Windows computer, we might access our documents with a path like this:
C:\Users\USERNAME\Documents\
Or on Linux and Mac, it might look like this:
/home/USERNAME/Documents/
We can type in the path to the folder want to get to in the "address bar" in our file explorer, or we can double-click on folders to get into each one and go folder by folder.
It can sometimes be useful to highlight and copy a folder path so that we can easily point projects to a new directory or for other reasons.
- Paths to documents
- Discussion board
Find the "π§ Tech Literacy - Filesystems" assignment on Canvas and participate in the discussion board!
ποΈ Nonogram - Nonogram C (U04.EXE.N)
How to play: Each cell in the grid of squares can either have a X (or blank) or be filled in. The filled in boxes create the pixels of an image. Each row and each column have one or more numbers. This specifies how many pixels are in that row/column. The number given is how many unbroken pixels will show up together. Two numbers separated by a space, e.g., "1 1", will have at least one empty spot between them.
Hint: Love
Hint: :P
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3917692
π§βπ« Status Update - Control flow (U04.SUP)
WEEK 5 - FEB 19
UNIT 05: Structs
π Presentation - Structs (U05.PRES)
ποΈ Reading - Structs (U05.READ)
- Introduction to objects
Programming paradigms (pronounced "pair-uh-dimes") are ways we can classify different programming styles. Some programming languages support multiple paradigm styles and some are restricted to one style of coding. Over the decades different paradigms have been developed and evolved over time. Object Oriented Programming is one of the most common styles of programming these days, and is a big part of how C++, C#, and Java-based programs are designed.
- What are "Objects"?
Defining classes and structs in our programs are a way that we can create our own data types for our variables. When we define our own structures, we can create them with internal variables and functions available to them. The variables we create, whose data types come from a defined class or struct, is known as an object.
Design-wise, the idea is to take real-world objects and find a way to represent them in a computer program as an object that has attributes (variables) and functionality (functions).
- OOP design ideals
The concept of Object Oriented Programming is creating a design that is easy to maintain over time. In particular, there are some core design goals behind OOP, including:
- Encapsulation: Giving the user / other programmers an βinterfaceβ
to interact with the objects, hiding the inner-workings within the class.
- Certain functions are made public, which other programmers can use to interface with the object.
- The other programmers don't need to worry about the inner-workings of the object in order to use it.
- The developer of the class can modify how the internals work without breaking the public interface.
- Helps protect the data within the class from being accessed or modified by external things that shouldn't have access to it.
- Loose coupling: Ideally, different objects in a program shouldn't have their functionality tied to other objects too closely; we wan tto reduce inter-dependence between objects. When objects are more independent from each other, we say they are loosely coupled.
- High cohesion: When we design our objects, we shouldn't just throw everything and the kitchen sink into one object. To design an object with high cohesion means that everything inside the object belongs to that object - reduce the clutter.
- What are "Objects"?
- Separate variables to one struct
Structs are a way we can group related information together into one data type.
For example, let's say we were writing a program for a restaurant, and an item on the menu would have a name, a price, a calorie count, and a "is it vegetarian?" signifier. We could declare these all as separate variables:
string food1_name; float food1_price; int food1_calories; bool food1_is_veggie;
But there isn't really anything in the program that says these variables are related, except that we as humans have given these variables similar prefixes in their names.
A better design would be to create a new datatype called MenuItem (or something similar), and the MenuItem will contain these four variables within it. We're basically making a variable data type that can contain multiple variables!
First we create the struct, which should go in its own .h file:
MenuItem.h:
struct MenuItem { string name; float price; int calories; bool isVeggie; };
And then we can declare variables of this type in our program:
main.cpp:
MenuItem food1; food1.name = "Bean Burrito"; food1.price = 1.99; food1.calories = 350; food1.isVeggie = true; MenuItem food2; food2.name = "Crunchy Taco"; food2.price = 1.99; food2.calories = 170; food2.isVeggie = false;
- Multiple files in C++ programs
When creating a struct, we should create a new source code file in our project. Usually the name of the file will be the same name as the struct, with a .h at the end. This is a header file and declarations for structs (and functions and classes later) will go in these types of files.
Something you need to require in your .h files that isn't needed for your .cpp files are file guards. These prevent the compiler from reading the file more than once. If it reads it multiple times, it will think you're redeclaring things over and over again.
Your .h files should always look like this:
#ifndef _MYFILE_H #define _MYFILE_H // put code here #endif
Where the "
_MYFILE_H
" should be changed to something unique in each file - usually, the name of your file.
- Creating our own structs
A basic struct declaration is of the form…
#ifndef _MYFILE_H #define _MYFILE_H struct STRUCTNAME { // member variables int MEMBER1; string MEMBER2; float MEMBER3; }; #endif
Note that the closing curly-brace
}
must end with a;
otherwise the compiler will give you errors.You can name your struct anything you'd please but it has to abide by the C++ naming rules (no spaces, no keywords, can contain letters, numbers, and underscores).
Any variables we declare within the struct are known as member variables - they are members of that struct.
Any new variables you declare whose data type is this struct will have its own copy of each of these variables.
- Declaring object variables
A object is a type of variable whose data type is a struct (or class). To declare a variable whose data type is a struct, it looks like any normal variable declaration:
DATATYPE VARIABLE;
- Accessing member variables
Our struct object variables each have their own member variables, which we access via the dot operator
.
. We can assign values to it, our read its value, similar to any normal variable.VARIABLE.MEMBER1 = 10; VARIABLE.MEMBER2 = "ASDF"; VARIABLE.MEMBER3 = 2.99; cout << VARIABLE.MEMBER1 << endl;
- Example: Fraction struct
First we would declare our Fraction struct within Fraction.h:
#ifndef _FRACTION_H #define _FRACTION_H struct Fraction { int num; int denom; }; #endif
Within
main()
, we could then create Fraction variables and work with them:main.cpp:
#include "Fraction.h" int main() { Fraction frac1, frac2, frac3; cout << "FIRST FRACTION" << endl; cout << "* Enter numerator: "; cin >> frac1.num; cout << "* Enter denominator: "; cin >> frac1.denom; cout << endl; cout << "SECOND FRACTION" << endl; cout << "* Enter numerator: "; cin >> frac2.num; cout << "* Enter denominator: "; cin >> frac2.denom; frac3.num = frac1.num * frac2.num; frac3.denom = frac1.denom * frac2.denom; cout << endl; cout << "PRODUCT: " << frac3.num << "/" << frac3.denom << endl; return 0; }
- Declaring object variables
- Review questions:
- File guards are needed because…
- What kind of data would be good to represent with a struct?
- A character in a video game including the amount of experience points they have, their current hit points, and current level
- The tax rate of a city
- The URL of a website you're visiting
- An address, including recipient name, street address, city, state, and zip code
- If we declared an object variable like
Course cs200;
, How would we assign "cs" to thedepartment
member variable and 200 to thecode
member variable?
π Concept intro - Structs (U05.CIN.202401CS200)
π§βπ¬ Lab - Structs (U05.LAB)
What we're gonna do:
- Practice with declaring struct object variables
- Practice with accessing member variables
- Practice with writing our own struct declaration
Using the command line:
Navigate to your folder using the cd
(change directory) command:
$ cd FOLDERNAME
View what files are in the current folder using the ls
(list) command:
$ ls graded_program_1 practice2_ifelse practice5_switch graded_program_2 practice3_ifelseif practice6_while_program practice1_if practice4_operators
Build ALL SOURCE code files using the g++
compiler:
g++ *.cpp *.h
Run your program using ./
(Linux/Mac) or .\
(Windows):
- Windows:
.\a.exe
- Linux/Mac:
./a.out
practice1_struct
: Pet store program
---- PET 1 ---- Name: Kabe Age: 9 Animal: Cat Breed: Gray ---- PET 2 ---- Name: Luna Age: 5 Animal: Cat Breed: Tuxedo7 Collected information: PET# NAME AGE ANIMAL BREED -------------------------------------------------------------------------------- 1 Kabe 9 Cat Gray 2 Luna 5 Cat Tuxedo
This program contains two files: Pet.h
and pet_store.cpp
.
Our struct declarations go in header files, which end with the ".h" file extension.
Within Pet.h
, a struct is already declared:
struct Pet { string name; int age; string animal; string breed; }; // ; is required at the end of a struct declaration
And within pet_store.cpp
, one pet is already created:
Pet pet1; // Ask the user to enter information... cout << "Name: "; // Display prompt getline( cin, pet1.name ); // Get string input cout << "Age: "; // Display prompt cin >> pet1.age; // Get int input cin.ignore(); // Flush the input buffer cout << "Animal: "; // Display prompt getline( cin, pet1.animal ); // Get string input cout << "Breed: "; // Display prompt getline( cin, pet1.breed ); // Get string input
For this assignment, create a second pet (struct object variable), fill out its information (member variables), and display its information afterwards. Use the first pet as a reference.
practice2_struct
: Recipe ingredients
BREAD RECIPE Ingredients * 4.5 Cups of Flour * 1 Tablespoons of Sugar * 2.25 Teaspoons of Instant Yeast * 1.66 Cups of Water * 2.5 Teaspoons of Table Salt
Within the Ingredient.h
file, create a Struct named Ingredient
that contains the following
member variables:
Ingredient | |
---|---|
- name |
: string |
- unit |
: string |
- amount |
: float |
Remember that a struct declaration must have a semicolon ;
on its
closing curly brace }
!
Within the recipe.cpp
file, a bunch of variables are already created:
string ingredient1_name = "Flour"; string ingredient1_unit = "Cups"; float ingredient1_amount = 4.5;
You'll replace each set of variables with a single Ingredient
variable instead,
and update its member variables:
Ingredient ing1; ing1.name = "Flour"; ing1.unit = "Cups"; ing1.amount = 4.5;
Further down in the program there are cout
statements that display all the data.
You will have to remove the old variables (ingredient1_name
) and replace them
with the new variables (ing1.name
) as well.
Graded program: Room builder
Enter room's width: 5 Enter room's length: 7 RESULT: * width: 5 * length: 7 * area: 35 * perimeter: 24
Within the Room.h
file, a Room struct has been declared:
struct Room { float width; float length; float area; float perimeter; };
You'll work in the room_builder.cpp
file. Within the StudentCode function,
it starts by creating a Room object, then it has a TODO comment, and then it returns the Room
object at the end:
Room StudentCode( float width, float length ) { Room my_room; // TODO: Finish setting up my_room return my_room; }
Note that this function has access to a float width
and a float length
variable,
which you will be using when you write your code.
At the TODO line, work with the my_room
variable to set its member variables.
Member variable | Assign to… |
---|---|
my_room.width |
width |
my_room.length |
length |
my_room.area |
width * length |
my_room.perimeter |
2 * width + 2 * length |
Afterwards you can run the program to manually check your work and you can run the AUTOMATED TESTS to verify that all the tests pass.
- Turning in your work
- Go to your GitLab webpage.
- Select the folder for this unit in the main view. Locate the file you want to update and click on it.
Click on the blue "Edit" button, then click "Edit single file".
- COPY your work off your computer and PASTE it into the web editor on GitLab. Scroll to the bottom of the page and click "Commit changes" to finish up.
Go back to the unit folder and COPY the URL for this unit.
- On Canvas, locate the assignment. Click "Start assignment".
Paste the copied URL into the box and click "Submit assignment".
ποΈ Unit 05 Debugging - Debugging review - C++ basics (U05.EXE.D)
ποΈ Nonogram - Nonogram D (U05.EXE.N)
How to play: Each cell in the grid of squares can either have a X (or blank) or be filled in. The filled in boxes create the pixels of an image. Each row and each column have one or more numbers. This specifies how many pixels are in that row/column. The number given is how many unbroken pixels will show up together. Two numbers separated by a space, e.g., "1 1", will have at least one empty spot between them.
Hint: Tree
Hint: Chocolate chip cookie
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3918191
π§βπ« Unit 05 Status Update - Structs (U05.SUP)
WEEK 6 - FEB 26
UNIT 06: Functions
π Presentation - Functions (U06.PRES)
ποΈ Reading - Functions (U06.READ)
- Program Structure
As programs become more sophisticated and offer more features, the size of the program increases. At some point, it becomes too complicated to keep your entire program just within
main()
.(You could certainly do it, but maintaining it would be a nightmare!)
One of the tools we use to build modular, easier-to-read code is functions. By using functions, we can delegate tasks out to other portions of the program, passing inputs as data to the function, and receiving some kind of output as a result.
As a basic example, let's say we need to calculate square footage of a room in multiple places in a program. By making a
float GetArea( float width, float length )
function.Then, we only have to implement the formula once and can use the function in every part of the program. Then, we wouldn't be copy-and-pasting the same formula over and over again in the code - which also means less likelihood of errors, and easier to update later as needed.
- Program flow and functions
Whenever a function is called, the program flow is redirected into that function, running from top-to-bottom as normal (with branching and loops changing that flow). Once the function has completed, it can return some data, which is received by the call location.
From a design standpoint, this means we can break out different parts of programs into their own sections. Each function has a name, which should be used to label what the purpose of its code is.
- Function Basics
- Uses of functions
- Functions for formulas
In algebra, you've seen functions like this:
\[ f(x) = 2x + 3 \]
If you were like me in algebra, you might have thought to yourself, "That's the same as \(y = 2x + 3\), why did we replace \(y\) with \(f(x)\)?"
The reason is that we want to write a function in terms of its input, \(x\), and its output \(f(x)\). The equation \(2x + 3\) is the function body, which specifies how we get some output given some input.
We can use functions in programming like with math as well - defining formulas that we might need a lot - but there's more to functions than just making computations.
Let's say we want to make our "GetArea" function in math. We would need two inputs: Width and Length, and the output would end up being the area, so maybe we would name the function \(A\). It might look like this:
\[ A( w, l ) = w \cdot l \]
In C++, it would look like this:
float Area( float width, float length ) { return width * length; }
(Luckily we don't have to restrict ourselves to single-letter variable and function names in C++ :)
- Functions to validate
Functions can also be handy in validating data and user input, putting the validation in one place instead of having to re-implement the same checks over and over.
For example, let's say we want to keep some variable percentage in our program betwee 0% and 100% - no negative values, nothing over 100%. We could implement a function that takes the percentage as an input, and either returns the same percentage, or 0%, or 100% as output…
int BoundPercent( int originalPercent ) { if ( originalPercent < 0 ) { return 0; } else if ( originalPercent > 100 ) { return 100; } else { return originalPercent; } }
Then, anywhere in the program, we could use this function to make sure our percentages are in the right range…
// in main() hungerPercent = BoundPercent( hungerPercent ); healthPercent = BoundPercent( healthPercent ); happinessPercent = BoundPercent( happinessPercent );
- Functions to get input
Getting user input is a common part of writing software, and we will usually need to validate what the user is entering prior to doing any operations on it. Let's say your program is full of numbered menus and you want to validate the user's menu choices easily. You can use a function with a while loop in it:
int GetUserInput( int min, int max ) { int choice; cout << "Choice: "; cin >> choice; while ( choice < min || choice > max ) { cout << "Invalid choice, try again: "; cin >> choice; } return choice; }
You write this function once and then you can reuse it in your entire program for all menus…
cout << "1. Deposit money" << endl << "2. Withdraw money" << endl << "3. View balance" << endl; choice = GetUserInput( 1, 3 ); // 1, 2, or 3 if ( choice == 1 ) { cout << "1. Checking account" << endl << "2. Savings account" << endl; choice = GetUserInput( 1, 2 ); // 1 or 2 }
- Functions to output
Functions aren't required to return data. Sometimes, you just want a function that is responsible for formatting output or displaying a menu. In this case, a function's return type can be
void
.void DisplayStudentInfo( string name, float gpa ) { cout << "Name: " << name << "GPA: " << gpa << endl; }
You also aren't required to pass input to functions. In this case, the parameter list between ( ) remains empty, but the () is always required for functions:
void DisplayMainMenu() { cout << "1. Deposit" << endl; cout << "2. Withdraw" << endl; cout << "3. View Balance" << endl; cout << "4. Log Out" << endl; }
- Other uses
These are just some examples of why you might use functions in your programs. Anything you write in
main()
can go inside of a different function as well - it's just another tool for designing clean, maintanable, and readable code.
- Anatomy of a function
- Function Declaration
float GetArea( float width, float height );
Before you start using a function, you have to declare and define it… A function declaration is similar to a variable declaration - we tell the program "hey, we want to use this function, here's its name and some info about it." Declaration statements end with a semi-colon and don't contain a code block (the function body) because it's just a declaration.
Function Header: The function header is the first line of a function, which includes the following information: return type, function name, and parameter list.
RETURNTYPE FUNCTIONNAME( PARAM1TYPE PARAM1NAME, ... )
- Function Return Type:
The return type of a function specifies what kind of data
is returned from this function. The return type can be any data type,
or it can be
void
if nothing is going to be returned. - Function Name: The function name should describe what the responsibility of the function is - what it does.
- Function Parameters: The parameters of a function are a list of input variables that are expected to be passed into the function from elseware. The parameter list is located between the ( and ) in the function header.
- Function Return Type:
The return type of a function specifies what kind of data
is returned from this function. The return type can be any data type,
or it can be
- Function Definition
float GetArea( float width, float height ) { return width * height; }
The function definition is where we actually write what the function does. It includes the same information as the function declaration, but we include the function body in a code block.
- Function Body
The function body is the code block, written between
{
and}
, defining what logic the function performs.
- Function Call
float room1Sqft = GetArea( 5, 10 ); float room2Sqft = GetArea( room2width, room2length );
After a function is defined, we can then call that function to execute its internal code. If the function has input parameters, we can pass in literal values (hard-coded data) or variables to provide that input data.
Calling a function
Once the function has been defined, you can call it from anywhere in your program…
int main() { float width, height; cout << "Enter width and height: "; cin >> width >> height; // Call GetArea float area = GetArea( width, height ); cout << "Area: " << area << endl; }
Function Call: Calling a function requires the function name, and passing in a series of inputs that become the function's parameters. In the example above, the
GetArea
function is called, with the values from thewidth
andheight
variables being passed in. Once GetArea returns its output, that output is then stored in thearea
variable.Arguments: An argument is the name of the value or variables being passed into the function during the function call. These arguments become the values that the function parameters within the function definition uses.
Here in the function call, 10 and 20 are the arguments:
// Call GetArea float area = GetArea( 10, 20 );
So the values of 10 and 20 get used as the width and length parameters' values:
float GetArea( float width, float height ) { return width * height; }
The arguments of a function call can be hard-coded values, like 10 and 20 above, or you can pass in other variables as arguments. Then, whatever is stored in those variables is copied over to the parameters.
// Call GetArea twice float area1 = GetArea( room1Width, room1Length ); float area2 = GetArea( room2Width, room2Length );
The arguments passed in do not need to share a name with the parameters; these are not the same variables. They're only sharing the data stored within them.
The first time
GetArea
is called, whatever is stored withinroom1Width
is copied from that variable and stored in the parameter variablewidth
within the function's definition.Common function errors:
- When you're declaring/defining a function you specify data types -
the return type and the parameters' data types.
When you're calling a function, you do not include data types!
- YES:
sqft = GetArea( room_width, room_length );
- NO:
sqft = GetArea( float room_width, float room_length );
- YES:
- Functions must have parentheses
()
! If you're missing the parentheses, your program isn't going to call the function!- YES:
DisplayMenu();
- NO:
DisplayMenu;
- YES:
- If a function contains a
return
statement, then you must store the returned data in a variable! If you don't assign the return anywhere, it will be lost!- YES:
sqft = GetArea( room_width, room_length );
- NO:
GetArea( room_width, room_length );
- YES:
- When you're declaring/defining a function you specify data types -
the return type and the parameters' data types.
When you're calling a function, you do not include data types!
- Function Declaration
- Uses of functions
- Variable scope
Scope refers to the location in the code where a variable exists.
- main():
- If you declare a variable at the top of the
main()
function, not inside any if statements or loops, then that variable is in scope for the entire duration ofmain()
, starting with the line it was declared on.
int main() { int a; // ...etc... }
- Variables declared within if statements and loops:
- Variables declared within the code block of an if statement or a loop only exists within that code block.
if ( a == 3 ) { int b; // only exists within this block } for ( int i = 0; i < 10; i++ ) { cout << i; // only exists within this block }
If you try to use these variables somewhere below the code block, your compiler will give an error, stating that the variable does not exist in that scope. Once the program leaves the code block, the variable is out of scope.
- Functions:
- Remember that
main()
is a function, just like any other functions we write in our program. Any variables declared within a function are local to that function, and accessible anywhere from the variable's declaration until the end of the function.
int GetChoice() { int choice; // local variable cout << "Choice: "; cin >> choice; return choice; }
- Parameters:
- Variables declared in the parameter list of a function are also local to that function and can be used anywhere within the function.
int Sum( int a, int b, int c ) { // a, b, and c are local to this function. return a + b + c; }
- Same names?
- The same name can be reused for different variables in different scopes. Even if they share the same name, they are not related in any way.
int GetChoice() { int choice; // Variable A cout << "Choice: "; cin >> choice; return choice; } int main() { int choice; // Variable B choice = GetChoice(); }
- Parameters and arguments
- Pass-by-value
When we have a function declared with a parameter…
void Example( int someNumber ) { cout << someNumber; }
…and we call that function elseware, passing in another variable as an argument…
int main() { int myNumber = 2; Example( myNumber ); return 0; }
… What happens is that the value of the variable myNumber is copied and passed to the function parameter
someNumber
. This works the same as if you simply pass inExample( 10 )
, passing in a hard-coded value instead of using a variable.If you wrote the function to change the value of its parameter, that change would only be reflected within the function and would not affect the original argument passed as part of the function call.
void Example( int someNumber ) { cout << "Example begin: " << someNumber << endl; someNumber = 100; cout << "Example end: " << someNumber << endl; } int main() { int myNumber = 2; Example( myNumber ); cout << "main end: " << myNumber << endl; return 0; }
The output of this program would be:
Example begin: 2 Example end: 100 main end: 2
Even though the value of
someNumber
from theExample
function changes (which is valid), that change doesn't affectmyNumber
within main(), because only the value was copied over.This is known as pass-by-value.
- Pass-by-reference
If we wanted to change the value of an argument variable within a function, we'd have to change the parameter to pass-by-reference. To do this, we use the symbol = &= in the parameter's declaration, after the data type and before the variable name.
void Example( int& someNumber ) { cout << "Example begin: " << someNumber << endl; someNumber = 100; cout << "Example end: " << someNumber << endl; }
The ampersand symbol can go next to the data type (
int & blah
), next to the variable name (int &blah
), or separate from both (int & blah
).Once we've made the parameter a reference, then when the function is called, the argument is not copied - a reference to that variable is passed to the function. Any changes to the reference parameter in the function also affects the original argument variable.
int main() { int myNumber = 2; // Calling it looks the same as before Example( myNumber ); cout << "main end: " << myNumber << endl; return 0; }
The output of this program would be:
Example begin: 2 Example end: 100 main end: 100
- Pass-by-reference instead of return
- In some cases, you may need to return multiple pieces of data
from a function - however, you can only return one item
from a function with the
return
statement (in C++). One option is to set the information you want "returned" as pass-by-reference parameters of the function.
void DoubleTheseNumbers( int & a, int & b, int & c ) { a *= 2; b *= 2; c *= 2; }
- Pass-by-reference of large things
We haven't gone over arrays or classes/objects yet, but another reason we might want to pass something by-reference instead of by-value is when the parameter is big (which can be the case with arrays and objects).
If we have a large object we need to pass to a function, doing a copy of the entire thing is inefficient - it is much simpler and faster to pass the large object by-reference.
- Summary: Ways to pass data to/from functions
The following table illustrates different ways we can define our parameters, and what the goal is. "RT" means "Return Type", "T" is the "Type" of the parameter.
# Function Read Return Info 1. RT func( T X )
yes no Pass-by-value X
2. RT func( const T& X )
yes no Const pass-by-reference X
3. RT func( T& X )
yes yes Pass-by-reference X
X
is pass-by-value, which is fine for primitive data types like ints, floats, chars, and bools.X
is passed by const-reference becauseX
is a mose sophisticated data type like a string or other class-based object. (Longer time to copy if passed by value.)- The function can read from
X
but also overwrite its value and the change will be reflected back to the argument being passed to the function call.
- Pass-by-value
- Default parameters
When declaring a function, you can also set default parameters. These are the default values assigned to the parameters if the user doesn't pass anything in. The default parameters are only specified in a function declaration - NOT the definition!
In this example, it could be a function that displays ingredients for a recipe, and by default the batch is set to 1.0 (one batch).
void OutputIngredients( float eggs, float sugar, float flour, float batch = 1.0 );
The function could be called without passing in a batch:
cout << "Ingredients:" << endl; OutputIngredients( 1, 2.0, 3.5 );
Or they could pass a batch amount explicitly:
cout << "Ingredients:" << endl; OutputIngredients( 1, 2.0, 3.5, 0.5 ); // half batch
You can have multiple default parameters specified in your function declaration - but all variables with default values must go after any variables without default values.
- Function Overloading
In C++, you can also write multiple functions that have the same name, but a different parameter list. This is known as function overloading.
Let's say you want to be able to sum numbers, and you make a version for floats and a version for integers:
int Sum( int a, int b ) { return a + b; } float Sum( float a, float b ) { return a + b; }
You can write as many versions of the function as you like, so long as the function headers are uniquely identifiable to the compiler, which means:
- The functions have a different amount of parameters, or
- The data types of the parameters are different, or
- The parameters are in a different order (when mixing data types).
These will become much more useful once we cover classes and objects.
- Review questions:
- Build the function signature given the following specs:
- The function is named "GetRectArea".
- The function returns a float.
- The function takes in a float for the width and a float for the length
- Identify each code snippet (function declaration / definition / call):
a.
float PercentToDecimal( float percent ) { return percent / 100.0; }
b.
float PercentToDecimal( float percent );
c.
float decimal = PercentToDecimal( percent );
Identify how the following parameters are passed (by value / by reference), given this function declaration:
void SomeFunction( int& a, int b );
a
is passed…b
is passed…
- Build the function signature given the following specs:
π Concept Intro - Functions (U06.CIN)
π§βπ¬ Lab - Function (U06.LAB)
What we're gonna do:
- Practice writing functions with a void return type and no parameters
- Practice writing functions with a void return type but with parameters
- Practice writing functions that return data but have no parameters
- Practice writing functions that return data and with parameters
- To build your code in the terminal:
- If the program has .h and .cpp files:
g++ *.h *.cpp
- If the program only has .cpp files:
g++ *.cpp
- If the program has .h and .cpp files:
- To run the program:
- Windows:
.\a.exe
- Linux/Mac:
./a.out
- Windows:
- Practice programs
Program documentation is inside the source files.
Practice Location Starter code practice 1: DisplayMenu function u06_Functions/practice1_NoInNoOut/
program1.cpp practice 2: DisplayFormattedUSD function u06_Functions/practice2_YesInNoOut/
program2.cpp practice 3: GetTaxPercent function u06_Functions/practice3_NoInYesOut/
program3.cpp practice 4: GetPricePlusTax function u06_Functions/practice4_YesInYesOut/
program4.cpp
- Graded program: Purchase program
######################################## PURCHASE CALCULATOR Current transaction amount: $0.00 1. Add item 2. Checkout Enter a number between 1 and 2: 1 Enter price of new item: $2.50 Current transaction amount: $2.50 1. Add item 2. Checkout Enter a number between 1 and 2: 1 Enter price of new item: $4.56 Current transaction amount: $7.06 1. Add item 2. Checkout Enter a number between 1 and 2: 2 RECEIPT * Transaction total: $7.06 * Tax rate: %9.61 * After tax: $7.74 RESULT: 7.74
This project has several files, but you only need to make updates in a couple of them.
- Program.cpp: contains
main()
(I've already written this) - Tester.cpp: contains the automated tests (I've already written this)
- Functions.h: contains the function declarations (I've already written these)
- Functions.cpp: contains the function definitions (you will update these)
Within Functions.h update the
YOURNAME
string with your name.
Updating the Function Definitions in Functions.cpp:
You can copy the
DisplayMenu
,FormatUSD
,GetTaxPercent
, andGetPricePlusTax
functions from the practice programs. (Look at the practice programs for the requirements for these functions.)There are a few new functions as well.
float GetNewPrice():
- Create a float variable to store a new price.
- Ask the user to enter the price of the new item.
- Get their input and store it in your float variable.
return
your float variable at the end.
int GetChoice( int min, int max ):
- Create an integer variable to store the user's input.
- Ask the user to enter a number.
- Get their input and store it in your integer variable.
- WHILE their input is less than
min
OR greater thanmax
, do:- Display an error message ("Outside valid range!")
- Get the user's input again and store it in your integer variable (the same one).
- After the while loop,
return
the user's input variable.
float StudentCode():
This will be where the main program lives.
Quick reference: How to call the functions that we'll be working with:
Function name Declaration Inputs Outputs Example call DisplayMenu void DisplayMenu();
none none DisplayMenu();
GetChoice int GetChoice( int min, int max );
min, max the user's choice choice = GetChoice(1, 2);
GetNewPrice float GetNewPrice();
none a price price = GetNewPrice();
DisplayFormattedUSD void DisplayFormattedUSD( float );
a price none FormatUsd( var );
GetTaxPercent float GetTaxPercent();
none the tax percent tax = GetTaxPercent();
GetPricePlusTax float GetPricePlusTax( float, float );
price, tax the updated price newprice = GetPricePlusTax( price, tax );
How to implement this function: Follow each step linearly, starting from the top of the
StudentCode
function.- Make sure you have the following variables declared here:
Variable Type Value final_price
float transaction_total
float new_price
float running
bool true
choice
int - Create a while loop to keep the program running until the user decides to quit:
while ( running ) { }
- Within the while loop do the following:
- Display "Current transaction amount:"
- Call the
DisplayFormattedUSD
function, passing in thetransaction_total
. (DON'T use a cout on this line!) - Call the
DisplayMenu
function. - Call the
GetChoice
function passing in1
and2
as the arguments. Store the return data in thechoice
variable. - If
choice
is1
:- Call the
GetNewPrice
function and store its return data in thenew_price
variable. - Add
new_price
to thetransaction_total
, making sure to update thetransaction_total
's value.
- Call the
- Otherwise if
choice
is2
:- Set
running
tofalse
so that the loop will end and the program will continue.
- Set
- After the while loop is over, display the text "RECEIPT".
- Call the
GetPricePlusTax
function, passing intransaction_total
andGetTaxPercent()
as its arguments. Store its return data in thefinal_price
funnction. - Display "Transaction total:".
- Call
DisplayFormattedUSD
, passing in thetransaction_total
. (DO NOT USE cout HERE.) - Display "Tax rate:", then call
GetTaxPercent()
, all in one cout statement. - Display "After tax:".
- Call the
DisplayFormattedUSD
function, passing in thefinal_price
. (Do not use cout here.) - Finally,
return
thefinal_price
at the end of this function.
- Program.cpp: contains
- Turning in your work
Go to the GitLab webpage, locate the file you want to update, and click the blue "Edit" button, then click "Edit single file". Paste in your changes and click the "Commit changes" at the bottom of the page. Copy the URL to the file or unit folder and paste it in as your submission on the Canvas assignment.
π§ Tech Literacy - Software development lifecycle (U06.TEC)
π§βπ« Status Update - Functions (U06.SUP)
WEEK 7 - MAR 4
Project 2
π» Project 2 (PROJ2)
$ ./a.out ----------------------------------------------------- -- R E C I P E P R O G R A M -- ----------------------------------------------------- 0. Quit program 1. Tiger Butter Candy 2. White Chocolate Peppermint Pretzels Which recipe? 1 How many batches would you like to make? 2 -------------------------------------------------------------------------------- Tiger Butter Candy (From https://butterwithasideofbread.com/tiger-butter-fudge/) INGREDIENTS * 22 oz of Vanilla chips * 1 cup of Creamy peanut butter * 1 cup of Semi-sweet chocolate chips -------------------------------------------------------------------------------- Press ENTER to continue 0. Quit program 1. Tiger Butter Candy 2. White Chocolate Peppermint Pretzels Which recipe? 2 How many batches would you like to make? 0.5 -------------------------------------------------------------------------------- White Chocolate Peppermint Pretzels (From https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/) INGREDIENTS * 5.5 oz of Vanilla chips * 0.25 cup of Creamy peanut butter * 0.25 cup of Semi-sweet chocolate chips -------------------------------------------------------------------------------- Press ENTER to continue 0. Quit program 1. Tiger Butter Candy 2. White Chocolate Peppermint Pretzels Which recipe? 0
- About
For this project we're adding onto our recipe program from Project 1. You'll want to make a copy of the
project1.cpp
file for this new version (more instructions later) but we will be adding control flow, functions, and a struct into our project, step-by-step.Make sure to follow the entire document to successfully complete the project.
- How to be successful at projects
- Your program should always build. Don't continue writing features if you have build errors. WORKING CODE THAT IS INCOMPLETE IS BETTER THAN "COMPLETE" BUT BROKEN CODE THAT DOESN'T EVEN RUN.
- Implement one feature at a time. Test after implementing one feature. Work on small chunks at a time.
- Utilize other code as reference material; code from in class, previous projects, example code from the example code repository (https://gitlab.com/rachels-courses/example-code/-/tree/main/C++?ref_type=heads).
- Research error messages via search engine, look for an explanation of what an error message means. You can even try to ask an AI what an error message means and see if it gives a coherent explanation.
- You can refer to outside sources, just don't plagiarize. You need to learn how to do the programming yourself, but researching is a normal part of "the job".
- If you get stuck, you should seek solutions, such as:
- Asking a tutor - The campus has tutors via the Academic Achievement Center.
- Asking the instructor - You can email me, you can ask me in class, you can schedule a one-on-one time to meet via Zoom or in person.
- Looking at example code from class videos and the example code repository.
- CS 200 topics quick reference
Use this as a reference while working through your program. You might copy/paste these notes elseware or print them out to keep them handy.
Terminal commands
Command What it does cd FOLDERNAME
Moves you into the FOLDERNAME. cd ..
Moves you out of the current folder. ls
View a LiSt of files and folders in the current directory. g++ FILENAME
Build a C++ file, turning source code into an executable file. Creates "a.exe" or "a.out". ./a.exe
Runs the executable file named "a.exe". C++ instructions
Instruction What it does DATATYPE VARNAME;
Declare a variable with some datatype and name. int my_int;
Declare an integer variable named my_int
.float my_float;
Declare a float variable named my_float
.string my_string;
Declare a string variable named my_string
.my_int = 10;
Assign a value of 10 to the my_int
variable.my_float = 9.99;
Assign a value of 9.99 to the my_float
variable.my_string = "Hello!";
Assign a value of "Hello!" to the my_string
variable.cout << "Hello!";
Displays "Hello!" to the screen. cout << my_string;
Displays the value of the my_string
variable to the screen.cout << endl;
Adds a new line before the next cout display. cin >> my_float;
Gets keyboard input, stores in my_float
variable.if ( CONDITION ) { }
Executes code within code block {}
ONCE if CONDITION is true.else if ( CONDITION ) { }
Executes code within code block {}
ONCE if associated "if" CONDITION is false and this "else if" CONDITION is true.else {}
Executes code within code block {}
ONCE if all previous "if" and "else if" CONDITIONS are false.switch( VARIABLE ) { }
Investigates the value of the VARIABLE, uses case statements for different possible variable values. case 3: /* ... */ break;
Code between "case" and "break" is executed if the switch's VARIABLE equals this case value (3 in this example). default:
The default "catch all" (like else) for a switch statement. while ( CONDITION ) { }
Executes code within code block {}
REPEATEDLY while the CONDITION is true.struct STRUCTNAME { };
Declare a struct. Within the code block {}
member variables can be declared.STRUCTNAME VARIABLE;
Declare a new variable whose data type is the struct. VARIABLE.MEMBER = 3;
Access a member variable of the struct using the dot operator .
and the name of the member variable.RETURN FUNCNAME( PARAMS );
Function declaration (goes in .h file). RETURN FUNCNAME( PARAMS ) { }
Function definition (goes in .cpp file). Add program logic within the code block {}
, which will get executed when the function is called.FUNCTIONNAME();
Calling a void function that doesn't have parameters. Make sure to use () at the end of the function name. FUNCTIONNAME( ARGS );
Calling a void function, use the function name and pass in values as arguments. VARIABLE = FUNCTIONNAME( ARGS );
Calling a function with a return type, assign the return value of the function to some variable.
- Setup
- Creating new source files
Create a new folder for this entire project, such as "project2". You'll need this as a folder on your computer and in your GitLab repository. We'll go over the GitLab steps further down. For now, let's update the files on your computer.
Copy your "project1.cpp" file and paste it into your folder. I would suggest renaming "project1.cpp" to "main.cpp" instead, as it is the file that has the
main()
function in it.Also create several new files:
- Ingredient.h
- Functions.h
- Functions.cpp
You can either create these files in your File Explorer by right-clicking in the empty space and selecting New > New Text Document, and making sure to give them the correct file extension (.cpp or .h):
Or you can create a new file from the terminal by using the
touch
command:touch Ingredient.h touch Functions.h touch Functions.cpp
Then you'll have the files you need:
These will also need to be uploaded to GitLab, so even though we haven't edited any code yet, let's get them uploaded.
- Setting up the GitLab folder
On GitLab, go into your
PROJECTS
folder, then click the "+" button and choose "New directory":Name the new folder "project2" and click "Create directory":
Go into the folder, then click the "+" button again and choose "Upload file":
Upload each file, one at a time: main.cpp, Ingredient.h, Functions.h, Functions.cpp. Once done, you'll have all the files for your project here:
They're currently blank, but we'll make backups as we complete each version of the program.
- Creating new source files
- Recipe v4: Ingredient structs
Within the Ingredient.h file, we are going to declare our Ingredient struct. Since this is a header file (a .h file), we need to start off with fileguards:
#ifndef _INGREDIENT #define _INGREDIENT #endif
Within this file, declare your Ingredient struct. Refer back to your notes, example code, or the textbook for how to write a struct if needed.
Your struct should contain the following member variables:
name
, a stringamount
, a floatunit
, a string
Once that is done, we can start editing main.cpp to integrate the struct into our program.
Hint: At this point you may get a build error complaining that this file doesn't know what "string" is. This means that you need to have
#include <string>
andusing namespace std;
at the top of this file.
In main.cpp, make sure to include the ingredient file up top, before
int main()
:#include "Ingredient.h"
Within your recipe program, work on changing the old variables for the ingredient name, amount, and unit, to use this struct now.
Old version:
string recipe1_ingredient1_name = "Pretzel"; float recipe1_ingredient1_amount = 35; string recipe1_ingredient1_unit = "chips";
New version:
Ingredient recipe1_ing1; recipe1_ing1.name = "Pretzel"; recipe1_ing1.amount = 35; recipe1_ing1.unit = "chips";
Update all your ingredients from before, both the declaration and where the recipe is being outputted.
New variables:
- Recipe 1's ingredients:
Ingredient recipe1_ing1
Ingredient recipe1_ing2
Ingredient recipe1_ing3
- Recipe 2's ingredients:
Ingredient recipe2_ing1
Ingredient recipe2_ing2
Ingredient recipe2_ing3
Variables to rename:
- Recipe 1's ingredients:
recipe1_ingredient1_name
recipe1_ingredient1_amount
recipe1_ingredient1_unit
recipe1_ingredient2_name
recipe1_ingredient2_amount
recipe1_ingredient2_unit
recipe1_ingredient3_name
recipe1_ingredient3_amount
recipe1_ingredient3_unit
- Recipe 2's ingredients:
recipe2_ingredient1_name
recipe2_ingredient1_amount
recipe2_ingredient1_unit
recipe2_ingredient2_name
recipe2_ingredient2_amount
recipe2_ingredient2_unit
recipe2_ingredient3_name
recipe2_ingredient3_amount
recipe2_ingredient3_unit
Once you've updated the program, you need to build and test before continuing on.
Open the terminal/console within the folder where your project files are. To build all the files, use:
g++ *.h *.cpp -o project2exe
Then run the program with:
./project2exe
Your program output should be pretty much the same as before, we haven't changed any functionality yet, we've just improved the code to that it will be a bit easier to maintain over time.
Now it's time to back up your work before continuing.
Back up main.cpp and Ingredient.h:
- Click on the "Edit" button, then select "Edit single file".
- Back on your computer, open Ingredients.h in your text editor.
- Select all with "CTRL+A", then hit "CTRL+C" to copy it.
- Back in GitLab, select all with "CTRL+A", then hit "CTRL+V" to paste your updates on top.
- Scroll to the bottom of the page. Add a commit message like "project 2 setup", then click Commit changes.
- Recipe v5: Program loop
Back in main.cpp, we're going to update the program so that it will keep running until the user decides to quit. This means we're going to need a program loop and we'll have a main menu with several options.
Within
main()
toward the top of the file somewhere, create a boolean variable that stores whether the program is actively running or not:bool running = true;
After the recipe variables setup and before any recipes are displayed, we're going to add the program loop:
while ( running ) { // Main menu: // Get user choice: // Quit? // Get batches: // Display a recipe: }
Implementing the main menu:
Have the program display a numbered menu to the user. It should look something like this, except with your own recipes:
0. Quit program 1. Tiger Butter Candy 2. White Chocolate Peppermint Pretzels Which recipe? _
Getting the user's choices:
We'll need to get the user's input, and since the menu has numbered options, their selection will be an integer.
Declare an integer variable to store the user's choice, and use a
cin
statement to read their input into this variable.If the choice is 0, then you can set
running
tofalse
, or use thebreak;
statement to leave the while loop immediately (causing the program to quit.)
How many batches?:
After checking to make sure the user hasn't chosen the "quit" option, we still need to ask them how many batches they want to make. Locate your code from before that would get the amount of
batches
from the user, and move it here into your while loop.
Displaying a recipe:
Finally, you can use an
if/else if
statement or aswitch
statement to look at the user's selection and determine which recipe to display. Investigate their choice variable.- if they selected option 1, then show your first recipe
- else, if they selected option 2, then show your second recipe
For both recipes, locate your code from before that displayed the recipe information and ingredients and move it within the while loop, within the appropriate if or else if statement.
Once you've updated the program, you need to build and test before continuing on.
Open the terminal/console within the folder where your project files are. To build all the files, use:
g++ *.h *.cpp -o project2exe
Then run the program with:
./project2exe
Your program should now continue running and you can select 1 or 2 to display different recipes, or 0 to quit the program.
Now it's time to back up your work before continuing.
Back up main.cpp:
- Click on the "Edit" button, then select "Edit single file".
- Back on your computer, open Ingredients.h in your text editor.
- Select all with "CTRL+A", then hit "CTRL+C" to copy it.
- Back in GitLab, select all with "CTRL+A", then hit "CTRL+V" to paste your updates on top.
- Scroll to the bottom of the page. Add a commit message like "project - version 5", then click Commit changes.
- Recipe v6: Helper functions
Now we're going to add some helper functions to help us clean up
main()
. Our function declarations will go in the Functions.h file and the function definitions will go in the Functions.cpp file. Function calls will happen in main().Hint: Remember that in your .h file you need file guards!
#ifndef _FUNCTIONS #define _FUNCTIONS // Code goes here #endif
And make sure to include the file within your .cpp file:
#include "Functions.h"
Additionally, if you're using cin/cout anywhere, you need to include
#include <iostream>
andusing namespace std;
DisplayMenu function
- Return type:
void
- Parameters: none
Use this function to display your main menu from before. This will only DISPLAY the menu, and it will not get input from the user.
0. Quit program 1. Tiger Butter Candy 2. White Chocolate Peppermint Pretzels Which recipe?
After you've moved the code into the function, make sure to call
DisplayMenu();
in main() where the menu code originally was.!!! BUILD AND TEST THE PROGRAM BEFORE CONTINUING !!!
DisplayRecipe function
- Return type:
void
- Parameters:
string recipe_name
,string recipe_url
,float batches
,Ingredient ing1
,Ingredient ing2
,Ingredient ing3
Copy the
cout
statements you were using to display one of the recipes and paste it into this function. We can use this same layout, but replace the variables from before with the parameter variables available within this function, so instead ofrecipe1_ing1.name
, you can useing1.name
,ing2.name
, etc.Back in
main()
, replace the two places the recipes are being displayed - instead, call the DisplayRecipe function, passing in the recipe's information. For example:DisplayRecipe( recipe1_name, recipe1_url, batches, recipe1_ing1, recipe1_ing2, recipe1_ing3 );
Hint: Since this function takes in
Ingredient
variables as parameters, make sure to have#include "Ingredient.h"
at the top of your Functions.h and Functions.cpp file!!!! BUILD AND TEST THE PROGRAM BEFORE CONTINUING !!!
GetUserInput function
- Return type:
int
- Parameters:
int min
,int max
Within this function, do the following:
- Create an integer variable to store the user's input.
- Use a cin statement to get the user's input.
- While their input is less than
min
or greater thanmax
, do:- Display an error message. ("Selection is invalid!")
- Use cin to get the user's input again, store in the same input variable.
- After the while loop,
return
the user's input.
Within
main()
, after displaying the main menu, replace your cin statement with a call to the GetUserInput function:int choice = GetUserInput( 0, 2 );
!!! BUILD AND TEST THE PROGRAM BEFORE CONTINUING !!!
SetupRecipes function
- Return type:
void
- Parameters:
string& rec1_name
string& rec1_url
Ingredient& rec1_ing1
Ingredient& rec1_ing2
Ingredient& rec1_ing3
string& rec2_name
string& rec2_url
Ingredient& rec2_ing1
Ingredient& rec2_ing2
Ingredient& rec2_ing3
The
&
for these variables' types mean that these are passed in by reference, which gives us access to the original variables. Any updates we make within this function will be saved back inmain()
.Cut your recipe and ingredient variable setup functions in main() and paste them into the SetupRecipes function, adjusting the variable values.
Back in
main()
, where the setup code originally was, call theSetupRecipes
function, passing in all of your variables for the two recipes…SetupRecipes( recipe1_name, recipe1_url, recipe1_ing1, recipe1_ing2, recipe1_ing3, recipe2_name, recipe2_url, recipe2_ing1, recipe2_ing2, recipe2_ing3 );
!!! BUILD AND TEST THE PROGRAM BEFORE CONTINUING !!!
- Return type:
- Turning in the assignment
- Backing up your work
Back up main.cpp, Functions.h, and Functions.cpp:
- Click on the "Edit" button, then select "Edit single file".
- Back on your computer, open Ingredients.h in your text editor.
- Select all with "CTRL+A", then hit "CTRL+C" to copy it.
- Back in GitLab, select all with "CTRL+A", then hit "CTRL+V" to paste your updates on top.
- Scroll to the bottom of the page. Add a commit message like "project - version 5", then click Commit changes.
- Uploading to Canvas:
On your GitLab page, go into your PROJECTS/project2 folder. Copy the URL to this directory, and use this as the submission link for the project in Canvas.
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3929229
- Backing up your work
WEEK 8 - MAR 11 - SPRING BREAK
Take a break!
WEEK 9 - MAR 18
UNIT 07: Strings
ποΈ Reading - Strings (U07.READ)
A string is a special data type that really is just an array of char variables. A string has a lot going on behind-the-scenes, and it also has a set of functions you can use to do some common operations on a string - finding text, getting a letter at some position, and more.
Note that everything with strings is case-sensitive.
A computer considers the letter 'a'
and 'A'
different, since they are represented by different number codes.
Keep that in mind for each of the string's functions.
Strings as arrays
When we declare a string like this:
string str = "pizza";
what we have behind-the-scenes is an array like this:
Value: | 'p' |
'i' |
'z' |
'z' |
'a' |
Index: | 0 | 1 | 2 | 3 | 4 |
Declaring a string actually gives us an array of char
variables.
We can access the string as a whole by using the string variable's name
(str
), or access one char
at a time by treating
str
like an array.
- Subscript operator - get one char with [ ]
We can access each letter of the string directly with the subscript operator, just like an array:
cout << str[0] << endl; // Outputs p cout << str[1] << endl; // Outputs i cout << str[2] << endl; // Outputs z cout << str[3] << endl; // Outputs z cout << str[4] << endl; // Outputs a
Because we can act on a string like an array, this means we can also use a variable to access an arbitrary index of a character in the array…
int i; cout << "Get which letter? "; cin >> i; cout << str[i];
Or even iterate over the string with a for loop…
for ( int i = 0; i < str.size(); i++ ) { cout << i << " = " << str[i] << endl; }
Additionally, strings have a set of functions that we can use to manipulate, search, and otherwise work with them.
String functionality
- Size of the string
size_t size() const;
The string's
size()
function will return the size of the string - how many characters are stored in the string. Thesize_t
data type is just a type of integer - an unsigned integer, because sizes cannot be negative amounts.Documentation: https://www.cplusplus.com/reference/string/string/size/
- Example: Outputting a string's length
- Let's write a little program that asks the user to enter some text, and then outputs the length of the string:
string text; cout << "Enter some text: "; getline( cin, text ); cout << "That string is " << text.size() << " characters long!" << endl;
When the user enters a line of text, it will count all characters (including spaces) in the string, so the text
"cats dogs"
would be 9 characters long.Enter some text: cats dogs That string is 9 characters long!
- Example: Counting z's
- If we wanted to use a for loop to iterate over all the letters of an array, we could! Perhaps we want to count the amount of z's that show up:
string text; int zCount = 0; cout << "Enter some text: "; getline( cin, text ); // Iterate from i=0 to the size of the string (not-inclusive) for ( unsigned int i = 0; i < text.size(); i++ ) { // If this letter is a lower-case z or upper-case Z if ( text[i] == 'z' || text[i] == 'Z' ) { // Add one to z count zCount++; } } // Display the result cout << "There were " << zCount << " z(s) in the string!" << endl;
Enter some text: The wizard fought a zombie lizard There were 3 z(s) in the string!
- Concatenating strings with +
We can use the
+
operator to add strings together as well. This is called concatenation.Let's say we have two strings we want to combine -
favoriteColor
andpetName
, we can use the concatenation operator+
to build a new string,superSecurePassword
.string favoriteColor = "purple"; string petName = "Luna"; string superSecurePassword = favoriteColor + petName; cout << superSecurePassword << endl; // = purpleLuna
We can also add onto strings by using the
+=
operator. Let's say you're building a string over time in a program, and want to append parts separately.string pizzaToppings = ""; // Later on... pizzaToppings += "Buffalo sauce, "; // Later on... pizzaToppings += "Cheese, "; // Later on... pizzaToppings += "Pineapple"; // Later on... cout << pizzaToppings << endl;
At the end of the program, the value of
pizzaToppings
would be:"Buffalo sauce, Cheese, Pineapple"
- Finding text with find()
size_t find (const string& str, size_t pos = 0 ) const;
The find function can be used to look for a substring in a bigger string. If the substring is found, its position is returned. Otherwise, the value of
string::npos
is found.When a starting
pos
is included, it only begins the search at that position. If left off, it defaults to 0 (the start of the string).Documentation: https://www.cplusplus.com/reference/string/string/find/
So when we want to search a string for some text, we can call it like
bigString.find( findMeString )
, and that function call will return an unsigned integer: the location of thefindMeString
withinbigString
, or the value ofstring::npos
when it is not found.string str = "this was written during the 2021 winter storm make it stop please."; string findMe = "winter"; size_t position = str.find( findMe ); cout << "The text \"" << findMe << "\" was found at position " << position << endl;
The text "winter" was found at position 33
- Finding substrings with substr()
string substr (size_t pos = 0, size_t len = npos) const;
Returns a string within the string, starting at the position
pos
provided, and with a length oflen
.Documentation: https://www.cplusplus.com/reference/string/string/substr/
With the
substr()
function, we can pull part of a string out, using a starting point and a length.string text = "Name: Bob"; int start = 6; int length = 3; string name = text.substr( start, length ); cout << "Extracted \"" << name << "\"." << endl;
Extracted "Bob".
- Comparing text with compare()
int compare (const string& str) const;
This compares the string with
str
and returns an integer:- \(0\) is returned if both strings are the same.
- \(< 1\) (a negative number) is returned if the caller string is "less-than" the
str
string. - \(> 1\) (a positive number) is returned if the caller string is "greater-than" the
str
string.
One character is "less than" another if it comes before, and it is "greater than" if it comes after, alphabetically.
(Remember that lower-case and upper-case letters are considered separate, so comparing
'a'
to'A'
would actually return a positive number.)Documentation: https://www.cplusplus.com/reference/string/string/compare/
string first; string second; cout << "Enter first string: "; cin >> first; cout << "Enter second string: "; cin >> second; int order = first.compare( second ); cout << endl << "Result: " << order << endl;
Enter first string: apple Enter second string: banana Result: -1
- Inserting text into a string with insert()
= string& insert (sizet pos, const string& str);=
This function will take the calling string and modify it by inserting the string
str
at the positionpos
.Documentation: https://www.cplusplus.com/reference/string/string/insert/
string text = "helloworld"; cout << "Original text: " << text << endl; int start; string insertText; cout << "Enter text to insert: "; getline( cin, insertText ); cout << "Enter position to insert: "; cin >> start; text = text.insert( start, insertText ); cout << endl << "String is now: " << text << endl;
Original text: helloworld Enter text to insert: -to the- Enter position to insert: 5 String is now: hello-to the-world
- Erasing a chunk of text with erase()
string& erase (size_t pos = 0, size_t len = npos);
This function will return a string with a portion erased, starting at position
pos
and pulling out a length oflen
.Documentation: https://www.cplusplus.com/reference/string/string/erase/
string text = "helloworld"; cout << "Original text: " << text << endl; int start; int length; cout << "Enter position to begin erasing: "; cin >> start; cout << "Enter length of text to erase: "; cin >> length; text = text.erase( start, length ); cout << endl << "String is now: " << text << endl;
Original text: helloworld Enter position to begin erasing: 2 Enter length of text to erase: 5 String is now: herld
- Replacing a region of text with replace()
string& replace (size_t pos, size_t len, const string& str);
This function is similar to erase, except it will insert the string
str
in place of the erased text.Documentation: https://www.cplusplus.com/reference/string/string/replace/
string text = "helloworld"; cout << "Original text: " << text << endl; int start; int length; string replaceWith; cout << "Enter string to replace with: "; getline( cin, replaceWith ); cout << "Enter position to begin replacing: "; cin >> start; cout << "Enter length of text to replacing: "; cin >> length; text = text.replace( start, length, replaceWith ); cout << endl << "String is now: " << text << endl;
Original text: helloworld Enter string to replace with: BYE Enter position to begin replacing: 2 Enter length of text to replacing: 5 String is now: heBYErld
- A
string
is technically an array of… - How would you output the letter at position 0 in a string? At position 2?
- What function is used to get the amount of characters in a string?
- What operator is used to combine (concatenate) two strings together?
- What does the find() function return if the searched-for substring is not found?
π Concept Intro - Strings (U07.CIN)
π§βπ¬ Lab - Strings (U07.LAB)
Starter code location: https://gitlab.com/moosadee/courses/-/tree/main/202401_Spring/Course2_CoreCPP/labs/starter_code/u07_Strings?ref_type=heads
What we're gonna do:
- Look at the cplusplus.com documentation for strings
- Work with some common string operations
- IDE help: Look at the "C++ projects - Integrated Development Environments" section under the Reference part of this textbook.
- Graded program:
Graded program: String operations program
- STRING PROGRAM --------------------------------------------------------------- OPTIONS: 0. RUN AUTOMATED TESTS 1. String length 2. Get letter 3. Find substring 4. Combine strings 5. Compare strings 6. String relations 7. Insert string 8. Erase string 9. Replace string >> 1 Enter a string: hello there! The length of your string is: 12 characters --------------------------------------------------------------------------------
When we run this program there will be the option to run the automated tests (0) or do various string operations. Each of these correspond to a function that we'll implement within the Functions.cpp file.
unsigned int GetStringLength( string text )
Enter a string: everything changed when the Fire Nation attacked The length of your string is: 48 characters
Docs: https://cplusplus.com/reference/string/string/size/
Use the string's size function to return the size of the
text
string.
char GetLetter( string text, unsigned int position )
Enter a string: the quick brown fox jumps over the lazy dog Enter a position #: 10 The letter at position 10 is: b
Docs: https://cplusplus.com/reference/string/string/operator[]/
Use the string's subscript operator to return a letter in
text
at theposition
specified.
int GetSubstringPosition( string haystack, string needle )
Enter the full string: never gonna let you up Enter the substring to search for: gonna The substring was found at position 6
Docs: https://cplusplus.com/reference/string/string/find/
Use the string's find function to see if
needle
is in thehaystack
; return the position.
string CombineStrings( string str1, string str2 )
Enter a first string: we can dance... Enter a second string: if we want to The strings combined is: "we can dance...if we want to"
Docs: https://cplusplus.com/reference/string/string/operator+/
Use the string's concatenation operator to combine
str1
andstr2
and return the result.
int CompareStrings( string str1, string str2 )
Enter a first string: cat Enter a second string: dog The comparison between string 1 and string 2 is: -1
Docs: https://cplusplus.com/reference/string/string/compare/
Use the string's compare function to compare
str1
andstr2
and return the result.
string StringRelations( string str1, string str2 )
Enter a first string: cat Enter a second string: dog The relation between string 1 and string 2 is: cat < dog
Docs: https://cplusplus.com/reference/string/string/operators/
Use the relational operators < and > to return "[str1] < [str2]" or "[str1] > [str2]" or "[str1] == [str2]".
string InsertString( string original, string insert_me, int position )
Enter first string: banphone Enter string to insert: ana Enter position where to insert it: 3 The string is now: "bananaphone"
Docs: https://cplusplus.com/reference/string/string/insert/
Use the string's insert function to insert the
insert_me
string into theoriginal
string at theposition
given. Return the result.
string EraseFromString( string original, int position, int length )
Enter string: I can't even comprehend Enter position to begin erasing from: 12 Enter length of characters to remove: 11 The string is now: "I can't even"
Docs: https://cplusplus.com/reference/string/string/erase/
Use the string's erase function to remove text from the
original
string, starting at theposition
given, and going forlength
amount of characters. Return the result.
string ReplaceInString( string original, string insert_me, int position, int length )
Enter a first string: good work Enter a second string: bad Enter starting position of string 1 to replace: 0 Enter length of characters to remove: 4 The string is now: "bad work"
Docs: https://cplusplus.com/reference/string/string/replace/
Use the string's replace function to replace text in the
original
string atposition
, going for thelength
given, replacing the text with theinsert_me
string. Return the result.
- Turning in your work
Go to the GitLab webpage, locate the file you want to update, and click the blue "Edit" button, then click "Edit single file". Paste in your changes and click the "Commit changes" at the bottom of the page. Copy the URL to the file or unit folder and paste it in as your submission on the Canvas assignment.
UNIT 08: File I/O
ποΈ Reading - File I/O (U08.READ)
- Output streams
In C++ we've been using
cout
to stream information to the console window in our programs. Usingcout
requires including theiostream
library.cout << "Hello, " << location << "!" << endl;
Writing out to a text file works in a very similar way. We will need to include the
fstream
library in order to get access to theofstream
(output-file-stream) object. Streaming out to a file works in the same way as withcout
, except that we need to declare aofstream
variable and use it t open a text file.#include <iostream> // Console streams #include <fstream> // File streams using namespace std; int main() { // Console output cout << "Hello, world!" << endl; // File output ofstream outputFile( "file.txt" ); outputFile << "Hello, world!" << endl; outputFile.close(); }
You can use the output stream operator
<<
to continue chaining together different items -endl=s, string literals in double quotes, variable values, etc. just like with your =cout
statements.Once the file is closed, you will see the file on your computer, usually the same directory as your .cpp files.
- Different file types…
- Any file type that is a plaintext file can be built as well - .html files, .csv files, heck, even .cpp files. However, generally if you wanted to write a program to output a different file type, you'd use a library to properly convert the data.
Outputting html data:
#include <fstream> using namespace std; int main() { ofstream outputFile( "page.html" ); outputFile << "<body>" << endl; outputFile << "<h1>This is a webpage</h1>" << endl; outputFile << "<p>Hello, world!</p>" << endl; outputFile << "</body>" << endl; outputFile.close(); }
Outputting csv data:
#include <fstream> using namespace std; int main() { ofstream outputFile( "spreadsheet.csv" ); outputFile << "COLUMN1,COLUMN2,COLUMN3" << endl; outputFile << "cell1,cell2,cell3" << endl; // row 1 outputFile << "cell1,cell2,cell3" << endl; // row 2 outputFile << "cell1,cell2,cell3" << endl; // row 3 outputFile.close(); }
- Input streams
File input streams work just line console input streams. You will need to create a
ifstream
(input-file-stream) object and open a file, and then you can read in the contents of that file. Files to be read should generally be placed in the same path as your .cpp file, though the working directory on your system may vary.#include <fstream> // File streams #include <string> // Strings using namespace std; int main() { string data1, data2; // File input ifstream inputFile( "file.txt" ); inputFile >> data1; // Read one word inputFile.ignore(); // Clear buffer getline( inputFile, data2 ); // Read one line inputFile.close(); }
Just like with using
cin
, you can use the input stream operator(>>)
and thegetline()
function with the file streams to get text. You will also need one or more variable to store the text read in.- Reading an entire file
- Reading chunks of data:
- Let's say you have a file full of data to read in. For this example, the file will be a list of numbers that we want to add together. The file might look something like….
Data.txt:
9 15 16 0 10 13 5 16 1 9 2 17 3 3 8
In our program, we want to read all the numbers, but to do this, we need to use a loop and read in one number at a time. We can keep a running total variable to keep adding data to the sum as we go. We can use a loop to continue reading while it is successful, using this as the condition:
input >> readNumber
. This will stop the loop once there's nothing else to read, and it updates thereadNumber
variable with the input each cycle.ifstream input( "data.txt" ); int sum = 0; // Sum variable int readNumber; // Buffer to store what we read in // Keep reading while it's possible while ( input >> readNumber ) { sum += readNumber; // Add on to the sum // Output what we did cout << "Read number " << readNumber << ",\t sum is now " << sum << endl; } cout << "FINAL SUM: " << sum << endl;
The output of this program would look like this:
Read number 9, sum is now 9 Read number 15, sum is now 24 (... etc ...) Read number 3, sum is now 119 Read number 8, sum is now 127 FINAL SUM: 127
- Reading lines of data:
- In other cases, maybe you're reading in text data from a file
and want to read in a full line at a time. We can use
a while loop with the
getline()
function as well to make sure we read each line of a text file:
ifstream input( "story.txt" ); string line; while ( getline( input, line ) ) { cout << line << endl; }
The output of this program would look like this:
CHAPTER I. Down the Rabbit-Hole Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, "and what is the use of a book," thought Alice "without pictures or conversations?"
- Reading an entire file
- Saving and loading data
- Parsing files
Reading in data from a file is one thing, but making sense of what was read in is another. Are you storing saved data from the last session of the program? Are you trying to parse data to crunch? How do you read that data in logically?
First, if your program is going to be saving output that will need to be read in and made sense of later on, how do you organize the data that's output? It's up to you to make sure to structure the output save data in a consistent and readable way…
SAVEGAME RachelsGame LEVEL 5 GOLD 1000 LOCATION RegnierCenter
If every save file from the program is formatted in the same way, then when reading the file we can make assumptions…
- First word: "SAVEGAME" - not important (human readable)
- Second word: Save game name - store in
gameFileName
- Third word: "LEVEL" - not important (human readable)
- Fourth word: Player's level - store in
level
…And so on. This could work, but we could also take advantage of those human-readable labels that were added into the file.
- Read
firstWord
. - If
firstWord
is "SAVEGAME", then read the next word intogameFileName
. - Else if
firstWord
is "LEVEL", then read the next word intolevel
.
So, let's say we have our four variables for a save game:
Name Data type gameFileName
string
level
int
gold
int
location
string
When we go to save our game file, it would be a simple output like this:
// Save the game ofstream output( "save.txt" ); output << "SAVEGAME " << gameFileName << endl; output << "LEVEL " << level << endl; output << "GOLD " << gold << endl; output << "LOCATION " << location << endl;
Giving us a save file like:
SAVEGAME MyGame LEVEL 1 GOLD 10 LOCATION OCB
Then to read it, we could approach it in a couple of different ways. If we assume that the file will always have exactly four lines of data saved and will always be in the same order, we could read it like:
// Load the game string buffer; ifstream input( "save.txt" ); input >> buffer; // ignore SAVEGAME input >> gameFileName; input >> buffer; // ignore LEVEL input >> level; input >> buffer; // ignore GOLD input >> gold; input >> buffer; // ignore LOCATION input >> location;
Or, if we weren't sure that order these would show up in, we could store the first item read into
buffer
each time, and based on what that label was ("SAVEGAME", "LEVEL", etc.) we would know what to read next…string buffer; ifstream input( "save.txt" ); while ( input >> buffer ) { if ( buffer == "SAVEGAME" ) input >> gameFileName; else if ( buffer == "LEVEL" ) input >> level; else if ( buffer == "GOLD" ) input >> gold; else if ( buffer == "LOCATION" ) input >> location; }
If we stepped through this,
buffer
is always going to store one of the data labels, because after buffer is read, we immediately read the second item in the line of text. Once the second item is read, the next thing to be read will be the next label.
- Parsing files
- What library is required in order to use file I/O in C++?
- What data type is used to create a file that inputs (reads in) text from an outside file?
- What data type is used to create a file that outputs (writes out) text to an outside file?
- How do you write out the string literal "Hello world" to an output file?
- How do you write out the value of a variable to an output file?
- How do you read in one word from an input file?
- How do you read in one line from an input file?
π Concept Intro - File I/O (U08.CIN)
π§βπ¬ Lab - File I/O (U08.LAB)
What we're gonna do:
- Read text in from text files using
ifstream
- Write text out to text files using
ofstream
- IDE help: Look at the "C++ projects - Integrated Development Environments" section under the Reference part of this textbook.
- Practice programs
Program documentation is inside the source files.
Practice Location Starter code practice 1: save file u08_FileIO/practice1_savefile/
grade.cpp practice 2: load single word u08_FileIO/practice2_loadsingle/
load1.cpp practice 3: load single line u08_FileIO/practice3_loadline/
load2.cpp practice 4: read all lines u08_FileIO/practice4_readitall/
loadall.cpp practice 5: save and load data u08_FileIO/practice5_saveload/
saveload.cpp
- Graded program 1: Calculate Raise
Example program output:
1. Run AUTOMATED TESTS 2. Run PROGRAMS >> 2 Enter starting salary: $100000 Enter raise per year (as decimal): 0.05 Enter the amount of years to compute: 4 RESULT: 121550.00 Check results.txt for additional information
Example file output:
Starting salary: $100000 Year: 1, Salary: $105000 Year: 2, Salary: $110250 Year: 3, Salary: $115762 Year: 4, Salary: $121551
This program calculates an increase in salary over time based on some percent. Within the
raise.cpp
file you'll see the StudentCode function:int StudentCode( float starting_salary, float raise_per_year, int years ) { // TODO: Create an ofstream object named `output`, open "results.txt". // TODO: Create float called `updated_salary`. Initialize it to the `starting_salary` amount. float updated_salary = 0; // TODO: Write "Starting salary:" and the `starting_salary` to the `output` file. // TODO: Use a loop, you need to create a counter variable that goes from 1 to `years`. // Within the loop, calculate the updated salary with // `updated_salary = updated_salary + ( updated_salary * raise_per_year );` // Use `output` to display the year (counter) and the `updated_salary` each iteration. // TODO: Return the `updated_salary` as the result. return updated_salary; }
Notice that this function takes in three variables that we'll be using:
starting_salary
raise_per_year
years
We'll be calculating the update and writing the result to our output file. Do the following:
- Create an
ofstream
object namedoutput
. - Open the "results.txt" file.
updated_salary
has already been declared and initialized to 0.- Write "Starting salary:" and the
starting_salary
to theoutput
file. - Use a for loop that goes from
counter = 1
toyears
. With the loop:- Update the salary:
updated_salary = updated_salary + ( updated_salary * raise_per_year );
- Output the current information (
counter
andupdated_salary
) to theoutput
file.
- Update the salary:
- After the loop is over, return the
updated_salary
.
When the program is run the details will be calculated and written to an output file. Check the "results.txt" file on your computer after running the program to make sure its output looks like the example above.
- Graded program 2: Get line from file
Example program output:
Enter filename: lyricsB.txt Enter line number: 3 RESULT: I still make a mistake or two
Example input file:
I finally made it through med school Somehow I made it through I'm just an intern I still make a mistake or two
Within the getword.cpp file you'll see the starter code:
string StudentCode( string filename, int line_number ) { // TODO: Create a `counter` int variable, initialize it to 0. // TODO: Create ifstream object named `input`, try to open the `filename`. // TODO: Check for an input fail. Display error message and return "" on failure. // TODO: Load in lines from the `input` file until you hit the // "n-th" line (given by `line_number`). Return the line loaded in here. // TODO: Return "" if nothing was returned during the file read. return ""; }
This function has two parameter variables we'll be using:
filename
line_number
A lyricsB.txt file is located within the folder, which we will be reading from. Do the following:
- Create an input file stream (
ifstream
) object. - Use the
open
function, passing in thefilename
variable instead of a hard-coded string. - Call the input's
fail
function to see if opening the file failed. Display an error message andreturn "";
on failure. - You'll probably want to create a string variable at this point to load data into.
- Using a loop, read in lines from the input file until you hit line #
line_number
. (You'll probably want to create a counter variable of some sort to keep track of how many times the file has been read.) - At the end of the function return the string loaded in.
- Turning in your work
Go to the GitLab webpage, locate the file you want to update, and click the blue "Edit" button, then click "Edit single file". Paste in your changes and click the "Commit changes" at the bottom of the page. Copy the URL to the file or unit folder and paste it in as your submission on the Canvas assignment.
WEEK 10 - MAR 25
UNIT 09: Pointers
ποΈ Reading - Pointers (U09.READ)
- Memory addresses
When we declare a variable, what we're actually doing is telling the computer to set aside some memory (in RAM) to hold some information. Depending on what data type we declare, a different amount of memory will need to be reserved for that variable.
Data type Size boolean 1 byte character 1 byte integer 4 bytes float 4 bytes double 8 bytes A bit is the smallest unit, storing just 0 or 1. A byte is a set of 8 bits. With a byte, we can store numbers from 0 to 255, for an unsigned number (only 0 and positive numbers, no negatives).
Minimum value, 0
(Decimal value = \(128 \cdot 0 + 64 \cdot 0 + 32 \cdot 0 + 8 \cdot 0 + 4 \cdot 0 + 2 \cdot 0 + 1 \cdot 0\))
place 128 64 32 16 8 4 2 1 value 0 0 0 0 0 0 0 0 Maximum value, 255
(Decimal value = \(128 \cdot 1 + 64 \cdot 1 + 32 \cdot 1 + 8 \cdot 1 + 4 \cdot 1 + 2 \cdot 1 + 1 \cdot 1\))
place 128 64 32 16 8 4 2 1 value 1 1 1 1 1 1 1 1 A
char
only needs one byte to store a single letter because we represent letters with the ASCII or UTF8 codes 65 - 90 for upper-case, and 97 - 122 for lower-case.A B C D E F G H I J K L M 65 66 67 68 69 70 71 72 73 74 75 76 77 N O P Q R S T U V W X Y Z 78 79 80 81 82 83 84 85 86 87 88 89 90 a b c d e f g h i j k l m 97 98 99 100 101 102 103 104 105 106 107 108 109 n o p q r s t u v w x y z 110 111 112 113 114 115 116 117 118 119 120 121 122 Any of these numbers can be stored with 8 bits:
A = 65…
(Decimal value = \(128 \cdot 0 + 64 \cdot 1 + 32 \cdot 0 + 8 \cdot 0 + 4 \cdot 0 + 2 \cdot 0 + 1 \cdot 1\))
place 128 64 32 16 8 4 2 1 value 0 1 0 0 0 0 0 1 z = 122…
(Decimal value = \(128 \cdot 0 + 64 \cdot 1 + 32 \cdot 1 + 8 \cdot 1 + 4 \cdot 0 + 2 \cdot 1 + 1 \cdot 0\))
place 128 64 32 16 8 4 2 1 value 0 1 1 1 1 0 1 0 So when we declare a variable, the computer finds an available space in memory and reserves the appropriate amount of bytes in memory. For example, our char could be assigned the memory address
0xabc008
in memory, and its value being stored would look like this:…007 …008 …009 …00a …00b …00c …00d …00e …00f …010 … 0 1 1 1 1 0 1 0 … (…007 and …010 are spaces in memory taken by something else)
We can view the addresses of variables in our program by using the address-of operator
&
. Note that we have used the ampersand symbol before to declare pass-by-reference parameters, but this is a different symbol used in a different context.#include <iostream> using namespace std; int main() { int number1 = 10; int number2 = 20; cout << &number1 << "\t" << &number2 << endl; return 0; }
Running the program, it would display the memory addresses for these two variables. Notice that they're 4 bytes apart in memory (one is at …70 and one is at …74):
0x7ffd3a24cc70 0x7ffd3a24cc74
Each time we run the program, we will get different memory addresses, since the operating system reclaims that memory when the program ends, and gives us new memory spaces to allocate next time we run the program.
0x7ffe0e708a80 0x7ffe0e708a84
When we declare an array of integers of size \(n\), the program asks for \(n \times 4\) bytes of memory to work with. The two variables above didn't have to be side-by-side in memory; they just happened to be because they were declared close together. With an array, however, all elements of the array will be contiguous (side-by-side) in memory.
Here we have an array of integers:
int arr[3]; for ( int i = 0; i < 3; i++ ) { cout << &arr[i] << "\t"; }
And the output:
0x7ffd09a130c0 0x7ffd09a130c4 0x7ffd09a130c8
Because the elements of an array must be contiguous in memory, we cannot resize a normal array. After our array is declared, chances are the memory addresses right after it will be put to use elseware on the computer and will be unavailable to our program and our array.
But, after we learn about pointers, we will learn how we can dynamically allocate as much memory as we need at any time during our program's execution - giving us the ability to "resize" arrays by allocating space for a new array, copying the data over to the larger chunk of memory, and deallocating the old chunk of memory from the smaller array.
- Pointers
- Creating pointer variables
We can declare special variables that store memory addresses rather than storing an int or float or char value. These variables are called pointers.
We can declare a pointer like this:
int* ptrNumber;
Or like this:int * ptrNumber;
Or like this:int *ptrNumber;
But note that doing this declares one pointer and several integers:
int * ptrNumber, notAPointer1, notAPointer2;
To avoid confusion, \underline{declare multiple pointers on separate lines}.If we declare a pointer as an
int*
type, then it will only be able to point to the addresses of integer variables, and likewise for any other data type.Context: Safety with pointers!
Remember how variables in C++ store garbage in them initially? The same is true with pointers - it will store a garbage memory address. This can cause problems if we try to work with a pointer while it's storing garbage.
To play it safe, any pointer that is not currently in use should be initialized to
NULL
ornullptr
.Declaring a pointer and initializing it to
nullptr
:#include <iostream> using namespace std; int main() { int * ptr = nullptr; return 0; }
- Assigning pointers to addresses
Once we have a pointer, we can point it to the address of any variable with a matching data type. To do this, we have to use the address-of operator to access the variable's address - this is what gets stored as the pointer's value.
- Assigning an address during declaration:
int * ptr = &somevariable;
- Assigning an address after declaration:
ptr = &somevariable;
After assigning an address to a pointer, if we
cout
the pointer it will display the memory address of the pointed-to variable - just like if we had usedcout
to display the address-of that variable.// Shows the same address cout << ptr << endl; cout << &somevariable;
Here's a simple program that has an integer
var
with a value of 10, and a pointerptr
that points tovar
's address.#include <iostream> using namespace std; int main() { int * ptr; int var = 10; ptr = &var; cout << "var address: " << &var << endl; cout << "ptr address: " << &ptr << endl; cout << "var value: " << var << endl; cout << "ptr value: " << ptr << endl; return 0; }
The output would look like:
var address: 0x7ffc3d6028b0 ptr address: 0x7ffc3d6028b4 var value: 10 ptr value: 0x7ffc3d6028b0
Some things to note:
var
stores its data at its address0x7ffc3d6028b0
.ptr
stores its data at its address0x7ffc3d6028b4
.var
's value is 10, since it's an integer.ptr
's value is the address ofvar
, since it's a pointer-to-an-integer.
- Assigning an address during declaration:
- Dereferencing pointers to get values
Once the pointer is pointing to the address of a variable, we can access that pointed-to variable's value by dereferencing our pointer. This gives us the ability to read the value stored at that memory address, or overwrite the value stored at that memory address.
We dereference the pointer by prefixing the pointer's name with a
*
- again, another symbol being reused but in a different context.In this code, we point
ptr
to the address ofvar
. Outputtingptr
will give usvar
's address, and outputting*ptr
(ptr dereferenced) will give us the value stored atvar
's address.int * ptr; int var = 10; ptr = &var; cout << "ptr value: " << ptr << endl; cout << "ptr dereferenced: " << *ptr << endl;
Output:
ptr value: 0x7ffd21de775c ptr dereferenced: 10
Then, we could also overwrite the value stored at
var
's address by again dereferencing the pointer and writing an assignment statement:*ptr = 20;
When we output the value that
var
is storing, either directly throughvar
or through theptr
, we can see that the value ofvar
has been overwritten:cout << "var value: " << var << endl; cout << "*ptr value: " << *ptr << endl;
var value: 20 *ptr value: 20
- Creating pointer variables
- Pointer cheat sheet
Declare a pointer int* ptrInt;
float *ptrFloat;
Assign pointer to address ptrInt = &intVar;
ptrFloat = &floatVar;
Dereference a pointer cout << *ptrChar;
*ptrInt = 100;
Assign to nullptr float *ptrFloat = nullptr;
ptrChar = nullptr;
- Invalid memory access with pointers
Remember that when you declare a variable in C++, it will initially store garbage. This is true of pointers as well. When you declare a pointer without initializing it to
nullptr
, it will be storing random garbage that it will try to interpret as a memory address. If you dereference a pointer that is pointing to garbage, your program is going to run into a problem - a segmentation fault.A pointer pointing to garbage:
int main() { int * bob; cout << *bob << endl; return 0; }
Program output:
Segmentation fault (core dumped)
- How do we check whether memory address is valid?
In short, we can't check if an address stored in a pointer is valid. This is why we initialize our pointers to
nullptr
when they're not in use - we knownullptr
means that the pointer is not pointing to anything.
- Review questions:
- Given the variable declaration:
int num = 10;
What kind of memory is the num variable stored in? - Given the variable declaration:
int* num = new int;
What kind of memory is the num variable stored in? - How do you declare a pointer?
- How do you access the address of a variable?
- How do you assign the address of a variable to a pointer?
- How do you dereference a pointer to display the value of the address it's pointing to?
- How do you dereference a pointer to store a new value in the memory block pointed to?
- When a pointer is not currently in use, it should be initialized to…
- Given the variable declaration:
π Concept Intro - Pointers (U09.CIN)
π§βπ¬ Lab - Pointers (09.LAB)
What we're gonna do:
- Look at variables' memory addresses
- Create pointer variables that store memory addresses
- Dereference pointers to access the address location
IDE help: Look at the "C++ projects - Integrated Development Environments" section under the Reference part of this textbook.
Topic | Visual Studio | Code::Blocks | Xcode | VSCode |
---|---|---|---|---|
Creating a project | π₯ Create a new project in Visual Studio | π₯ Creating a new project in Code::Blocks | π₯ Creating a project in Xcode | π₯ Creating a new project in VSCode |
Creating a new file | π₯ Add new files in Visual Studio | π₯ Add new files in Code::Blocks | π Xcode documentation - Managing files | π₯ Add new files in VSCode |
Adding an existing file(s) | π₯ Add existing files in Visual Studio | π₯ Add existing files in Code::Blocks | π Xcode documentation - Managing files | π₯ Add existing files in VSCode |
Building and running the program | π₯ Build in Visual Studio π₯ Run in Visual Studio | π₯ Build and run in Code::Blocks | π₯ Build and run in Xcode | π₯ Build and run in VSCode |
- Practice:
practice1_sizes
Example program output:
integer size: 4 float size: 4 double size: 8 bool size: 1 char size: 1 string size: 32
Create a project:
- Start by creating a new project in your IDE. Put your project in the
practice1_sizes
folder. - After creating a project, add a new file to your project, named "sizes.cpp".
In your .cpp file, start by creating your basic empty C++ program:
int main() { return 0; }
We're going to be using
cout
andstring
for this program, so make sure to have#include <iostream>
,#include <string>
, andusing namespace std;
at the top of the file.Getting the size of each data type:
We're going to use the
sizeof()
function to see the size of different data types. We can call this function like:sizeof( int )
and it will return a number, in bytes:cout << "integer size: " << sizeof( int ) << endl;
Finish writing the program by doing the same for the following data types:
- float
- double
- bool
- char
- string
- Start by creating a new project in your IDE. Put your project in the
- Practice:
practice2_addresses
Example program output:
int1's address is: 0x7ffe831367c4 int2's address is: 0x7ffe831367c8 int3's address is: 0x7ffe831367cc int4's address is: 0x7ffe831367d0 int5's address is: 0x7ffe831367d4 bool1's address is: 0x7ffe831367bf bool2's address is: 0x7ffe831367c0 bool3's address is: 0x7ffe831367c1 bool4's address is: 0x7ffe831367c2 bool5's address is: 0x7ffe831367c3
(Note: each time your run the program the addresses will be different!)
Create a project:
- Start by creating a new project in your IDE. Put your project in the
practice2_addresses
folder. - After creating a project, add a new file to your project, named "addresses.cpp".
In your .cpp file, start by creating your basic empty C++ program:
int main() { return 0; }
We're going to be using
cout
for this program, so make sure to have#include <iostream>
andusing namespace std;
at the top of the file.Getting variable addresses:
First, declare a set of integer variables, you don't have to assign them a value. For example:
int1
,int2
,int3
,int4
, andint5
.Second, declare a set of boolean variables. These also don't need to be initialized:
bool1
,bool2
,bool3
,bool4
,bool5
.We're going to display the address of each of these variables using the address-of operator
&
, like this:cout << "int1's address is: " << &int1 << endl;
Do this for all of your int variables and bool variables. Once you run the program, we can see the memory addresses, which are written in hexadecimal notation.
Integers will be 4-bytes apart in memory, and booleans will be 1-byte apart in memory.
- Start by creating a new project in your IDE. Put your project in the
- Practice:
practice3_pointers
Example program output:
studentA address: 0x7ffdccb9e170, value: Luna studentB address: 0x7ffdccb9e190, value: Kabe studentC address: 0x7ffdccb9e1b0, value: Korra ptrStudent is now pointing to: 0 ptrStudent is now pointing to address: 0x7ffdccb9e170 ptrStudent is now pointing to address: 0x7ffdccb9e190 ptrStudent is now pointing to address: 0x7ffdccb9e1b0
Create a project:
- Start by creating a new project in your IDE. Put your project in the
practice3_pointers
folder. - After creating a project, add a new file to your project, named "pointers.cpp".
In your .cpp file, start by creating your basic empty C++ program:
int main() { return 0; }
We're going to be using
cout
andstring
for this program, so make sure to have#include <iostream>
,#include <string>
, andusing namespace std;
at the top of the file.Working with pointer variables:
First, we're going to set up three strings to hold student names, such as:
Variable type Variable name Variable value string studentA "Luna" string studentB "Kabe" string studentC "Korra" Next, we're going to display each variable's address and current value. When we prefix a variable's name with the address-of operator
&
we get its address. If we just use the variable's name, we get the value it's storing as usual:cout << "studentA address: " << &studentA << ", value: " << studentA << endl; cout << "studentB address: " << &studentB << ", value: " << studentB << endl; cout << "studentC address: " << &studentC << ", value: " << studentC << endl;
Next we're going to create a string pointer and for safety we're going to initialize it to
nullptr
. We do this becausenullptr
is basically 0, and we can tell that "0" is an invalid memory address, so it basically marks the pointer as "do not use!!" until it has a valid memory address.A standard variable declaration looks like:
TYPE NAME = VALUE;
A pointer variable declaration looks like:
TYPE* NAME = VALUE;
So in this case, we're going to declare a string pointer variable named ptrStudent and initialize it to nullptr. Then, we're going to display what address our pointer is pointing to:
string* ptrStudent = nullptr; cout << "ptrStudent is now pointing to: " << ptrStudent << endl;
If we run the program right now, it will just show:
studentA address: 0x7ffdccb9e170, value: Luna studentB address: 0x7ffdccb9e190, value: Kabe studentC address: 0x7ffdccb9e1b0, value: Korra ptrStudent is now pointing to: 0
Next, we'll assign the pointer to each string variable's address. Any time we use
cout
on theptrStudent
on its own, it will retrieve the address that the pointer is pointing to.To point a pointer to a variable's address, we use the form:
POINTER = &VARIABLE;
So to point it to the first student:
ptrStudent = &studentA; cout << "ptrStudent is now pointing to address: " << ptrStudent << endl;
Do this for studentB and studentC as well, and your program output should be similar to the example given above (except the addresses will always be different).
- Start by creating a new project in your IDE. Put your project in the
- Practice:
practice4_dereferencing
Example program output:
ORIGINAL TABLE studentA address: 0x7ffc63090040, value: Luna studentB address: 0x7ffc63090060, value: Kabe studentC address: 0x7ffc63090080, value: Korra ptrStudent is pointing to address: 0 ptrStudent is now pointing to address: 0x7ffc63090040 CURRENT VALUE: Luna Enter a new name: Katara ptrStudent is now pointing to address: 0x7ffc63090060 CURRENT VALUE: Kabe Enter a new name: Aang ptrStudent is now pointing to address: 0x7ffc63090080 CURRENT VALUE: Korra Enter a new name: Sokka UPDATED TABLE studentA address: 0x7ffc63090040, value: Katara studentB address: 0x7ffc63090060, value: Aang studentC address: 0x7ffc63090080, value: Sokka
Copy a project:
If you would like, you can copy your folder for the
practice3_pointers
part and rename it topractice4_dereferencing
instead of having to make a new project. (Make sure that your .vcxproj (Visual Studio) / .cbp (Code::Blocks) project is inside that folder!)If you make a new project, we're still starting from the code written in part 3, so copy your program code from there and we'll continue.
Dereferencing pointers:
In the previous version of the program we assign our
ptrStudent
to the address of each student variable and display the address. We are going to add on after these lines. Locate the first part like this:ptrStudent = &studentA; cout << "ptrStudent is now pointing to address: " << ptrStudent << endl;
After the cout statement, display another message saying "Please enter a new name:".
Afterwards, we're going to get input from the keyboard and store it in the student variable indirectly - we're going to do it via the pointer. To do this, we need to dereference the pointer by using the dereference operator:
*
. We use the asterisk for different types of operators, but when it comes before a variable name, it is the dereference operator.cout << "Enter a new name: "; getline( cin, *ptrStudent );
This will get the user's input and store the value to the address that
ptrStudent
is pointing to.Do this after
ptrStudent = &studentB;
andptrStudent = &studentC;
as well.Finally, we want to display the updated list of variables afterwards so we can see our changes:
cout << endl << endl << "UPDATED TABLE" << endl; cout << "studentA address: " << &studentA << ", value: " << studentA << endl; cout << "studentB address: " << &studentB << ", value: " << studentB << endl; cout << "studentC address: " << &studentC << ", value: " << studentC << endl; cout << endl;
- Graded program: VIP Student
Example program output:
Enter ID of VIP student: 1 RESULT: Hikaru
Open a project:
The
graded_program
folder contains two subfolders:Project_VisualStudio2022
andProject_CodeBlocks
. If one of these is your IDE, open the project folder inside the appropriate one. Open the VisualStudioSolution.sln file or the CodeBlocksProject.cbp file. If you're using Xcode or VScode, I think you can just open thegraded_program
folder to get started.This program just contains one file: vip.cpp. We'll be working in the StudentCode function.
string StudentCode( int vip ) { string student1 = "Hikaru"; string student2 = "Umi"; string student3 = "Fuu"; string* ptrVip = nullptr; // TODO: Point `ptrVip` to one of the players' addresses based on // whether `vip` is 1, 2, or 3. // TODO: If `ptrVip` is still pointing to nullptr, return "UNKNOWN". // Otherwise, return `*ptrVip` to dereference the pointer and return // the name it is pointing to. }
This function contains 3 student variables:
student1
,student2
, andstudent3
. It also contains aptrVip
pointer variable that is currently initialized tonullptr
. This function takes inint vip
, the student # who is VIP, and returns astring
, which will be the name of that student - or "UNKNOWN" if it's an invalid index.Assigning ptrVip to an address:
Under the first TODO comment use a set of if/else if statements to assign
ptrVip
to an address…Value of vip
parameterAddress to point ptrVip
to1 student1's address 2 student2's address 3 student3's address (If you're unsure how to do this, I'd suggest looking at the practice programming assignments.)
Returning a student name or UNKNOWN:
Under the second TODO comment, use an if/else statement. If
ptrVip
is pointing tonullptr
, then return the string literal"UNKNOWN"
. Otherwise, dereference theptrVip
pointer as the item to be returned.All automated tests should pass once finished:
[PASS] TEST 1, StudentCode(1) = Hikaru [PASS] TEST 2, StudentCode(2) = Umi [PASS] TEST 3, StudentCode(3) = Fuu [PASS] TEST 4, StudentCode(4) = UNKNOWN
- Turning in your work
Go to the GitLab webpage, locate the folder for the unit you're working in. Upload all .h and .cpp files (as applicable). If you would like, you can also back up your project file: .vcxproj for Visual Studio or .cbp for Code::Blocks, but these are not required.
ποΈ Nonogram - Nonogram E (U09.EXE.N)
How to play: Each cell in the grid of squares can either have a X (or blank) or be filled in. The filled in boxes create the pixels of an image. Each row and each column have one or more numbers. This specifies how many pixels are in that row/column. The number given is how many unbroken pixels will show up together. Two numbers separated by a space, e.g., "1 1", will have at least one empty spot between them.
Hint: Burger
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3946482
UNIT 10: Arrays and vectors
ποΈ Reading - Arrays and vectors (U10.READ)
- For loops
A for loop is another type of loop that combines three steps into one line of code. A for loop looks like this:
for ( INIT_CODE ; CONDITION ; UPDATE_ACTION ) { }
- INIT CODE: This is some code that is executed before the loop starts. This is usually where a counter variable is declared.
- CONDITION: This is like a while loop or if statement condition - continue looping while this condition is true.
- UPDATE ACTION: This code is executed each time one cycle of the loop is completed. Usually this code adds 1 to the counter variable.
Technically you can use the for loop in a lot of ways, but the most common use is something like this:
for ( int i = 0; i < 10; i++ ) { // Do something 10 times cout << i << "\t"; }
For loops are especially useful for anything that we need to do \(x\) amount of times. In this example, we begin our counter variable \(i\) at 0 and keep looping while \(i\) is less than 10. If we
cout
\(i\) each time, we will get this:0 1 2 3 4 5 6 7 8 9
We can have the loop increment by 1's or 2's or any other number, or we could subtract by 1's or 2's, or multiply by 1's or 2's, or anything else.
Example: Count down from 10 to 1 by 1 each time.
// 10 9 8 7 6 5 4 3 2 1 for ( int i = 10; i > 0; i-- ) { cout << i << "\t"; }
Example: Count from 0 to 14 by 2's:
// 0 2 4 6 8 10 12 14 for ( int i = 0; i >= 14; i += 2 ) { cout << i << "\t"; }
Example: Count from 1 to 100 by doubling the number each time:
// 1 2 4 8 16 32 64 for ( int i = 0; i >= 100; i *= 2 ) { cout << i << "\t"; }
For loops will come in even more handy later on once we get to arrays.
- Nesting code blocks
If statements, While loops, and For loops all have code blocks: They contain internal code, denoted by the opening and closing curly braces
{ }
. Within any block of code you can continue adding code. You can add if statements in if statements in if statements, or loops in loops in loops.- Nesting if statements
Nesting an if statement within another if statement basically gives you a boolean expression with an AND.
Example:
if ( wantsBeer ) { if ( age >= 21 ) { GiveBeer(); } }
Equivalent logic:
if ( wantsBeer && age >= 21 ) { GiveBeer(); }
Whether you implement some logic with nested if statements, or with if / else if statements using AND operations is a matter of design preference- in some cases, one might be cleaner than the other, but not always.
If you have a statement like this:
if ( conditionA ) { if ( conditionB ) { Operation1(); } else { Operation2(); } }
It could be equivalently described like this:
if ( conditionA && conditionB ) { Operation1(); } else if ( conditionA && !conditionB ) { Operation2(); }
- Nesting loops
Let's say we have one loop that runs 3 times, and another loop that runs 5 times. If we nest the loops - have one loop within another - then we will end up with an operation that occurs 15 times - \(3 \times 5\).
Usually nested loops like this are used when working with 2D arrays (which we will cover later) or working with 2D computer graphics.
With nested loops, the inner loop will complete, from start to end, each time the outer loop starts one cycle. If the outer loop were to go from A to C, and the inner loop went from 1 to 5, the result would be like this:
A 1 2 3 4 5 B 1 2 3 4 5 C 1 2 3 4 5
Example:
for ( int outer = 0; outer < 3; outer++ ) { for ( int inner = 0; inner < 5; inner++ ) { cout << "OUTER: " << outer << "\t INNER: " << inner << endl; } }
Output:
OUTER: 0 INNER: 0 OUTER: 0 INNER: 1 OUTER: 0 INNER: 2 OUTER: 0 INNER: 3 OUTER: 0 INNER: 4 OUTER: 1 INNER: 0 OUTER: 1 INNER: 1 OUTER: 1 INNER: 2 OUTER: 1 INNER: 3 OUTER: 1 INNER: 4 OUTER: 2 INNER: 0 OUTER: 2 INNER: 1 OUTER: 2 INNER: 2 OUTER: 2 INNER: 3 OUTER: 2 INNER: 4
See how each line, the INNER number goes up each time and the OUTER number does NOT go up each time… it only goes up once the INNER loop has completed.
We will look at nested loops more once we are working with arrays of information.
- Nesting if statements
- Arrays
- Array basics
- What are arrays?
In C++, arrays are a built-in way to store a series of similar data all under one name.
Before now, if we wanted to store a list of students in a class (or similar kind of data), we would have to declare a bunch of separate variables and write the same code over and over to manage it:
string student1, student2, student3; cout << "Enter student 1 name: "; cin >> student1; cout << "Enter student 2 name: "; cin >> student2; cout << "Enter student 3 name: "; cin >> student3;
This would quickly become unmanagable if you were writing a program with tens, hundreds, or thousands of students stored in it. Instead, we can make use of arrays to store a series of related data together.
string students[100]; for ( int i = 0; i < 100; i++ ) { cout << "Enter student " << (i+1) << " name: "; cin >> student[i]; }
Arrays allow us to operate on the same name (e.g.,
student
), but addressing different elements of the array with an index number. This way, we can write code to act on the data once, just modifying that index to work with different pieces of data.
Example: student array of size 4:
Element Rai Anuj Rebekah Rose Index 0 1 2 3 Each item in the array has a corresponding index marking its position in the list, with 0 being the first value. If an array is of size \(n\), then the valid indices are 0 through \(n-1\).
An element is the information stored at that index position, which is essentially a single variable in an array of variables.
- Declaring arrays:
In C++, we declare an array similarly to how we declare a variable, except that we need to specify an array size during declaration:
// An array of size 100 string students[100];
Or, if we already have data to put into it, we can initialize it with an initializer list. Then the array will be sized at however many items you give it.
// An array of size 4 string students[] = {"Rai", "Anuj", "Rebekah", "Rose"};
- Array size - named constant:
- Array sizes must be defined
during its declaration and the array cannot be resized during the program's execution. Because the array size can't change, and because we may need to know the size of the array throughout the program, we will generally use a named constant to store the size of the array.
const int MAX_STUDENTS = 100; string students[MAX_STUDENTS];
- Element count - variable:
Because an array's size cannot be changed after its declaration, it often becomes necessary to overshoot the amount of spaces we need in the array so that we always have enough room for our data. Perhaps a school's classrooms range from 20 to 70 seats, so we would want to declare the array of the biggest size so that we don't run out of space. Because of this, not all spaces in the array may be taken up at any given time.
C++ doesn't have a function to directly get the amount of elements in an array, so generally when declaring an array we need to also have an associated variable to track how many items we've stored in the array.
const int MAX_STUDENTS = 100; // total array size int studentCount = 0; // how many elements string students[MAX_STUDENTS]; // array declaration students[0] = "Rai"; // setting up first student studentCount++; // adding 1 to student count
- Array data types:
Arrays can be declared with any data type. To the computer, we are just declaring \(n\) amount of some variable, and it takes care of putting all the \(n\) variables back-to-back in memory.
- Valid indices:
As stated earlier, if an array is of size \(n\), then its valid indices are 0 to \(n-1\). In most computer languages, arrays and lists start at index 0 and go up from there, meaning to count for items we have "0, 1, 2, 3".
Context: * A common source of program crashes is *going outside the bounds of an array! This happens if you try to access an invalid index, such as
student[-1]
orstudent[100]
(for an array of size 100; valid indices are 0-99).
- Accessing indices with variables
Since the array index is always an integer, we could use a variable to determine which item in an array to modify - such as asking the user which item they want to edit.
const int TOTAL_ITEMS = 10; float prices[TOTAL_ITEMS]; cout << "Edit which item? (0-9): "; int itemIndex; cin >> itemIndex; cout << "Enter price for item: "; cin >> prices[ itemIndex ];
- Using for loops with arrays
Using for loops is the most common way to iterate over all the data in an array, setting data or accessing data. Have an array of size \(n\)? We want to iterate from
i
= 0 to \(n-1\), going up by 1 each time.- Initializing an array:
- When we declare a variable without initializing it, it will be full of garbage data. This is the same for arrays, and sometimes you want to clean up an array prior to using it.
const int TOTAL_ITEMS = 10; float prices[TOTAL_ITEMS]; // Initialize all prices to 0. for ( int i = 0; i < TOTAL_ITEMS; i++ ) { prices[i] = 0; }
- Asking the user to enter all elements:
We can iterate over all the items in an array and have the user enter information for each element by using a loop. Since the first index is 0, we sometimes just add +1 to the index for the user's benefit, since people generally aren't used to lists starting at 0.
const int TOTAL_ITEMS = 10; float prices[TOTAL_ITEMS]; // Initialize all prices to 0. for ( int i = 0; i < TOTAL_ITEMS; i++ ) { cout << "Enter price for item " << (i+1) << ": "; cin >> prices[i]; }
- Displaying all items in an array:
We can display all the elements of an array by using a loop as well, though we usually don't want to show all elements of the array - usually just the items we know we're storing data in. Recall that we usually will have an extra integer variable to count how many items have actually been stored in the array, which is different from the total array size.
const int MAX_STUDENTS = 100; int studentCount = 0; string students[MAX_STUDENTS]; // ...Let's say 20 students were added here... // Iterate from index 0 to 19, since we have stored // 20 students so far. for ( int i = 0; i < studentCount; i++ ) { cout << "Student " << (i+1) << " is " << students[i] << endl; }
You can also use a range-based for loop in versions of C++ from 2011 or later:
for ( auto & student : students ) { cout << student << endl; }
- Using multiple ("parallel") arrays
Let's say we're writing a simple restaurant program where we need a list of dishes and their prices together. Later on, we will write our own data type using structs and classes to keep these items together. But for now, we would implement this relationship by keeping track of two separate arrays with the data we need.
const int MAX_DISHES = 20; int dishCount = 0; // Information about a dish string dishNames[MAX_DISHES]; float dishPrices[MAX_DISHES]; bool dishVegetarian[MAX_DISHES]; // ... Let's say we created some dishes here... // Display the menu cout << "What would you like to order?" << endl; for ( int i = 0; i < dishCount; i++ ) { cout << i << ". " << dishNames[i] << " (" << dishPrices[i] << " dollars) "; if ( dishVegetarian[i] ) cout << "Veg"; cout << endl; } // Get the index of dish they want int whichDish; cout << "Selection: "; cin >> whichDish;
- Arrays as arguments
they could potentially take up a lot of memory. Because of this, passing an array as a pass-by-value parameter would be inefficient - remember that pass-by-value means that the parameter is copied from the caller argument.
C++ automatically passes arrays around as pass-by-reference instead. You don't have to inclue the
&
symbol in your parameter list for an array, it just happens! But - keep in mind that any problems with pass-by-reference also apply to arrays. If you want to pass an array to a function but you don't want the data changed, then you would need to mark that array parameter as const.void DisplayAllItems( const string arr[], int size ) { for ( int i = 0; i < size; i++ ) { cout << arr[i] << endl; } }
When using an array as a parameter, you don't have to hard-code a size to it. You can leave the square brackets empty (but you DO need square brackets to show that it's an array!) and then pass any array (with matching data type) to the function. However, you will also want to have an int parameter to pass the size of the array as well.
- Array management
Since arrays require quite a bit of management to work with, you could implement some basic functions to do this management, instead of having to re-write the same code over and over. For example…
- Clear array:
- Sets all elements of this string array to an empty string and
resets the
elementCount
to 0 afterwards.
void Clear( string arr[], int & elementCount ) { for ( int i = 0; i < elementCount; i++ ) { arr[i] = ""; } elementCount = 0; }
- Display all elements:
Shows all the elements of an array.
void Display( const string arr[], int elementCount ) { for ( int i = 0; i < elementCount; i++ ) { cout << i << "\t" << arr[i] << endl; } }
- Add new element to array:
Often in our programs we will only set up one item at a time (perhaps when selected from a menu). This means we need to get the data for the array and figure out where in the array it will go.
void AddItem( string arr[], int & elementCount ) { cout << "Enter new element: "; cin >> arr[ elementCount ]; elementCount++; }
For an array,
elementCount
starts at 0 when the array is empty. This also happens to be the index where we will insert our first element - at 0.Element Index 0 1 2 3 Once we add our first element, our
elementCount
will be 1, and the next index to insert data at will also be 1.Element Cats Index 0 1 2 3 Then,
elementCount
will be 2, and the next index to insert at will be 2.Element Cats Dogs Index 0 1 2 3 Because of this, the
elementCount
variable both tells us how many items have been stored in the array and what is the next index to store new information at.
- Deleting an element from an array
Generally, when using an array to store data, we want to avoid gaps in the array, like this:
Element "A" "B" "" "C" "" "D" Index 0 1 2 3 4 5 Because of these gaps, it makes it more difficult to add items to the list (have to search the array for an empty spot before adding a new item - that's time consuming, process-wise). We usually design our data storage in arrays so that everything is contiguous, starting from 0, leaving all the empty space at the end of the array:
Element "A" "B" "C" "D" "" "" Index 0 1 2 3 4 5 Let's say we have data stored in the array above, but want to delete
"B"
. We could set it to an empty string, but that would leave us with a gap:Element "A" "B""C" "D" "" "" Index 0 12 3 4 5 We would want to do a shift-left operation to move
"C"
to 1 and"D"
to 2, giving us:Element "A" "C" "D" "" "" "" Index 0 1 2 3 4 5 In code, it would look like:
void DeleteItem( int deleteIndex, string arr[], int & elementCount ) { // Shift left for ( int i = deleteIndex; i < elementCount-1; i++ ) { arr[i] = arr[i+1]; } elementCount--; }
- Inserting an element into an array
Sometimes we want to insert some data in between other items, such as if we wanted to maintain a sorted order or were ranking the data in the array.
Let's say we want to insert
"C"
before the"D"
in this array:Element "A" "B" "D" "E" "" "" Index 0 1 2 3 4 5 This would be at index 2, but if we just put the
"C"
at index 2, then we would overwrite"D"
- we don't want to lose data!What we're going to have to do is move 2 to 3, but we don't want to overwrite
"E"
either, so we move 3 to 4. But the order we do this matters - we need to start at the end of the list and shift everything until 2 right by one, to get this array:Element "A" "B" "" "D" "E" "" Index 0 1 2 3 4 5 Then we could add our new data in the position we want.
In code, it would look like this:
void InsertItem( string newData, int insertIndex, string arr[], int & elementCount ) { // Shift right for ( int i = elementCount-1; i >= insertIndex; i-- ) { arr[i] = arr[i-1]; } // Insert new item arr[ insertIndex ] = newData; elementCount++; }
- Multidimensional arrays
We can also declare multidimensional arrays, such as 2D or 3D arrays. As with a 1D array, there is just one data type that all the elements share.
string spreadsheet[32][32]; // rows and columns int vertices[4][4][4]; // x, y, z
Let's say we wanted to turn a day planner into a program. Perhaps we originally stored the day plan like this:
Day Time Task Monday 8:00 Work meeting with Bob Monday 13:00 Project review Tuesday 10:00 Customer meeting Tuesday 12:00 Crying in car Wednesady 14:00 Sprint Retrospective We can convert this into a 2D array of strings (the "task"), with one dimension being for "day of the week" and the other dimension being for "hour of the day"…
int DAYS_OF_WEEK = 7; int HOURS_IN_DAY = 24; string todo[ DAYS_OF_WEEK ][ HOURS_IN_DAY ];
We could ask the user what day they want to set a task for, and if they type "Sunday" that could translate to 0, and "Saturday" could translate to 6 (or however you want to organize your week)…
Sunday Monday Tuesday Wednesday Thursday Friday Saturday 0 1 2 3 4 5 6 We could ask them next for what hour the task is at, and that can map to the second index: "0" for midnight, "8" for 8 am, "13" for 1 pm, and so on to 23.
With this information, we can get the user's todo task and store it at the appropriate indices:
int day, hour; cout << "Enter the day:" << endl; cout << "0. Sunday 1. Monday 2. Tuesday 3. Wednesday " << "4. Thursday 5. Friday 6. Saturday" << endl; cout << "Day: "; cin >> day; cout << "Enter the hour (0 to 23): "; cin >> hour; cout << "Enter your task: "; cin >> todo[ day ][ hour ];
With the user's week planned out, you could then display it back to the user by using a nested for loop: One loop for the day, one loop for the hour.
cout << "YOUR SCHEDULE" << endl; for ( int day = 0; day < DAYS_OF_WEEK; day++ ) { for ( int hour = 0; hour < HOURS_IN_DAY; hour++ ) { cout << day << ", " << hour << ": " << todo[ day ][ hour ] << endl; } }
Though you'd probably want to do some extra formatting; such as determining that if the day is 0, then write "Sunday" instead of the number "0".
- Dynamic Array
We can use Dynamic Arrays to allocate space for an array at run-time, without having to know or hard-code the array size in our code. To do this, we need to allocate memory on the heap via a pointer.
- Creating a dynamic array
- We don't have to know the size of the array at compile-time, so we can do things like ask the user to enter a size, or otherwise base its size off a variable.
int size; cout << "Enter size: "; cin >> size; string* products = new string[size];
- Setting elements of the array
- We can access elements of the dynamic array with the subscript operator, as before.
However, we won't know the size of the array unless we use the
size
variable, so it'd be better to use a for loop to assign values instead of this example:
products[0] = "Pencil"; products[1] = "Eraser"; products[2] = "Pencil case"; products[3] = "Pencil sharpener"; products[4] = "Ruler";
- Iterating over the array
- Accessing elements of the array and iterating over the array is done the same way as with a traditional array.
for ( unsigned int i = 0; i < size; i++ ) { cout << i << ". "; // Display index cout << products[i] << endl; // Display element at that index }
- Freeing the memory when done
- Before your pointer loses scope we need to make sure to free the space that we allocated:
delete [] products;
- C++ Standard Template Library: Arrays
If we put
#include <array>
at the top of our file, we can use anarray
object instead of a traditional array to store data. They are basically interchangible, ecxept thearray
object gives us access to the.size()
function, making our job slightly easier. However, thearray
still can't be resized.
- Creating an STL array
array<string, 5> products;
- Setting elements of the array
products[0] = "Pencil"; products[1] = "Eraser"; products[2] = "Pencil case"; products[3] = "Pencil sharpener"; products[4] = "Ruler";
- Iterating over the array
for ( unsigned int i = 0; i < products.size(); i++ ) { cout << i << ". "; // Display index cout << products[i] << endl; // Display element at that index }
- C++ Standard Template Library: Vectors
The C++ Standard Template Library contains a special structure called a vector. A vector is a class (something we'll learn about later) and it is implemented on top of a dynamic array (which we will learn about later with pointers). Basically, it's a resizable array and it has functionality to make managing data a bit more managable.
Generally, in Computer Science curriculum, we teach you how to build data structures (structures that store data) like vectors, lists, and other items because it's important to know how they work (thus why we're covering arrays), but for your own projects and in the real world, you would probably use a vector over an array.
- Declaring a vector
- Vectors are a type of templated
object, meaning it can store any data type - you just have to specify what kind of type the vector stores. The format of a vector declaration looks like this:
// Declaring vectors vector<string> students; vector<float> prices;
- Adding data:
- You can add data to a vector by using
its
push_back
function, passing the data to add as the argument:
vector<string> students; students.push_back( "Rai" );
- Getting the size of the vector
- The
size
function will return the amount of elements currently stored in the vector.
cout << "There are " << students.size() << " students" << endl;
- Clearing the vector:
- You can erase all the data in a vector with the
clear
function:
students.clear();
- Accessing elements by index:
- Accessing an element at some index looks just like it does with an array:
cout << "Student: " << students[0] << endl;
- Iterating over a vector:
- You can use a for loop to iterate over all the elements of a vector, similar to an array:
cout << "Students:" << endl; for ( int i = 0; i < students.size(); i++ ) { cout << i << "\t" << students[i] << endl; }
You can also use C++11 style range-based for loop if you don't need the index. It allows you to iterate over all the elements of
students
, using an alias ofstudent
for each element.for ( auto & student : students ) { cout << student << endl; }
- Array basics
- Review questions:
- What are the 3 parts of a for loop's header?
- Do all items in an array need to be the same data type in C++?
- What is an element of an array?
- What is an index?
- The subscript operator is…
- What code would you write to display the item at position 0 in an array?
- What code would you write to display the item at position 2 in an array?
- Given an array of size \(n\), the valid indices of the array are…
- How do you iterate over all elements of an array?
π Unit 10 - Arrays and vectors (U10.CIN)
π§βπ¬ Lab - Arrays and vectors (U10.LAB)
What we're gonna do:
- Practice with for loops
- Practice with C style ("traditional") arrays
- Practice with the C++ STL
array
object - Practice with the C++ STL
vector
object - Practice using pointers to make a dynamic array
- IDE help: Look at the "C++ projects - Integrated Development Environments" section under the Reference part of this textbook.
- Practice:
practice1_for_counting
Example program output:
Enter a low number: 2 Enter a high number: 8 Low to high: 2 3 4 5 6 7 8 High to low: 8 6 4 2 Multiply up: 2 4 8 GOODBYE
Create a project: Create a new project in this assignment's folder and use the add existing item feature of your IDE to add
forloops.cpp
to your project.At the beginning of the program the user is asked for a
low
number and ahigh
number. We will be using these in our for loops.Generic for loop: A for loop comes in this form:
for ( START; CONDITION; UPDATE ) { /* loop body */ }
Counting up with a for loop:
First create a for loop with the following properties:
- The start action is declaring an integer
i
and initializing it to thelow
value. - The condition is to keep looping while
i
is less than or equal to thehigh
value. - The update action is to incremenet
i
each time:i++
.
Within the function body write a cout statement that displays
i
and then a space…for ( ???; ???; ??? ) { cout << i << " "; } cout << endl << endl; // Added for spacing :)
Counting down with a for loop:
Next create a for loop with the following properties:
- The start action is declaring
int i
and initializing it to thehigh
value. - The condition is to keep looping while
i
is greater than or equal to thelow
value. - The update action is to decrement
i
each time:i--
.
The inside of your for loop should be the same as above: display
i
and then a space.
Multiply up with a for loop:
Finally, now we're going to multiply our counter variable by 2 each time in a loop.
Create a loop with the following properties:
- The start action is declaring an integer
i
and initializing it to thelow
value. - The condition is to keep looping while
i
is less than or equal to thehigh
value. - The update action is to multiple
i
by 2 each time and assign it back to thei
variable:i*=2;
- The start action is declaring an integer
- Practice:
practice2_oldArray
Example program output:
Getting input: Enter class #0: CS134 Enter class #1: ASL120 Enter class #2: ENG101 Enter class #3: CS200 Enter class #4: MATH120 Resulting array: 0 = CS134 1 = ASL120 2 = ENG101 3 = CS200 4 = MATH120
Create a project: Create a new project in this assignment's folder and use the add existing item feature of your IDE to add
oldarray.cpp
to your project.In this program we will use the C-style "traditional" array.
C-style traditional arrays:
Traditional array declarations take this form:
TYPE NAME[SIZE];
The size must either be an integer literal or come from a named constant integer.
Course program with a traditional C array:
Because traditional arrays have a fixed size that must be known at compile time, we first need to declare a named constant to store our array's size:
const size_t ARRAY_SIZE = 5;
(Note: a
size_t
type is just an unsigned integer)After we declare a size, we can then declare our traditional array:
string my_classes[ARRAY_SIZE];
Since our array size is 5, the valid indices will be 0, 1, 2, 3, and 4.
We can then iterate over all the elements of the array, asking the user to enter a value for each item. To do this use a for loop with the following properties:
- Begin the counter variable
i
at index 0. - Continue looping while
i
is less thanARRAY_SIZE
. - Increment
i
by 1 each time.
Within the for loop, display the current class # (which is stored in the
i
variable) and ask the user to enter that course. Use acin
statement to read in some text and store it in the array at the current position,my_classes[i]
.cout << "Enter class #" << i << ": "; getline( cin, my_classes[i] );
Afterwards use another for loop (same properties) to display each element's index (represented by
i
) and value (represented bymy_classes[i]
) in a nice format.
- Begin the counter variable
- Practice:
practice3_arrayObject
Example program output:
Getting input: Enter class #0: CS210 Enter class #1: CS211 Enter class #2: MATH120 Enter class #3: ASL120 Enter class #4: ENG101 Resulting array: 0 = CS210 1 = CS211 2 = MATH120 3 = ASL120 4 = ENG101
Create a project: Create a new project in this assignment's folder and use the add existing item feature of your IDE to add
stlarray.cpp
to your project.In this program we will use the
array
class from C++'s Standard Template Library (STL).STL array objects:
STL array declarations take this form:
array<TYPE, SIZE> NAME;
The size must either be an integer literal or come from a named constant integer.
Course program with an STL array object:
We're going to do the same functionality here except with an STL array object instead. You can pretty much copy/paste the previous program and make the following updates.
Declaring the array: Update the array declaration to be an STL array:
array<string, 5> my_classes;
- Array size: the
my_classes.size()
function will be used here to keep track of the array size. - Named constant: You don't need the
ARRAY_SIZE
named constant anymore. - For loops: Update the condition in your for loops to use
my_classes.size()
instead ofARRAY_SIZE
.
Everything else can remain the same.
- Practice:
practice4_dynamicArray
Example program output:
How many classes do you have? 3 Getting input: Enter class #0: CS200 Enter class #1: CS235 Enter class #2: CS250 Resulting array: 0 = CS200 1 = CS235 2 = CS250
Create a project: Create a new project in this assignment's folder and use the add existing item feature of your IDE to add
ptrarray.cpp
to your project.In this program we will look at how to create an array using pointers.
Dynamic arrays:
Dynamic array declarations take this form:
TYPE* NAME = NEW TYPE[SIZE];
Course program with a dynamic array:
We're going to do the same functionality here except with a dynamic array using a pointer instead. You can copy the practice2 or practice3 program to modify here, but make sure to keep the start of the program where it asks the user how many classes they have.
Declaring the array: Update the array declaration to use a pointer and allocate memory:
string* my_classes = new string[ total_classes ];
- Array size: the
total_classes
variable will be used here to keep track of the array size. - For loops: Update the condition in your for loops to use
my_classes
for the size. Deallocating memory: Before the program ends at
return 0;
, make sure to deallocate your memory!delete [] my_classes;
Everything else can remain the same.
- Practice:
practice5_vector
Example program output:
Enter class #0, or STOP to end: CS134 Enter class #1, or STOP to end: CS200 Enter class #2, or STOP to end: CS210 Enter class #3, or STOP to end: STOP Resulting array: 0 = CS134 1 = CS200 2 = CS210
Create a project: Create a new project in this assignment's folder and use the add existing item feature of your IDE to add
stlvector.cpp
to your project.In this program we will use the
vector
class from C++'s Standard Template Library (STL).STL vector objects:
STL vector declarations take this form:
vector<TYPE> NAME;
Course program with an STL vector object:
We're going to do the same functionality here with some small updates. You can use one of the previous programs as a starting point - I'd suggest the STL Array version.
Here are the things to update:
- Create a
string input;
to store user input into. Declaring the vector: Update the array declaration to be a vector instead:
vector<string> my_classes;
- Array size: the
my_classes.size()
function will be used here to keep track of the array size. - While loop: Create a program loop. You can make it
while ( true )
, the loop will stop once the user tells it to. Within the while loop do the following:- Display "Enter class #", then
my_classes.size()
, "or STOP to end:". - Get the user's input, store it in the
input
variable. - If
input
is "STOP", then use thebreak;
command to exit the loop. - Otherwise (else), use the vector's push back function to add the new class:
my_classes.push_back( input );
- Display "Enter class #", then
- After the while loop, use the for loop to display all the items in the
my_classes
vector. Usemy_classes.size()
for the size.
- Create a
- Practice:
practice6_variableindex
Example program output:
MENU 0. Bean Burrito ($1.99) 1. Crunchy Taco ($1.79) 2. Baja Blast ($1.29) What do you want to eat? 2 You chose: Baja Blast, which costs $1.29 GOODBYE
Create a project: Create a new project in this assignment's folder and use the add existing item feature of your IDE to add
shop.cpp
to your project.
Starter code:
For this program we have a
Product
struct that contains astring name
andfloat price
:struct Product { string name; float price; };
This propgram already has a vector of
Product
objects set up:// Set up the data (start with 3 items): vector<Product> product_list(3); product_list[0].name = "Bean Burrito"; product_list[0].price = 1.99; product_list[1].name = "Crunchy Taco"; product_list[1].price = 1.79; product_list[2].name = "Baja Blast"; product_list[2].price = 1.29; // Display the data cout << "MENU" << endl; for ( size_t i = 0; i < product_list.size(); i++ ) { cout << i << ". " << product_list[i].name << " ($" << product_list[i].price << ")" << endl; }
Using a variable to access an element at some index:
Below the for loop there are some TODO comments. Do the following:
- Create an integer named
index
. - Ask the user what they weant to eat. Use a
cin
statement and store their response in theindex
variable. - Display the
name
andprice
of what they chose. Useproduct_list[index].MEMBER
to access each member variable (name and price) in yourcout
statement.
- Create an integer named
- Graded program: GPA Calculator
Example program output:
Enter a grade (A, B, C, D, or F): A Enter another? (Y/N): Y Enter a grade (A, B, C, D, or F): B Enter another? (Y/N): Y Enter a grade (A, B, C, D, or F): B Enter another? (Y/N): Y Enter a grade (A, B, C, D, or F): C Enter another? (Y/N): Y Enter a grade (A, B, C, D, or F): D Enter another? (Y/N): N RESULT: 2.60
Starter code:
float StudentCode( vector<char> course_grades ) { float total = 0; // TODO: Use a for loop to iterate over all the grades in the `course_grades` vector. // For each one, check if that item is an 'A', 'B', 'C', 'D', or 'F'. // For 'A', add 4.0 to the `total`. For 'B', add 3.0 to the `total`. // For 'C', add 2.0 to the `total`. For 'D', add 1.0 to the `total`. // Otherwise (for 'F'), add 0.0 or don't add anything to the `total`. // Returns the average return total / course_grades.size(); }
Within this function we have a
vector
ofchar
items calledcourse_grades
as the parameter. This will be a sequence of grades like 'A', 'B', 'C', 'D', or 'F'.We also have a
float total = 0;
variable declared.We're goign to create a loop to go over each grade in the vector and add 4.0, 3.0, 2.0, 1.0, or 0.0 to the
total
, and at the end it returns the GPA by dividing that total by the amount of grades there were.Calculating the total:
You will need a for loop here. We are going to iterate over all the elements of the vector
course_grades
. (If you're not sure how to do this, please review the practice programs.)For each grade in
course_grades
, they will have a value of 'A', 'B', 'C', 'D', or 'F', and each of these correspond to a number value. This number value will be added onto thetotal
variable.Letter grade Float value 'A' 4.0 'B' 3.0 'C' 2.0 'D' 1.0 'F' 0.0 Once the function is implemented all the tests should pass.
Passing tests:
[PASS] TEST 1, StudentCode(AABC) = 3.25 [PASS] TEST 2, StudentCode(ABCCCDF) = 2.00
- Turning in your work
Go to the GitLab webpage, locate the folder for the unit you're working on. Upload all worked on files .h and .cpp files. Copy the URL to the file or unit folder and paste it in as your submission on the Canvas assignment.
ποΈ Debugging - Arrays and vectors (U10.EXE.D)
WEEK 11 - APR 1
π» Project 3 (PROJ3)
Project 3
- About
For version 3 of our project we'll be working with vectors to make it so that we can store any amount of recipes and any amount of ingredients in our programs.
We'll also be cleaning things up even more with functions, and you can even add in file I/O to output the recipes to a text file - or save and load recipe data.
- How to be successful at projects
- Your program should always build. Don't continue writing features if you have build errors. WORKING CODE THAT IS INCOMPLETE IS BETTER THAN "COMPLETE" BUT BROKEN CODE THAT DOESN'T EVEN RUN.
- Implement one feature at a time. Test after implementing one feature. Work on small chunks at a time.
- Utilize other code as reference material; code from in class, previous projects, example code from the example code repository (https://gitlab.com/rachels-courses/example-code/-/tree/main/C++?ref_type=heads).
- Research error messages via search engine, look for an explanation of what an error message means. You can even try to ask an AI what an error message means and see if it gives a coherent explanation.
- You can refer to outside sources, just don't plagiarize. You need to learn how to do the programming yourself, but researching is a normal part of "the job".
- If you get stuck, you should seek solutions, such as:
- Asking a tutor - The campus has tutors via the Academic Achievement Center.
- Asking the instructor - You can email me, you can ask me in class, you can schedule a one-on-one time to meet via Zoom or in person.
- Looking at example code from class videos and the example code repository.
- Setup
You'll want to create a new "project3" folder, with a copy of your project2 files inside. We will continue expanding on the recipe program. In your repository, there should be a couple of helper files already: SinghFunctions.h and SinghFunctions.cpp. These functions include code that will Save and Load your recipe data to a data file outside of the program. However, you'll need to implement the Recipe struct.
- Project v3 requirements
- Iteration 1: Adding in the Recipe struct
- Recipe struct
You'll need to implement the
Recipe
struct (in its own Recipe.h file), with the following:- name, a string
- url, a string
- ingredients, a vector of Ingredients (
vector<Ingredient>
).
Note that since Recipe.h uses the Ingredient struct, you will need
#include "Ingredient.h"
at the top of the file.
- Adding a vector of Recipes to main
Within main(), we're going to start using a
vector
ofRecipe
objects instead of storing separate variables for everything.Old:
string rec1_name = "Tiger Butter Candy"; string rec1_url = "https://butterwithasideofbread.com/tiger-butter-fudge/"; Ingredient rec1_ing1, rec1_ing2, rec1_ing3; string rec2_name = "White Chocolate Peppermint Pretzels"; string rec2_url = "https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/"; Ingredient rec2_ing1, rec2_ing2, rec2_ing3;
New:
vector<Recipe> recipes;
Now inside of
main()
instead of calling the oldSetupIngredientsForRecipe1
type functions we will call theLoadRecipes()
function that I implemented in the SinghFunctions file, so make sure to#include "SinghFunctions.h
.To create your Recipe vector and load the recipes in, call the function inside
main()
like this:vector<Recipe> recipes = LoadRecipes();
- Updating program to use Recipe
You'll need to update your program to use the
Recipe
class now. This means updating your Functions that are taking in separate pieces of information, like recipe name, url, ingredient 1, ingredient 2, ingredient 3, and instead just passing in one Recipe. For example:Old:
void SetupIngredientsForRecipe1( Ingredient& a, Ingredient& b, Ingredient& c ); void DisplayRecipe( string name, string url, float batches, Ingredient& a, Ingredient& b, Ingredient& c );
New:
void DisplayRecipe( Recipe recipe );
We are going to remove the Setup function in favor of the function
LoadRecipes
that I wrote to read in a recipe-data.txt file. This function is in the SinghFunctions files so make sure to have#include "SinghFunctions.h"
in your file that has main().For now, my starter recipes will be loaded in, but later on you can add your recipes as well. Also, since each
Recipe
has a vector ofIngredient
objects, now each Recipe can have any amount of ingredients.Work on converting your program to use the Recipe object to clean it up before starting on the next part.
Summary:
- Create a
Recipe
struct - Create a
Recipe
object variable inmain()
- Update the program to use the
Recipe
struct- Update DisplayRecipe to take a
Recipe
item - Don't need the
SetupIngredientsForRecipe
functions anymore
- Update DisplayRecipe to take a
- Use the
LoadRecipes
function to load the recipes in from recipe-data.txt - this goes at the BEGINNING of the program. Use the
SaveRecipes
function to save the recipes to recipe-data.txt - this goes at the END of the program.
- Create a
- Recipe struct
- Iteration 2: Cleaning up the program
We're going to clean up the program further as well. We'll do this by creating functions to handle different parts of the program.
Create the following functions:
int GetChoice( int min, int max )
void MainMenu( vector<Recipe>& recipes )
void ViewRecipesMenu( vector<Recipe>& recipes )
The GetChoice function:
- Output return type: Integer, the user's valid input
- Input parameters:
int min
, the minimum valid choiceint max
, the maximum valid choice
Within this function ask the user to enter a number. Create an integer to store the user's choice, use
cin
to get their input.While the user's input is invalid (less than min or greater than max) have the user re-enter their selection.
After the while loop is done, return the user's choice.
--> Where do you want to go? 5 Invalid selection! Try again! --> -2 Invalid selection! Try again! -->
################################################################################ # MAIN MENU # ############# 0. Quit program 1. View recipe 2. Save recipes to text file 3. Add new recipe --> Where do you want to go? 1
The MainMenu function:
- Output return type: void (no return)
- Input parameters:
vector<Recipe>& recipes
, a list of all the recipes in the program
You can move your program loop into this function, including the
bool running = true;
andwhile( running )
code block. This will be our base main menu, which will have the "View recipe" option, but we are also going to add additional options as well.ViewRecipe will call our
ViewRecipesMenu
function (described next).Steps:
- Initialize
running
totrue
. - While
running
is true, do the following:- Display the header "RECIPES".
- Use a for loop to display a list of all recipe names.
- Display the header "MAIN MENU"
- Display options listed in the example output:
- 0. Quit program
- 1. View recipe
- 2. Save recipes to text file
- 3. Add new recipe
- Ask the user where they want to go. Get their input with the
GetChoice
function, store the result in an integer variable. - Use an if statement or switch statement to determine what to do based on their decision:
- Choice was 0, set
running
tofalse
. - Choice was 1, call
ViewRecipesMenu
function, pass in therecipes
variable. - We will work on Choice 2 and Choice 3 later!
- Choice was 0, set
- After the while loop, nothing needs to happen!
The ViewRecipesMenu function:
- Output return type: void (no return)
- Input parameters:
vector<Recipe>& recipes
, a list of all the recipes in the program
For this function we are essentially moving the functionality to display the list of all recipes, getting the user's input on which to show, and how many batches they would like to make. This function will get this data, then call the
DisplayRecipe
function, passing ONE recipe to that function.################################################################################ # VIEW RECIPE # ############### 0. GO BACK 1. Tiger Butter Candy 2. White Chocolate Peppermint Pretzels 3. Pie for breakfast shake --> Which recipe?
Steps:
- Draw the header, "VIEW RECIPE".
- Use a for loop to display each recipe's index (+1) and name.
- Ask the user which recipe to display, use the
GetChoice
function and store it in a variable. - If their choice was 0, you can use
return;
to exit this menu early. - Otherwise, you can get the
index
of the recipe by taking the user's choice minus 1. - Also ask the user how many batches they'd like to make and store it in a float variable.
Call the
DisplayRecipe
function, passing in therecipes
vector, with the appropriate[index]
.
- Iteration 3: Adding new recipes
Now we'll add a new menu to our program so that the user can add new recipes.
The AddNewRecipeMenu function:
- Output return type: void (no return)
- Input parameters:
vector<Recipe>& recipes
, a list of all the recipes in the program
This function will step the user through entering all the information needed for the recipe.
################################################################################ # NEW RECIPE # ############## --> Enter new recipe name: Homemade Cheezits --> Enter URL: none --> How many ingredients? 1 INGREDIENT #1: --> Name: Grated cheese --> Unit of measurement: cups --> Measurement amount: 5 New recipe added. --> Press ENTER to continue
Steps:
- Display header "NEW RECIPE"
- Create a new
Recipe
object namednew_recipe
- Create a new
Ingredient
object namednew_ing
- Ask the user to enter the recipe's name. Store it into
new_recipe.name
. - Ask the user to enter the recipe's URL. Store it into
new_recipe.url
- Create an integer named
total_ings
. - Ask the user how many ingredients there are. Store their answer into
total_ings
. - Create a for loop, iterating from
i
equals 1 tototal_ings
(inclusive). Within the for loop:- Display the ingredient number (
"INGREDIENT #" << i
) - Ask the user to enter the ingredient name. Store this in
new_ing.name
. - Ask the user for the unit of measurement. Store this in
new_ing.unit
. - Ask the user what the amount is. Store this in
new_ing.amount
. - In the
new_recipe.ingredients
, use itspush_back
function, passing innew_ing
.
- Display the ingredient number (
- After the for loop is over, use the
recipes
'push_back
function, passing in thenew_recipe
.
Calling the function:
Within the
MainMenu
function, when the user selects "3. Add new recipe" from the main menu, then call theAddNewRecipeMenu
function, passing in therecipes
vector.
- Iteration 4: Writing out recipes to a text file
Finally, you'll be implementing a function to write out the recipes to a text file. The output file should be nicely formatted, similarly to your program's console output.
The PrintRecipesMenu function:
- Output return type: void (no return)
- Input parameters:
vector<Recipe>& recipes
, a list of all the recipes in the program
################################################################################ # PRINT RECIPES # ################# Enter a filename for your output: recipez.txt File saved. --> Press ENTER to continue
Steps:
- Display header "PRINT RECIPES"
- Ask the user to enter a filename. Store their response in a string variable, such as
filename
. - Create an
ofstream
variable namedoutput
. Open thefilename
given. - Use a for loop to iterate over all the elements of the
recipes
vector. Within the for loop do the following:- Write the recipe's name (
recipes[i].name
) to the output file. - Write the recipe's url to the output file.
- Create another for loop that iterates over all the
recipes[i].ingredients
. Within this for loop:- Output the ingredient's
amount
,unit
, andname
to the text file.
- Output the ingredient's
- Write the recipe's name (
- After the for loop is over, display a message "File saved".
Example file output:
RECIPE 0: Tiger Butter Candy From https://butterwithasideofbread.com/tiger-butter-fudge/ Ingredients: - 11 oz of Vanilla chips - 0.5 cups of Creamy peanut butter - 0.5 cups of Semi-sweet chocolate chips -------------------------------------------------------------------------------- RECIPE 1: White Chocolate Peppermint Pretzels From https://www.twopeasandtheirpod.com/white-chocolate-peppermint-pretzels/ Ingredients: - 11 oz of Vanilla chips - 0.5 cups of Creamy peanut butter - 0.5 cups of Semi-sweet chocolate chips - 35 chips of Pretzel - 12 oz of White chocolate melting wafers - 0.5 cups of Crushed candy canes -------------------------------------------------------------------------------- RECIPE 2: Pie for breakfast shake From https://www.allrecipes.com/recipe/235558/pie-for-breakfast-shake/ Ingredients: - 0.75 Cups of Frozen strawberries - 0.5 Cup of Vanilla coconut milk - 0.5 Cup of Greek yogurt - 1 Tablespoon of Flax seed meal - 1 Tablespoon of Almond butter - 1 Teaspoon of Honey - 0.5 Teaspoon of Vanilla extract -------------------------------------------------------------------------------- RECIPE 3: Homemade Cheezits From none Ingredients: - 5 5 cups of Grated cheese
Calling the function:
Within the
MainMenu
function, when the user selects "2. Save recipes to text file" from the main menu, then call thePrintRecipesMenu
function, passing in therecipes
vector.Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3948052
- Iteration 1: Adding in the Recipe struct
- Project v3 requirements
WEEK 12 - APR 8
UNIT 11: Classes
ποΈ Reading - Classes (U11.READ)
- Introduction to Object Oriented Programming
- Programming paradigms
Programming paradigms (pronounced "pair-uh-dimes") are ways we can classify different programming languages based on features they have available or the style programs are written. Different paradigms have popped up over the life of computers as programming languages grow and evolve.
- Machine code
At the beginning, computers were programmed with machine code, where you work directly with instructions supported by the hardware - for example,
add
,sub
, storing data in registers, and other relatively simple commands.- Procedural Languages
Eventually, those commands were abstracted into higher-level languages, where one command in, say, C, could "translate" to several machine-code instructions. Languages like C, Fortran, Algol, BASIC, and C are known as Procedural Languages, where these programs would describe a procedure to follow and instructions are executed one-at-a-time in a specific order (top-to-bottom, or calling a function and returning).
- Object Oriented Programming
Languages like C supported our basic control flow and using functions, but did not include classes - a way to make more sophisticated data types. A class is a structure that can store its own member variables and member functions. A variable whose data type is from some defined class is known as an object.
There are other programming paradigms, but we are going to focus on Object Oriented Programming (OOP) now since it's a large part of using C++ and other languages like Java, C#, and Python.
- Design ideals
In programming, an object is some sort of structure that stores its own data (variables) and functionality (functions). We try to design our programs as a collection of objects that interact with each other to get some job done.
Designing programs in an OOP style helps us pursue certain design goals:
- Abstraction: Hiding complexity in the design, creating an "interface" for the user, generalizing functionality to a more "digestible" form.
Think of a button on any device: If you open up the device, there's a lot actually going on, but we just see the simple button and don't have to worry about the rest.
- Certain functions are made public that other programmers can use to interface with the object.
- The other programmers don't need to worry about the inner-workings of the object in order to use it.
- The developer of the class can modify how the internals work without breaking the public interface.
- Helps protect the data within the class from being accessed or modified by things it shouldn't.
- Encapsulation: Also goes along with creating an "interface", though in this regard we are encapsulating related pieces together. We can store data (variables) with the functions that operate on that data (functions) all within a class object.
- Loose coupling: Ideally, different objects in a program shouldn't have their functionality tied to other objects too closely; we want to reduce inter-dependence between objects. When objects are more independent from each other, they are loosely coupled.
- High cohesion: When we design our objects, we shouldn't just throw everything and the kitchen sink into one object. To design an object with high cohesion means that everything inside the object belongs in that object. Reduce the clutter.
- Abstraction: Hiding complexity in the design, creating an "interface" for the user, generalizing functionality to a more "digestible" form.
Think of a button on any device: If you open up the device, there's a lot actually going on, but we just see the simple button and don't have to worry about the rest.
- Example: Moving to an OOP design
Let's think about a simple program we can make with just functions and arrays for contrast: A library of the movies a user owns.
For this program, we could start with an array of strings to store movie titles, but we'd have to create new arrays for each additional field to keep track of - year, genre, rating, etc.
string movieTitles[MAX_MOVIES]; string movieRatings[MAX_MOVIES]; string movieGenre[MAX_MOVIES]; int movieYearReleased[MAX_MOVIES];
In addition to our arrays, we need functions to deal with different operations we would want to do on our movie collection…
void AddMovie( string movieTitles[], string movieRatings[], string movieGenre[], int movieYears[], int& savedMovies, const int MAX_MOVIES ); void UpdateMovie( string movieTitles[], string movieRatings[], string movieGenre[], int movieYears[], int& savedMovies );
- Cons of this style:
- We have to add logic in our program to make sure that item \(i\) in
movieTitles
and item \(i\) in =movieRatings will refer to the same movie. There's nothing in C++ that will directly link these things so we have to add the logic ourselves. - Have to keep track of four different arrays and have to pass four different arrays between functions.
- We have to add logic in our program to make sure that item \(i\) in
Instead, we can take this general structure and turn it into an object, like this:
Movie - title
: string - rating
: string - genre
: string - year
: int + Setup( ... )
: void + Update( ... )
: void + Display()
: void The Movie object would store information about the movie and a set of functionality we would do on a movie. During the "Add Movie" feature of the program, we would be calling the
Setup(...)
function of theMovie
object to get its information all set up.In addition to our Movie object, we could also build an object that is the library itself - what data and functionality does our library of movies have?
MovieLibrary - movieList
: Movie[] - totalMovies
: int - MAX_MOVIES
: const int + AddMovie()
: void + UpdateMovie()
: void + ClearMovie()
: void + DisplayAllMovies()
: void + SaveList( path: string )
: void + LoadList( path: string )
: void Our movie library would contain one array - an array of Movie objects - instead of the four separate arrays for each of the movie fields. The library itself would have the Add, Update, Clear, etc. functions and know how to handle that functionality.
Finally, in our
main()
function we would declare aMovieLibrary
variable for our single library - or, we could make an array ofMovieLibrary
objects if the program accomodated multiple users!After initialization, we would have our main menu as usual…
1. Add movie 2. Update movie (etc)
and when a choice is made, we call the appropriate function via our
MovieLibrary
object.Creating the MovieLibrary object:
int main() { // Creating a MovieLibrary object MovieLibrary movieLibrary;
Calling the AddMovie function of MovieLibrary:
if ( choice == 1 ) { // Calling the AddMovie function movieLibrary.AddMovie(); }
When defining the
AddMovie()
function, it could call theSetup()
function for the nextMovie
object in the array…#+BEGIN_SRC cpp :class cpp void MovieLibrary::AddMovie() { movieList[ totalMovies ].Setup(); totalMovies++; }
And the Movie object's Setup() function could handle dealing with the inputs and outputs…
void Movie::Setup() { cout << "Enter a title: ": getline( cin, title ); cout << "Enter a rating: "; getline( cin, rating ); cout << "Enter a genre: "; getline( cin, genre ); cout << "Enter a year: "; cin >> year; }
Here's a diagram of the main program and objects:
- Additional OOP examples
Here are a few more examples of using object oriented design in different types of programs:
- Video game
A video game usually has characters that can move around, a lot of 2D game levels are built out of a grid of tiles.
Anything that gets displayed to the screen will need \((x,y)\) coordinates as well as dimensions like width and height. C++ doesn't have a built-in image object, but there are graphical libraries that provide graphics functionality.
Player - x
: int - y
: int - width
: int - height
: int - image
: Texture + Setup()
: void + Move(...)
: void + BeginJump(...)
: void + BeginAttack(...)
: void + Draw(...)
: void Tile - x
: int - y
: int - width
: int - height
: int - image
: Texture + Setup()
: void + Draw(...)
: void Level - tiles
: Tile[][] - worldWidth
: int - worldHeight
: int + LoadLevel()
: void + DrawLevel()
: void
- College
A college could be separated into multiple different objects, where a
College
might have differentCampuses
(such as KU-Lawrence, KU-Edwards or the different MCCKC campuses), and each campus has an array of differentDepartments
(CSIS, MATH, ENG, etc.), each department has an array ofTeachers
and an array ofCourses
. A course would generally have oneTeacher
and an array ofStudents
.As far as functionality goes, this diagram has only some basic functions, like
SetTeacher
for a course, or =AddStudent=h. The idea is that, anything related to a course would go in the Course object, with each object handling its own little domain.
- Programming paradigms
- Structs
- Structs vs. Classes
Structs in C++ have all the same functionality of a Class, but are generally used design-wise to group a few variables together, maybe some functions, into a simple structure. A class, on the other hand, is usually used for much bigger and more complex objects.
In C++, the only difference between Structs and Classes are default accessibility - if you don't specify the accessibility of your variables/functions within a struct, they are
public
by default. This means that anything in the program can access those variables/functions. For Classes, everything isprivate
by default - only that Class itself can use the variables/functions.
- Declaring a struct
Struct declarations go in header (.h) files. Usually the file name should reflect the name of the struct itself, and the file guard labels should also match.
#ifndef _STRUCTNAME #define _STRUCTNAME struct STRUCTNAME { int var; void Func(); }; #endif
Design-wise, structs should only contain a small amount of data. While structs can contain functions, it is generally better to create a class if you find yourself needing functions.
An example of a small struct would be grouping \(x\) and \(y\) coordinates together in a Coordinate Pair…
struct CoordinatePair { float x, y; };
Sometimes we need to group some basic variables together. Structs are great for this.
struct Rectangle { float left, right, top, bottom; };
- Declaring object variables
Once a struct has been declared in a program, you can then create a variable with that data type. To access the internal variables of the struct, you use the variable's name followed by the dot operator . and then the name of the member variable.
// Declare two variables CoordinatePair point1, point2; cout << "Enter the x y coordinates for the first point: "; cin >> point1.x >> point1.y; cout << "Enter the x y coordinates for the second point: "; cin >> point2.x >> point2.y; float slope = ( point2.y - point1.y ) / ( point2.x - point1.x ); cout << "The slope is: " << slope << endl;
We will have more examples during the section on Classes, since that's mostly what we will be using. Again, structs are useful for combining a small amount of member variables together under one name, usually used for structures for math (coordinates, rectangles, etc.) but more sophisticated objects ought to be created with a class.
- Structs vs. Classes
- Classes
Traditionally, a struct is used to create small objects that join a few variables together. Classes are much more heavily used in C++ and is the back-bone of Object Oriented Programming. There is a lot we can do with classes, but for now we are just going to look at the basics.
A class declaration looks just like a struct declaration except that we use the keyword
class
. Take note that with a struct and class declaration, we must end the closing curly brace with a semi-colon.class Player { public: void SetPosition( int newX, int newY ); void Move(); private: int x, y; };
- Accessibility
We can define our member variables and functions with three different levels of accessibility, dictating where these members can be accessed throughout the program:
- public:
- Any part of the program can access these members. This is usually used for the member functions of a class.
- private:
- These members can only be accessed by the class itself, from within its functions.
- protected:
- Similar to private except that classes that inherit from the class we're defining will also have access to protected members. More on this when we cover inheritance.
- Header and Source files
When we are creating a class, we generally will put the class declaration within its own header file. Header files end with .h or .hpp - I tend to use .hpp since we're using C++ and I like to explicitly state this is a "C++ header"; the .h extension was also used in C. However, the C++ Core Guidelines document says to
NL.27: Use a .cpp suffix for code files and .h for interface files
Reason It's a longstanding convention. But consistency is more important, so if your project uses something else, follow that.
(From https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#reason-451)
Class declaration goes in Rectangle.h (or Rectangle.hpp):
#ifndef _RECTANGLE_H #define _RECTANGLE_H class Rectangle { public: void SetPosition( int newX, int newY ); void SetDimensions( int newWidth, int newHeight ); private: int x, int y, int width, int height; }; #endif
Context: What is #ifndef?
In C++, when we
#include "Rectangle.h"
in a different source file, the compiler essentially copy-pastes the code from the included file into the includer file.Because of this, if multiple files are
#include "Rectangle.h"
-ing (or any other header), the same code in that header gets copied multiple times, making the compiler think you've declared the same class over and over.#ifndef
,#define
, and#endif
are preprocessor commands used by the compiler. We are essentially saying"if-not-defined
_RECTANGLE_H
, define_RECTANGLE_H
, … … end-if.",preventing the compiler from copying the same file twice.
Class function definitions go in Rectangle.cpp:
#include "Rectangle.h" void Rectangle::SetPosition( int newX, int newY ) { x = newX; y = newY; } void Rectangle::SetDimensions( int newWidth, int newHeight ) { width = newWidth; height = newHeight; }
In our source file (.cpp), we need to make sure to include the header that goes with our class so it knows about the class declaration. Then, we can define the member functions here.
Note that when we're defining the functions outside of the class declaration, we must prefix the function name with the class name, followed by the scope resolution operator
::
…void Rectangle::SetPosition( int newX, int newY )
This is the standard way C++ files are organized - for each class we create, we create a header and a source file for it.
- Defining member functions inside the class declaration
It is completely possible to define our member functions inside the class declaration, getting rid of the need for the .cpp file. However, this does end up being treated differently by the compiler - writing our class this way makes the functions inline… Basically, instead of having a separate function that the compiler will mark as "call this", it will copy the contents of the inlined function to the function call, basically replacing the call with the contents of the function.
I haven't written much about how the compiler works since that's a more specialized topic and we don't need to worry about it at this stage of learning C++. This is just here for your own info.
The entire class in Rectangle.h:
#ifndef _RECTANGLE_H #define _RECTANGLE_H class Rectangle { public: void SetPosition( int newX, int newY ) { x = newX; y = newY; } void SetDimensions( int newWidth, int newHeight ) { width = newWidth; height = newHeight; } private: int x, int y, int width, int height; }; #endif
This is also closer to how Java and C# files look, defining all their methods within the class declaration. It also does simplify having to go back and edit functions, not having to keep track of two different places where we have the function declaration and the function definition.
- Should you define functions in the .hpp or the .cpp?
In general, for my courses, you can choose either approach. Starter code I provide may have the .hpp and .cpp files for classes, but when writing your own class you can throw it all in the .hpp file if you'd like.
The main thing is that it's important to be aware of the standard way so that when you're working with other people you understand how things are structured.
- Function vs. Method
A method is a word that means "member function". In Java and C#, the term method is used instead of function, since you physically cannot have functions defined outside of a class in those languages.
I tend to stick with the term "member function", but if I write "method", it means that, whereas a "function" would be a standalone function elseware in the program.
- Getters and Setters
In Object Oriented Programming, we generally want to hide the inner-workings of a class from the outside world (other functions and other classes). If everything were exposed, then other parts of the program could make changes to our class and it could be difficult to track down all those modifying locations (this, in particular, is a nightmare at a job with a large codebase).
We generally write all our member variables as private - accessible only to the class' member functions themseves - and use public member functions to interface with those variables as needed.
For example, in our Rectangle class, we might have a function to set up the entire Rectangle all at once…
void Rectangle::Setup( int newX, int newY, int newWidth, int newHeight ) { x = newX; y = newY; width = newWidth; height = newHeight; }
… or just a couple things at a time …
void Rectangle::SetPosition( int newX, int newY ) { x = newX; y = newY; }
- Setters:
- Or, we might want to just set one member variable's value.
In this case, we write a member function called a setter (aka mutator) that is responsible for setting a member variable's value:
void Rectangle::SetX( int newX ) { x = newX; }
The good thing about having setters instead of directly updating the
x
variable is that we can add error checks in our setter. Say, perhaps, that we don't wantx
to be negative, so we validate the input before changing it…void Rectangle::SetX( int newX ) { if ( newX >= 0 ) { x = newX; } }
If somewhere else in the program tries to set a negative value for the
x
variable, it will just ignore that command. (We could also throw an exception or display an error message or set a default value - it's up to your design.)- Getters:
- Likewise, sometimes we want to access
those member variables to see what values they store. In this case, we write Getter member functions that are responsible for returning a copy of the data (or, in some cases, a reference to it - but that's a design decision).
int Rectangle::GetX() { return x; }
Getters are also handy for formatting output prior to returning it, or doing some other operation before returning something. Let's say we have a member function for a
Student
class, and aGetName
function is going to combine their names and return it together:int Student::GetFullName() { return lastName + ", " + firstName; }
To summarize…
- Setters: Sets the value of a member variable.
Generally, return type is
void
and there is one paramete for the new value.void SetThing( int newValue );
- Getters: Returns the value of a member variable. Generally, return type matches that variable, and there are no parameters. =int GetThing(); =
- Constructors and Destructors
Constructors and Destructors are special types of member functions in a class.
- Constructor:
- Runs automatically as soon as a new object is declared.
- Can declare more than one constructor.
- No return type
- Constructor name must match name of the class.
- Destructor:
- Runs automatically as soon as a new object is destroyed.
- Can only have one destructor.
- No return type
- Destructor name \underline=must= match name of the class, prefixed with a tilde
\~
.
- Example: Text file wrapper
Let's say we're writing a class that works with a text file.
When the object is created, the constructor will open the file and get it ready to write to. With various member functions we can write to that text file as the program is running. Then, when the program ends and the object is destroyed, it will automatically close the text file for us.
Class declaration:
class Logger { public: // constructors Logger( string filename ); Logger(); // destructor ~Logger(); // other method void Write( string text ); private: ofstream m_output; };
We have two constructors: one where we pass in a filename for a file to open, and one where we don't. In the second case, we can use a default file name.
Context: Why "
m_
" with the variable?In some places, it is standard to prefix private member variables with an underscore (
_output
) or (m_output
). I tend to use the latter when writing private member variables of a class. The "m" stands for "member".The constructor definitions could look like this:
Logger::Logger( string filename ) { m_output.open( filename ); } Logger::Logger() { m_output.open( "log.txt" ); }
The
Write
function could be used to write information to that text file, and could be implemented like this:void Logger::Write( string text ) { m_output << text << endl; }
And then the destructor would be used to close up the file at the end:
Logger::~Logger() { m_output.close(); }
Now, we don't have to manually deal with file operations since this class wraps that functionality and deals with it for us.
To use the program, we just declare the object variable:
#include "Logger.hpp" int main() { // At this point, // a constructor is called automatically Logger log( "logfile.txt" ); // Writing to the text file log.Write( "Hello!" ); log.Write( "How are you?" ); // Program ends here. The destructor // is called automatically when the log variable // goes out of scope and is destroyed. return 0; }
It can often be handy to overload our constructors so that we can initialize our objects in several different ways.
- Default Constructors
A default constructor is a constructor with no parameters in it. This will be called when a variable of this class type is declared with no constructor explicitly called.
Usually, a default constructor would be used to initialize variables to default values, and if your class contains pointers, this constructor should initialize those pointers to point to
nullptr
.class MyClass { public: MyClass() // Default constructor { m_value = 0; } private: int m_value; };
When we create a new object of this type like this, the default constructor will be called:
MyClass classVar;
- Parameterized Constructors
Parameterized Constructors take in one or more parameters to help initialize the member variables of the object. We can have 0, one, or multiple parameterized constructors for our class.
class MyClass { public: MyClass() { // Default constructor m_value = 0; } MyClass( int value ) { // Parameterized constructor m_value = value; } // etc };
When we instantiate our object, we can pass in argument(s) in order to call the parameterized version of the constructor:
MyClass classVar( 100 );
If you declare a parameterized constructor but not a default constructor, then the C++ compiler will assume that you don't want an object to be declared with the default constructor. This means, you would only be able to declare the variable with an explicit call to the constructor and with arguments.
If this isn't the desired design, make sure to include a default constructor, even if you just leave it blank.
- Copy Constructors
A copy constructor takes in another object of the same type as its parameter and uses this to copy over members from the parameter to the new object.
class MyClass { public: MyClass() // Default constructor { m_value = 0; } MyClass( int value ) // Parameterized constructor { m_value = value; } MyClass( const MyClass& other ) // Copy constructor { m_value = other.m_value; } private: int m_value; };
In this case, we might already have an object of this type available, and when we are creating a new object, we want to make a copy of the old object:
MyClass classVar( 100 ); MyClass anotherOne( classVar ); // Copy
- Design:
- When a class has multiple member variables, it is up to us to decide which variables get copied over during this operation. There could be some design cases where all information is copied over except certain fields (maybe a unique customerID or a name).
- Default copy constructor:
- If you don't explicitly declare a copy constructor, the C++ compiler will provide one for the class behind-the-scenes. This implicit copy constructor will only do shallow copies.
Ways to copy:
- A Shallow Copy is where values of variables are copied over. This is generally fine for any sort of non-pointer-based variables. If the class contains a pointer that is pointing to some address, the shallow-copy of the pointer will point to the same address.
- A Deep Copy is where values are copied over like with a shallow copy, but also will allocate new memory for a dynamic array (if the class has one) in order to copy over values of the element of the array to the new class copy.
Example of a shallow copy: With the implicit copy constructor, any pointers in the copied version will be pointing to the same address as in the original. If the class contains a dynamic array, both the copy and the original will end up pointing to the same address of the array in memory.
Example of a deep copy: A new block of memory has been allocated for the
int * numArr
. The values from InstanceA'snumArr
would be copied to InstanceB'snumArr
via a for loop during construction.
- Constructor:
- Example program: House Builder
This program allows a user to enter information about multiple rooms in a house and at the end it will output a text file with all the room information.
Example output:
HOUSE BUILDER (A)dd new room or (Q)uit: a Enter room name: livingroom Enter width: 10 Enter length: 20 (A)dd new room or (Q)uit: a Enter room name: kitchen Enter width: 10 Enter length: 15 (A)dd new room or (Q)uit: a Enter room name: bathroom Enter width: 6 Enter length: 10 (A)dd new room or (Q)uit: q Outputted to house.txt
In my design, I have two objects: A
Room
, which contains a roomname
,width
, andlength
, and aHouse
, which contains an array of rooms. In themain()
function, we work directly with the House, and the house takes care of dealing with the Rooms.- Room.h:
#ifndef _ROOM_HPP #define _ROOM_HPP #include <string> using namespace std; class Room { public: void Setup(); string GetName(); int GetWidth(); int GetLength(); int GetArea(); private: string name; int width; int length; }; #endif
We have getter functions for the
name
,width
, andlength
of the room, as well as to get the area. We don't need to store the area because we can calculate it any time we need it.There is also a function
Setup()
that deals with the cins and couts to set up the room's information.- Room.cpp:
#include "Room.hpp" #include <iostream> using namespace std; void Room::Setup() { cout << "Enter room name: "; cin >> name; cout << "Enter width: "; cin >> width; cout << "Enter length: "; cin >> length; } string Room::GetName() { return name; } int Room::GetWidth() { return width; } int Room::GetLength() { return length; } int Room::GetArea() { return width * length; }
- House.h:
#ifndef _HOUSE_HPP #define _HOUSE_HPP #include "Room.hpp" const int MAX_ROOMS = 10; class House { public: House(); ~House(); void AddRoom(); private: Room rooms[MAX_ROOMS]; int roomCount; }; #endif
The House class contains a constructor, which will be used to initialize data automatically. In particular, we want
roomCount
to be set to 0.The destructor will automatically open a text file, output all the rooms' information, and then close the text file when the House object is destroyed at the end of the program.
- House.cpp:
#include "House.hpp" #include <iostream> #include <fstream> using namespace std; House::House() { roomCount = 0; } House::~House() { ofstream output( "house.txt" ); for ( int i = 0; i < roomCount; i++ ) { output << rooms[i].GetName() << "\t" << rooms[i].GetWidth() << "x" << rooms[i].GetLength() << "\t" << "(" << rooms[i].GetArea() << " sqft)" << endl; } output.close(); cout << "Outputted to house.txt" << endl; } void House::AddRoom() { if ( roomCount == MAX_ROOMS ) { cout << "House is full!" << endl << "Cannot fit any more rooms!" << endl; return; // exit this function } rooms[ roomCount ].Setup(); roomCount++; }
- main.cpp:
#include <iostream> using namespace std; #include "House.hpp" int main() { House myHouse; cout << "HOUSE BUILDER" << endl; bool done = false; while ( !done ) { cout << "(A)dd new room or (Q)uit: "; char choice; cin >> choice; if ( toupper(choice) == 'A' ) { myHouse.AddRoom(); } else if ( toupper(choice) == 'Q' ) { done = true; } cout << endl; } return 0; }
This program only deals with one house, but we could have an array of Houses, each with their own separate array of Rooms.
- Accessibility
- Additional class concepts
- Const member methods
When we declare a class' member function as const, we are saying that this function should not ever change any values of any member variables of this class. This can be handy for methods like a Display() where we just want to output member variables but should never change them.
class Coordinates { public: int GetX() const; // Can't change m_x or m_y int GetY() const; // Can't change m_x or m_y void SetX( int val ); void SetY( int val ); private: int m_x, m_y; };
The function definition will also need to have this const marked at the end of the function header as well.
int Coordinates::GetX() const { return m_x; }
- this
Within our class methods, we can explicitly refer to the object we are currently working with as
this
.this
is a pointer, so it is pointing to a memory address. Any member of the class can also be accessed via thethis
pointer:class MyClass { public: void A() { cout << "Hello!" << endl; } void B() { this->A(); cout << this->var << endl; } void C() { A(); cout << var << endl; } private: int var; };
In this example, methods
B()
andC()
do the same thing, butB()
explicitly usesthis
.
- Const member methods
- Review questions:
- True or false: A class can have member variables and functions (methods).
- Class declarations go in what kind of file?
- Class function (method) definitions go in what kind of file?
- A class' public members can be accessed by…
- A class' protected members can be accessed by…
- A class' private members can be accessed by…
- When defining a function that is a member of a class, the function name needs to be prefixed with…
- What does a getter (accessor) function do?
- What does a setter (mutator) function do?
- When does a constructor function run?
- When does a destructor function run?
- The constructor and destructor name must match what?
π Concept Intro - Classes (U11.CIN)
π§βπ¬ Lab - Classes and inheritance (U11.LAB)
What we're gonna do:
- Practice working with classes and inheritance in C++
- IDE help: Look at the "C++ projects - Integrated Development Environments" section under the Reference part of this textbook.
- Practice 1: Basic class (Pet program)
Program requirements are in your code folder as "requirements.md", which can be opened with a text editor, or here: https://gitlab.com/moosadee/courses/-/blob/main/202401_Spring/Course2_CoreCPP/labs/starter_code/u11_Classes/practice1_pet/requirements.md?ref_type=heads
- Practice 2: Class constructor functions (Ingredient program)
Program requirements are in your code folder as "requirements.md", which can be opened with a text editor, or here: https://gitlab.com/moosadee/courses/-/blob/main/202401_Spring/Course2_CoreCPP/labs/starter_code/u11_Classes/practice2_ingredient/requirements.md?ref_type=heads
- Practice 3: Class Get/Set functions (Player program)
Program requirements are in your code folder as "requirements.md", which can be opened with a text editor, or here https://gitlab.com/moosadee/courses/-/blob/main/202401_Spring/Course2_CoreCPP/labs/starter_code/u11_Classes/practice3_getset/requirements.md?ref_type=heads
- Practice 4: Class inheritance
Program requirements are in your code folder as "requirements.md", which can be opened with a text editor, or here: https://gitlab.com/moosadee/courses/-/blob/main/202401_Spring/Course2_CoreCPP/labs/starter_code/u11_Classes/practice4_inheritance/requirements.md?ref_type=heads
- Graded: Employee program
Program requirements are in your code folder as "requirements.md", which can be opened with a text editor, or here: https://gitlab.com/moosadee/courses/-/blob/main/202401_Spring/Course2_CoreCPP/labs/starter_code/u11_Classes/graded_program/requirements.md?ref_type=heads
- Turning in your work
Go to the GitLab webpage, locate the file you want to update, and click the blue "Edit" button, then click "Edit single file". Paste in your changes and click the "Commit changes" at the bottom of the page. Copy the URL to the file or unit folder and paste it in as your submission on the Canvas assignment.
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3918416
ποΈ Nonogram - Nonogram F (U11.EXE.N)
How to play: Each cell in the grid of squares can either have a X (or blank) or be filled in. The filled in boxes create the pixels of an image. Each row and each column have one or more numbers. This specifies how many pixels are in that row/column. The number given is how many unbroken pixels will show up together. Two numbers separated by a space, e.g., "1 1", will have at least one empty spot between them.
Hint: Bunny
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3946483
UNIT 12: Inheritance
ποΈ Reading - Inheritance (U12.READ)
Inheritance is where one class inherits some or all member variables and functions from some parent class. Certain "traits" are passed on, and the child class can have additional member variables and functions defined, making it a more specialized version of the parent class.
- Design ideas
- Reusing functionality
Let's say we're designing an operating system that will store files. We can think about what all files have in common, and we can figure out what is different between different types of files. Any commonality could go in a base class (aka parent class).
So, a generic File class might have contain variables and functions like:
File - m_filename
: string
- m_extension
: string
- m_fileSize
: size_t
- m_creationDate
: DateTime
+ CreateFile(...)
: void
+ RenameFile(...)
: void
+ GetSize()
: size_t
+ GetPath()
: string
Then we could have specialized file classes that inherit from the original File, such as TextFile, ImageFile, SoundFile, and so on. These would inherit all the common attributes of its parent (File), but each would have additional variables and methods that are suited specifically to its own specialization.
- TextFile:
m_textContent
,Print()
- ImageFile:
m_pixels[][]
,Draw()
,EditPixel( x, y )
- SoundFile:
m_audioSample
,m_length
,Play()
,Pause()
,Stop()
- TextFile:
- The iostream and fstream
Part of the ios family. You can see the full library's family tree at http://www.cplusplus.com/reference/ios/
One family we've already been using are our console input/output streams,
cin
andcout
, and our file input/output streams,ifstream
andofstream
. Working with each of these works largely the same way.When we overload the
<<
and>>
stream operators, we use a base type ofistream
andostream
so that our class can handlecin
/cout
ANDifstream
/ofstream
, as well as any other streams in that family tree.
- Inheritance (Is-A) vs. Composition (Has-A)
Another way we think about inheritance is that one class "is-a" type of other class.
Car is-a vehicle:
class Car : public Vehicle { // etc. };
Whereas Composition, where one class contains another class as a member variable object, is known as a "has-a" relationship.
Car has-an engine:
class Car { private: Engine engine; };
When is composition more appropriate than inheritance? This is a design question and it can really depend on how the designer feels about each one.
- Example: Game objects
For example, when writing a game, I find inheritance handy for creating game objects. A BaseObject can contain everything that's in common between all objects (characters, items, tiles, etc.), such as:
Any items that don't animate, don't move, and just sit there in the level could be instantiated as a simple BaseObject and it would be fine.
BaseObject # m_position
: Coordinate
# m_sprite
: Sprite
# m_name
: string
+ Setup(...)
+ SetTexture(...)
+ Update(...)
+ SetPosition(...)
+ Draw(...)
Then, let's say we want to build a 2D game level and each level is made up of a 2D array of tiles. Tiles will be very similar to objects, but maybe we want more information stored in a tile. We could then inherit from the BaseObject…
The Tile class would have all the public and protected members from its parent, plus any new member variables and methods we declare within this class.
Tile Inherits from BaseObject - m_isSolid
: bool
- m_doesDamage
: bool
For the game characters, there would be two different types usually: characters that the players control and characters that the computer controls. Character could be its own base-class as well, implementing anything a character can do, with a Player and NPC (non-player-character) classes inheriting from Character.
Character Inherits from BaseObject # m_speed
: int
# m_direction
: Direction
# m_animFrame
: float
# m_maxFrames
: float
+ Move(...)
+ Animate(...)
Player Inherits from Character - m_score
: int
- m_experience
: int
- m_level
: int
+ HandleKeyboard(...)
+ LevelUp(...)
The Player class would be a specialized type of Character that can be controled via the keyboard (or some other input device), as well as have information that a non-player-character generally has, such as a score or a level.
NPC Inherits from Character - m_difficulty
: int
- m_isFriendly
: bool
+ SetGoal(...)
+ DecideNextAction(...)
Likewise, the NPC class is a specialization of Character as well, but with special functionality and attributes of a character in the game controlled by the computer itself. This could include some form of AI to help the NPC decide how to behave.
Game object family:
With this family of game objects, we could also write functions that work on all types of game objects, such as checking if there's a collision between items, because they all have a common parent.
- Reusing functionality
- Implementing inheritance
In C++ a class can inherit from one or more other classes. Note that Java and C# do not support multiple inheritance directly, if you end up switching to those languages. Design-wise, however, it can be messy to inherit from more than one parent and as an alternative, you might find a composition (has-a) approach a better design.
- Inheriting from one parent
To inherit from one other class in C++, all you need to do is add "
: public OTHERCLASS
" after the "class CLASSNAME
" at the beginning of your class declaration. With a public inheritance (the most common kind), the child class will inherit all public and protected members of the parent class.// File is the parent class File { protected: string name; string extension; size_t filesize; }; // TextDocument is the child class TextDocument : public File { protected: string textContents; /* Also inherits these members from File: string name; string extension; size_t filesize; */ };
Context: The Parent Class is often known as the superclass and the Child Class is often known as the subclass, particularly from the Java perspective.
- Inheriting from multiple parents
You can also have a class inherit from multiple parents, bringing in public/protected members from all parent classes, but again this can muddle your program's design somewhat and is generally pretty uncommon.
class AnimationObject // Parent A { public: void Animate(); protected: int totalFrames; int currentFrame; }; class PhysicsObject // Parent B { public: void Fall(); void Accelerate(); protected: float velocity; float acceleration; }; class PlayerCharacter : public AnimationObject, public PhysicsObject { public: void HandleKeyboard(); protected: string name; };
- Private, Public, and Protected
- Member access
Remember that we can declare our member variables and methods as private and public, but we can also make items protected. Protected members are similar to private, except that protected members will be inherited by child classes - private members do not get inherited.
Access Class' methods Childrens' methods Outside functions public Accessible Accessible Accessible protected Accessible Accessible Not accessible private Accessible Not accessible Not accessible
- Inheritance style
- You can also use public, protected, and private when inheriting other classes.
You probably won't need to ever do a protected or private inheritance.
- public inheritance: Child class inherits public and protected members from the parent.
- protected inheritance: Child class inheirits public and protected members and turns them into protected members.
- private inheritance: Child class inherits public and protected members and turns them into private members.
This could be used if, for some reason, you want a child class to inherit certain members but don't want "grandchildren" to have access to those members as well.
- Function Overriding
When a child class inherits from a parent class, the parent class' public and protected methods are passed down to the child and these functions are still callable for objects of the child type.
If we would like, the child class can also override any methods from the parent. This means that we write a new version of the function with the same return type and parameter list, and when that function is called from the child class, the child class' version will be called instead of the parents'.
Let's say we're writing a quizzer program that will support differnet question types. We can write a base "Question" class with whatever would be in common between all Questions:
class Question { public: Question( string q, string a ) { question = q; answer = a; } void AskQuestion() { cout << question << endl; string playerAnswer; cin >> playerAnswer; if ( playerAnswer == answer ) { cout << "Right!" << endl; } else { cout << "Wrong." << endl; } } protected: string question; string answer; };
We can then inherit from our Question class to make different types of quiz questions: Multiple choice, true/false, and so on. Adding additional functionality means that we might want to rewrite how
AskQuestion()
works - so we can.This also means that everything in our Question family has a similar interface - create a question, set it up, and then call
AskQuestion()
no matter what kind of question it is.class MultipleChoiceQuestion : public Question { public: void DisplayQuestion() { cout << question << endl; for ( int i = 0; i < 4; i++ ) { cout << i << ". " << answerChoices[i] << endl; } int playerAnswer; cin >> playerAnswer; if ( answerChoices[ playerAnswer ] == answer ) { cout << "Right!" << endl; } else { cout << "Wrong." << endl; } } protected: string answerChoices[4]; };
- Calling the parents' version of a method
In some cases, perhaps the parent version of a method has some common functionality we will need no matter what version in the family we're using, but the child versions of the methods add on to that functionality. We can directly call the parent's version of some method from within a child's method by explicitly calling the method with the parent class name and the scope resolution operator ::.
class Lion { public: void Activities() { cout << "Hunt" << endl; cout << "Eat" << endl; cout << "Sleep" << endl; } }; class HouseCat : public Lion { public: void Activities() { Lion::Activities(); cout << "Talk to human" << endl; cout << "Use catbox" << endl; } };
For this example, the HouseCat does everything the Lion does and adds a few activities to the list. We don't have to re-write the same Activities from Lion - we can just call the parent's version of the method directly with
Lion::Activities();
.
- Constructors and Destructors in the family
We often use constructors to initialize member variables for a class, and when a child is inheriting its parents' member variables, we want to make sure we're not forgetting to still initialize those variables.
We can call the parent's constructor from the child's constructor as well, but we do it via the initializer list of a constructor - a little bit of code after the constructor's function header that can be used to initialize variables and call the parent constructor.
class Person { public: Person( string name ) { m_name = name; } protected: string m_name; }; class Student : public Person { public: Student( string name, string major ) : Person( name ) // Calling the parent ctor { m_major = major; } protected: string m_major; };
(Note: "ctor" is short for "constructor")
We can also initialize variables through the initializer list as well:
class Student : public Person { public: Student( string name, string major ) : Person( name ), m_major( major ) { // nothing else to do now! } protected: string m_major; };
- Inheriting from one parent
WEEK 13 - APR 15
UNIT 13: Searching and sorting
ποΈ Reading - Searching and sorting (U13.READ)
- Introduction to searching and sorting
Searching and sorting algorithms are things that we'll study in college, and perhaps see during job interviews, but for the most part in the daily life of an average developer we may not be implementing these algorithms from scratch.
Like data structures, these algorithms have already been implemented and are available in various forms, usually already tested and optimized by someone else, and you can use them in your programs by adding in third party libraries.
I'm just saying this because a some of this functionality of sorting algorithms may not make "intuitive" sense, and I find the code pretty ugly for a lot of these, but you won't have to worry about these in the real world.
- Searching algorithms
When we're working with structures of data - such as an array - we often need to find information stored within. Perhaps we know the element or a piece of data we want to find, but we need to get the positional index of where it's located in the array. This is where our search algorithms come in handy.
- Linear search
Pseudocode:
LinearSearch ( Inputs: array, findme Outputs: index of found item, or -1 if not found ) begin function: for i begins at 0, loop while i < array size, update i++ each loop if array[i] matches findme, return i end for return -1 end function
When we're searching for items in an unsorted linear structure there's not much we can do to speed up the process. We can basically either start at the beginning and move forward checking each item in the structure for what you're looking for.
We begin at the first index 0 and iterate until we hit the last index. Within the loop, if the element at index
i
matches what we're looking for, we return this index.If the loop completes and we haven't returned an index yet that means we've searched the entire structure and have not found the item. In this case, it is not in the structure and we can throw an exception to be dealt with elseware or return something like -1 to symbolize "no valid index".
This search algorithm's growth rate is \(O(n)\) – the more items in the structure, the time linearly increases to search through it. Not much we can do about that, which is why we have different types of data structures that sort data as it is inserted - more on those later on.
Additional documentation: https://en.wikipedia.org/wiki/Linear_search
- Binary search
Pseudocode:
BinarySearch ( Inputs: array, findme Outputs: index of found item, or -1 if not found Note: array MUST BE SORTED ) begin function: left = 0 right = array size - 1 while left <= right: mid = left + ( right - left ) / 2 if ( array[mid] == findme ): return mid else if ( array[mid] < findme): left = mid+1; else if ( array[mid] > findme): right = mid-1; end while return -1 end function
A binary search allows for a faster search - if the array passed in is sorted (otherwise it won't work!). The binary search cuts its search range in half each iteration through the loop, thus giving us a \(log(n)\) growth rate.
Additional documentation: https://en.wikipedia.org/wiki/Binary_search_algorithm
- Linear search
- Sorting algorithms
- Selection sort
Pseudocode:
SelectionSort ( Inputs: array Outputs: void ) begin function: for i begins at 0, loop while i < array size - 1, update i++ each loop: minindex = i for j begins at i+1, loop while j < array size, update j++ each loop: if ( array[j] < array[minindex] ): minindex = j end for if ( minindex != i ): swap( array[i], array[minindex] ) end for end function
Additional documentation: https://en.wikipedia.org/wiki/Selection_sort
- Bubble sort
Pseudocode:
BubbleSort ( Inputs: array Outputs: void ) begin function: for i begins at 0, loop while i < array size - 1, update i++ each loop: for j begins at 0, loop while j < array size - i - 1, update j++ each loop: if ( array[j] > array[j+1] ): swap( array[j], array[j+1] ) end for end for end function
Additional documentation: https://en.wikipedia.org/wiki/Bubble_sort
- Insertion sort
Pseudocode:
InsertionSort ( Inputs: array Outputs: void ) begin function: i = 1 while ( i < array size ): j = i while ( j > 0 and array[j-1] > array[j] ): swap( array[j], array[j-1] ) j--; end while i++; end while end function
Additional documentation: https://en.wikipedia.org/wiki/Insertion_sort
- Quick sort
Pseudocode:
Partition ( Inputs: array, lowindex, highindex Outputs: an index value ) begin function: pivotvalue = array[high] i = low - 1 for j begins at low, loop while j <= high - 1, update j++ each loop: if ( array[j] <= pivotvalue ) then: i++ swap( array[i], array[j] ) end if end for swap( array[i+1], array[high] ) return i+1 end function ------------------------------------------------------ QuickSort_Recursive ( Inputs: array, lowindex, highindex Outputs: void ) begin function: if ( low < high ) then: partitionindex = Partition( array, low, high ) QuickSort_Recursive( array, low, partitionindex - 1 ) QuickSort_Recursive( array, partitionindex + 1, high ) end if end function ------------------------------------------------------ QuickSort ( Inputs: array Outputs: void ) begin function: QuickSort_Recursive( array, 0, array size - 1 ) end function
Additional documentation: https://en.wikipedia.org/wiki/Quicksort
- Merge sort
Pseudocode: (Adapted from https://www.programiz.com/dsa/merge-sort)
MergeParts ( Inputs: array, left, mid, right Outputs: void ) begin function: n1 = mid - left + 1 n2 = right - mid leftarr is a new array rightarr is a new array for i begins at 0, loops while i < n1, updates i++ each loop: leftarr push array[ left + i ] end for for j begins at 0, loops while j < n2, updates j++ each loop: rightarr push array[ mid + 1 + j ] end for i = 0 j = 0 k = left while ( i < n1 and j < n2 ): if ( leftarr[i] <= rightarr[j] ) then: array[k] = leftarr[i] i++ else: array[k] = rightarr[j] j++ end if k++ end while while ( i < n1 ): array[k] = leftarr[i] i++ k++ end while while ( j < n2 ): array[k] = rightarr[j] j++ k++ end while end function ------------------------------------------------------ MergeSort_Recursive ( Inputs: array, left, right Outputs: void ) begin function: if ( left < right ) then: mid = floor( left + right ) / 2 MergeSort_Recursive( array, left, mid ) MergeSort_Recursive( array, mid+1, right ) Merge( array, left, mid, right ) end if end function ------------------------------------------------------ MergeSort ( Inputs: array Outputs: void ) begin function: MergeSort_Recursive( array, 0, array size - 1 ) end function
Additional documentation: https://en.wikipedia.org/wiki/Merge_sort
- Heap sort
Pseudocode: (Adapted from https://en.wikipedia.org/wiki/Heapsort)
LeftChildIndex ( Inputs: index Outputs: where this index's left child is ) begin function: return 2 * index + 1 end function ------------------------------------------------------ RightChildIndex ( Inputs: index Outputs: where this index's right child is ) begin function: return 2 * index + 2 end function ------------------------------------------------------ ParentIndex ( Inputs: index Outputs: where this index's parent is ) begin function: return floor( ( index - 1 ) / 2 ) end function ------------------------------------------------------ SiftDown ( Inputs: array, root, end Outputs: void ) begin function: while ( LeftChildIndex( root ) < end ): child = LeftChildIndex( root ) if ( child + 1 < end and array[child] < array[child+1] ): child++ if ( array[root] < array[child] ) then: swap( array[root], array[child] ) root = child else: return end if end while end function ------------------------------------------------------ Heapify ( Inputs: array, end Outputs: void ) begin function: start = ParentIndexx( end-1 ) + 1 while ( start > 0 ): start-- SiftDown( array, start, end ) end while end function ------------------------------------------------------ HeapSort ( Inputs: array Outputs: void ) begin function: Heapify( array, array size ) end = array size while ( end > 1 ): end-- swap( array[end], array[0] ) SiftDown( array, 0, end ) end while end function
Additional documentation: https://en.wikipedia.org/wiki/Heapsort
- Radix sort
Pseudocode: (Adapted from https://www.geeksforgeeks.org/radix-sort/)
CountSort ( Inputs: array, n, exp Outputs: void ) begin function: output is an int array of size n (create as dynamic array) count is an int array of size 10 count[0] = 0 for i starts at 0, loops while i < n, updates i++ each loop: count[ ( array[i] / exp ) % 10 ]++ end for for i starts at 1, loops while i < 10, updates i++ each loop: count[i] += count[i-1] end for for i starts at n-1, loops while i >= 0, updates i-- each loop: output[ count[ ( array[i] / exp ) % 10 ] - 1 ] = array[i] count[ ( array[i] / exp ) % 10 ]-- end for for i starts at 0, loops while i < n, updates i++ each loop: array[i] = output[i] end for end function ------------------------------------------------------ GetMax ( Inputs: array Outputs: the value of the largest item in the array ) begin function: maxvalue = array[0] for i starts at 1, loops while i < array size, updates i++ each loop: if ( array[i] > maxvalue ): maxvalue = array[i] end for return maxvalue end function ------------------------------------------------------ RadixSort ( Inputs: array Outputs: void ) begin function: maxvalue = GetMax( array ) for exp starts at 1, loop while maxvalue / exp > 0, update exp *= 10 each loop: CountSort( array, array size, exp ) end for end function
Additional documentation: https://en.wikipedia.org/wiki/Radix_sort
- Selection sort
Project 4
Project 4
- About
For this assignment we're going to take the code you have from v3 and wrap it all in a Program class. We will also implement a basic search feature.
Utilize the starter code as a base: https://gitlab.com/moosadee/courses/-/tree/main/202401_Spring/Course2_CoreCPP/projects/starter_code/Project4?ref_type=heads
- How to be successful at projects
- Your program should always build. Don't continue writing features if you have build errors. WORKING CODE THAT IS INCOMPLETE IS BETTER THAN "COMPLETE" BUT BROKEN CODE THAT DOESN'T EVEN RUN.
- Implement one feature at a time. Test after implementing one feature. Work on small chunks at a time.
- Utilize other code as reference material; code from in class, previous projects, example code from the example code repository (https://gitlab.com/rachels-courses/example-code/-/tree/main/C++?ref_type=heads).
- Research error messages via search engine, look for an explanation of what an error message means. You can even try to ask an AI what an error message means and see if it gives a coherent explanation.
- You can refer to outside sources, just don't plagiarize. You need to learn how to do the programming yourself, but researching is a normal part of "the job".
- If you get stuck, you should seek solutions, such as:
- Asking a tutor - The campus has tutors via the Academic Achievement Center.
- Asking the instructor - You can email me, you can ask me in class, you can schedule a one-on-one time to meet via Zoom or in person.
- Looking at example code from class videos and the example code repository.
- Example output
Main menu
################################################################################ # MAIN MENU # ############# 0. Quit program 1. View recipe 2. Save recipes to text file 3. Add new recipe 4. Search for a recipe --> Where do you want to go?
View recipes menu
################################################################################ # VIEW RECIPE # ############### 0. GO BACK 1. Tiger Butter Candy 2. White Chocolate Peppermint Pretzels 3. Pie for breakfast shake --> Which recipe? 1 --> How many batches would you like to make? 2
View single recipe menu
################################################################################ # Tiger Butter Candy # ###################### From https://butterwithasideofbread.com/tiger-butter-fudge/ INGREDIENTS - 11 oz of Vanilla chips - 0.5 cups of Creamy peanut butter - 0.5 cups of Semi-sweet chocolate chips --------------------------------------------------------------------------------
Save recipes to text file menu
################################################################################ # PRINT RECIPES # ################# Enter a filename for your output: output.txt File saved. --> Press ENTER to continue
Add new recipe menu
################################################################################ # NEW RECIPE # ############## --> Enter new recipe name: Choco Cookies --> Enter URL: asdf.com --> How many ingredients? 2 INGREDIENT #1: --> Name: Chocolate, melted --> Unit of measurement: cups --> Measurement amount: 2 INGREDIENT #2: --> Name: Chocolate chips, whole --> Unit of measurement: cups --> Measurement amount: 2 New recipe added. --> Press ENTER to continue
Search for a recipe menu
################################################################################ # SEARCH FOR RECIPE # ##################### Enter part of recipe name to search for: Ch RESULTS 1. White Chocolate Peppermint Pretzels - Ingredients: Vanilla chips, Creamy peanut butter, Semi-sweet chocolate chips, Pretzel, White chocolate melting wafers, Crushed candy canes 3. Choco Cookies - Ingredients: Chocolate, melted, Chocolate chips, whole --> Press ENTER to continue
Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3948052
WEEK 14 - APR 22
UNIT 14: Recursion
https://rachels-courses.gitlab.io/webpage/semester/2024-01/presentations/cs200-unit14-recursion.html
ποΈ Reading - Recursion (U14.READ)
- Examples of recursion in math
Recursion is a manner of solving a problem by breaking it down into smaller pieces - and those smaller pieces are solved in the same way as the big-picture version.
- Summation:
A summation can be broken down into smaller chunks but using the same structure as the original.
Let's say we have \[ \sum_{i=1}^{6} { i } = 1 + 2 + 3 + 4 + 5 + 6 \]
The summation can be redefined recursively:
\[ \sum_{i=1}^{6} { i } = 6 + \sum_{i=1}^{5} { i } \]
The summation from \(i = 1\) to \(6\) is equivalent to whatever the sum is at \(i=6\), plus the sum from \(i = 1\) to \(5\). We can continue this way until we get to a case that we know (e.g., \(\sum_{i=1}^{1} { i }\)).
- \(\sum_{i=1}^{6} { i } = 6 + \sum_{i=1}^{5} { i }\)
- \(\sum_{i=1}^{5} { i } = 5 + \sum_{i=1}^{4} { i }\)
- \(\sum_{i=1}^{4} { i } = 4 + \sum_{i=1}^{3} { i }\)
- \(\sum_{i=1}^{3} { i } = 3 + \sum_{i=1}^{2} { i }\)
- \(\sum_{i=1}^{2} { i } = 2 + \sum_{i=1}^{1} { i }\)
- We know that \(\sum_{i=1}^{1} { i } = 1\), then we move back up to sub out this value.
Recursive problem Finding the solution A. \[\sum^{6}_{i=1} { i } = 6 + \sum_{i=1}^{5} { i }\] But what is \(\sum_{i=1}^{5} { i }\)? \(\downarrow\) K. DONE! \[\sum_{i=1}^{6} { i } = 6 + \sum_{i=1}^{5} { i } = 6 + 15 = 21\] B. \[\sum_{i=1}^{5} { i } = 5 + \sum_{i=1}^{4} { i }\] But what is \(\sum_{i=1}^{4} { i }\)? \(\downarrow\) J. \(\uparrow\) \[\sum_{i=1}^{5} { i } = 5 + \sum_{i=1}^{4} { i } = 5 + 10 = 15\] C. \[\sum_{i=1}^{4} { i } = 4 + \sum_{i=1}^{3} { i }\] But what is \(\sum_{i=1}^{3} { i }\)? \(\downarrow\) I. \(\uparrow\) \[\sum_{i=1}^{4} { i } = 4 + \sum_{i=1}^{3} { i } = 4 + 6 = 10\] D. \[\sum_{i=1}^{3} { i } = 3 + \sum_{i=1}^{2} { i }\] But what is \(\sum_{i=1}^{2} { i }\)? \(\downarrow\) H. \(\uparrow\) \[\sum_{i=1}^{3} { i } = 3 + \sum_{i=1}^{2} { i } = 3 + 3 = 6\] E. \[\sum_{i=1}^{2} { i } = 2 + \sum_{i=1}^{1} { i }\] But what is \(\sum_{i=1}^{1} { i }\)? \(\downarrow\) G. \(\uparrow\) \[\sum_{i=1}^{2} { i } = 2 + \sum_{i=1}^{1} { i } = 2 + 1 = 3\] F. \[\sum_{i=1}^{1} { i } = 1\] \(\uparrow\) Now we start substituting this value, from bottom-up… \(\rightarrow\) \(\uparrow\)
- Factorials:
With a factorial of \(n\), written \(n!\) the formula to solve this is:
\[ n! = n \cdot (n-1) \cdot ... \cdot 3 \cdot 2 \cdot 1 \]
So,
- \(2!\) is \(2 \cdot 1\),
- \(3!\) is \(3 \cdot 2 \cdot 1\),
- \(4!\) is \(4 \cdot 3 \cdot 2 \cdot 1\), and so on.
Additionally, we can break down each of these equations: \(3!\) is equivalent to \(3 \cdot 2!\) \(4!\) is equivalent to \(4 \cdot 3!\) … \(n!\) is equivalent to \(n \cdot (n-1)!\)
Thinking of breaking down the problem here in this way is looking at it recursively.
- Summation:
- Recursion in programming
In programming, we usually approach problems iteratively, using a for-loop or a while-loop:
// Iterative solution int Sum( int n ) { int result = 0; for ( int i = 1; i <= n; i++ ) { result += i; } return result; }
Which solves this summation:
\[ \sum_{i=1}^n {i} \]
But some types of problems lend themselves better to a recursive solution. To be fair, though, many problems are better solved iteratively. So how do we know which method is better?
- Recursion basics
When defining a problem recursively in programming, we need two things:
- A terminating case: A case that ends our recursing. Often, this is some known data, something hard-coded. For example with our summation, the terminating case would be that \[ \sum_{i=1}^1 {i} = 1 \] or for a factorial, \(1! = 1\) and \(0! = 1\).
- A recursive case: A recursive case is what happens
otherwise - if we're not to a solution yet (via the terminating case),
we call the same function again, but with updated arguments. For example:
Factorial( 4 ) = 4 * Factorial( 3 )
Factorial( 3 ) = 3 * Factorial( 2 )
Factorial( 2 ) = 2 * Factorial( 1 )
Factorial( 1 ) = 1
We can solve these basic math operations both iteratively and recursively:
// Iterative solution int FactorialI( int n ) { int result = 1; for ( int i = 1; i <= n; i++ ) { result *= i; } return result; }
// Recursive solution int FactorialR( int n ) { if ( n == 1 || n == 0 ) { return 1; } return n * FactorialR( n-1 ); }
- Breaking down problems into recursive solutions
One of the most challenging parts of recursion, at least for me, is trying to break away from thinking of something in terms of "looping" and figuring out how to think of it "recursively". It's not as natural-feeling, so don't worry if it's confusing at first.
Let's tackle some basic design problems to practice.
- Summation:
- Try to convert the Summation function to be recursive. Think about what the terminating case would be and the recursive case. Use the Factorial function for reference.
int SumI( int n ) { int result = 0; for ( int i = 1; i <= n; i++ ) { result += i; } return result; }
int SumR( int n ) { // Terminating case? // Recursive case? }
- Solution for recursive summation:
int SumR( int n ) { if ( n == 1 ) { return 1; } // Terminating case return n + SumR( n-1 ); // Recursive case }
- Draw a line:
- Now let's make a function that will draw a line of symbols, with a parameter being the length. Iteratively, it could look like this:
void DrawLineI( int amount ) { for ( int i = 0; i < amount; i++ ) { cout << "-"; } }
How would we repeat this behavior recursively? How do we have a "count up" sort of functionality? What would be the terminating case?
We're going to think of it a little differently: The recursive function will only output one "-" before it recurses. Each time it recurses, it draws one more dash…
void DrawLine_Recursive( int amount ) { cout << "-"; // Recursive case DrawLineR( amount ); }
However, we don't have a terminating case… it will continue looping, but it won't go forever like a bad while loop. We will eventually run out of stack space and the program will encounter a stack overflow and end.
So what would the terminating case be? How do we adjust the
amount
each time? Sinceamount
is the one parameter we have, let's have the recursion stop once it is 0. Each time we recurse, we can pass inamount-1
to the next call…void DrawLine_Recursive( int amount ) { cout << "-"; // Terminating case if ( amount == 0 ) { return; } // Recursive case DrawLineR( amount - 1 ); }
- Counting Up:
- How can we write a function that takes a
start
andend
integer, and outputs each number between them (including the start and end)?
Iteratively, it could look like this:
void CountUpI( int start, int end ) { for ( int i = start; i <= end; i++ ) { cout << i << "\t"; } }
Try to fill in this function to build a recursive solution:
void CountUpR( int start, int end ) { }
- Solution for recursive count up:
void CountUpR( int start, int end ) { cout << start << "\t"; // Terminating case if ( start == end ) { return; } // recursive case CountUp_Recursive( start+1, end ); }
- A case for recursion
Although there are a lot of problems we could convert from an iterative solution to a recursive solution, there are some types of problems that really are better suited to recursion.
- Searching a File System
On a harddrive, we generally have files and folders. Folders can contain files, but they will also contain subfolders as well. And subfolders can each contain their own subfolders.
When you don't know the exact layout of the filesystem, how would you even begin to iteratively search for a specific file?
Instead, it is good to think of it recursively. For example, say we're searching for a folder where you store your Recursion homework. We will begin searching at the top-most folder of the computer. The algorithm would then run like…
1. folder = "C:", 2. folder = "work", 3. folder = "C:" Is this "Recursion"? No. Is this "Recursion"? No. Are there subfolders? Yes. Are there subfolders? Yes. Are there subfolders? No. Then, search next subfolder. Then, search first subfolder. Return. 4. folder = "school" 5. folder = "cs210" 6. folder = "school" Is this "Recursion"? No. Is this "Recursion"? No. Are there subfolders? Yes. Are there subfolders? Yes. Are there subfolders? No. Then, search next subfolder. Then, search next subfolder. Return. 7. folder = "cs235" 8. 9. Is this "Recursion"? No. folder = "Recursion" folder = "cs235" Are there subfolders? Yes. Is this "Recursion"? Yes. Return Recursion. Then, search the first subfolder. Return Recursion. 10. folder = "school" 11. folder = "C:" Return Recursion. Return Recursion. For find functionality, terminating cases would be:
- Have we found the item? Return it.
- Are we out of places to search? Return nothing.
And the recursive case would be:
- Has a subfolder? Call Find() on that folder.
- Searching a File System
- Recursion basics
- Review questions:
- Recursion of a means of problem solving that…
- Each recursive function needs at least one … case and at least one … case.
We are designing a recursive function
CountUp( start, end )
…- The function displays start and
CountUp( start+1, end )
- The function returns when start is greater than end.
What is the terminating case?
- The function displays start and
We are designing a recursive function to figure out the result of \(n!\)…
- The result of \(n!\) is equal to \(n\) times \((n-1)!\)
- The result of \(0!\) is 1.
What is the terminating case?
π Concept Intro - Recursion (U14.CIN)
Additional
About
About this book
This "course book" contains the concept notes, assignment documentation, reference material, and other resources, all of which make up the author's Core C++ course. The goal is to be a one-stop location for all the resources you need for this course, and to give you something to keep for reference later on - in other classes, for review before a job interview, or just as a reference manual. I encourage you to write in this book, keep your notes in it, highlight it, and use it as your guide as you work through the course content.
About this course
This is a night class, with a 3 hour class session one night a week. Honestly, I try to design my courses so that you can succeed with the contents whether you are in class or not, so I try to make sure everything important is available to you online (or in this book-thing).
That being said, we do have weekly time scheduled and I have no fixed design for class periods themselves. Class time is whatever you want it to be. I usually treat it as "lab time", but if there's something you'd like to see during class time - let me know! You can also ask me about things like the professional world and what I've learned working as a software developer, or any other area I might have experience in.
Generally, I encourage students to utilize the class time to get the labs/homework done - you've already made time in your schedule for this class, so might as well utilize the time to get classwork done. Your course load will also go by faster if you happen to work in class, where you can ask me questions if you get stuck.
\vspace{0.2cm}
Course-related ideas: Example code for a course topic, example of building a BIG project and how to put it together, "Make a program about [topic]",
\vspace{0.2cm}
Other topics ideas: Working as a software developer, tips for taking university classes, how to use a Linux operating system, Open Source software, independent game development, ethics in software and game design, course and curriculum design, designing education for non-traditional students, volunteering, strategies for dealing with stress and anxiety.
\vspace{0.2cm}
My course design ideals
- I am interested in training you how to be a good software developer, which includes how the language works, designing software and good interfaces, diagnosing and fixing issues and bugs, and so on. I am not interested in making sure you're a cookie-cutter "best-student", which usually just translates to "a traditional student with the opportunity to give school 150% of their attention". I've been a non-traditional student, I've had to work full time my entire adult life, I understand that many of my students are also adults with jobs, families, and other responsibilities, and I am not interested in penalizing "non-traditional" students for not being able to make perfect attendance or get everything in by the due date 100% of the time.
- I try to build my courses in a way like a video game - start by tutorializing and easy challenges, and as you get more experience you are faced with harder challenges, but everything's designed to help you build the skills you need to tackle everything.
- I think that education should be free and available to everybody. (But also I need to pay bills so I am fortunate that I get to work as a teacher, which I enjoy doing.)
- All the (good) course content I create is available online for free for anyone to access. (GitLab, my webpage, YouTube). Anything that I think you need to know to be successful will be available in some form online and outside of class; I'm not going to penalize you for not making it to class.
- I want to help you build up your problem solving skills so I may not always answer your assignment questions directly (more in a guided, "here's a hint" way), but I am always here to answer questions and help guide you to where you need to go.
- I miss teaching from home where I could wear sweat pants all day. We should all be able to do what we do while being comfy in sweat pants or whatever.
About the author
I've been in the KC Metro area since I was around 11 years old. I started programming because I was in love with video games, and I spent my free time in my teen years (badly) programming video games. :)
\vspace{0.2cm}
Education: Homeschooled, GED, Associates in Computer Science from MCCKC, Bachelors in Computer Science from UMKC, dropped out of gradschool multiple times (UMKC, MS&T, KU) cuz money/time.
\vspace{0.2cm}
Development Work: Mostly C# (web development) and C++ (software development) professionally, also with PHP, HTML, CSS, JavaScript. Independent mobile app development for Android, independent game development with Lua or C++.
\vspace{0.2cm}
Teaching Work: Tutoring math @ MCCKC (2004), creating programming tutorials on YouTube (since 2008), adjunct teacher @ UMKC (2013, various other years), adjunct teacher @ JCCC (2016-2018), full time teacher @ JCCC (2020 - current).
\vspace{0.2cm}
Free time things: Playing video games, making video games, studying human languages, gardening, arts and crafts, journaling and organization, animating, video editing, playing piano, writing music, TTRPGs, drinking coffee, making zines, volunteering.
\vspace{0.2cm}
Other names: In the work system I'm R.W., but my full name is Rachel Wil Sha Singh. Around many friends I go by "Moose". I am nonbinary and go by various names in various contexts. I relate more to computers than I do to genders.
\vspace{0.2cm}
Links 'n' stuff:
- View all my education / work experience: https://www.linkedin.com/in/rachel-singh/
- Homepage of all my courses: https://rachels-courses.gitlab.io/webpage/
- Repositories for all my courses: https://gitlab.com/rachels-conlangs
- My games and projects: http://www.moosadee.com/
\newpage
Reference
Basic Computer Skills
- Basic computer skills
How to take a screenshot
- In Windows
- Press PRINTSCREEN on your keyboard, then go to an image editing application (Paint, if you have nothing else) and use EDIT > PASTE to paste the image in.
- In Mac
- CTRL+Z, COMMAND+SHIFT+3 to take a screenshot in Mac
- Navigating the filesystem
Identifying file extensions
You should be aware of the extensions of our files. You will need to be able to identify source code files, such as
.cpp
and.h
files for C++, or.py
files for Python. Additionally, most executable (runnable) files end with the.exe
extension in Windows.Turning on viewing file extensions in Windows
By default, Windows hides file extensions from you. However, it is important to know what kind of files you're working with in a programming class. To view file extensions, search for "File Explorer Options". Select the "View" tab, and UNCHECK the option "Hide extensions for known file types". Hit OK when done.
Project working directory
Visual Studio:
Code::Blocks:
It is important to keep in mind that the default working directory of our programs is the location where the project file is. For Visual Studio, that's a .vcxproj file. For Code::Blocks, that's a .cbp file.
Navigating quickly
Selecting multiple files with CTRL or SHIFT
- Editing text
Cut (CTRL+X), copy (CTRL+C), paste (CTRL+V)
Double-click to highlight word
CTRL+arrow keys to scroll a word at a time
CTRL+HOME/CTRL+END to go to start/end of a document
SHIFT to select regions of text
- IDE tips and tricks
Splitting code views
Go to declaration
Go to definition
Find all references
Refactor - Rename
Code and UI Style Guide
- Repository management
- Your merge request should only contain files related to the current feature or project you're working on
- It shouldn't contain code from multiple assignments.
- User Interface design
- Prompts before inputs
Before using an input statement (e.g.,
cin
), use an output statement (e.g.,cout
) to display a message to the user. Make sure you're clear about what kind of data you're expecting them to enter.No:
_
If you use an input statement it doesn't show anything on the screen, so it looks like your program has crashed.
Yes:
Please enter pet name: _
Use an output statement to display a message before getting the user's input.
- Prompts before inputs
- C++ Style Guide
- Naming conventions
- Variables
lowerCamelCase
- Variable names should begin with a lower-case letter and each subsequent letter use an Upper Case, in a camel-case format.Additionally:
- Variable names should be descriptive.
- Avoid using single-letter variable names except with for loops.
- Member variables
m_lowerCamelCase
- Variables that belong to a class should be prefixed withm_
to signify "member".
- Functions
CamelCase
- Function names should begin with an upper-case letter and be in CamelCase form. In some cases, using an underscore might be okay to group like-functions together, if it makes things more clear.
- Classes
CamelCase
- Class names should begin with an upper-case letter and be in CamelCase form.
- Best practices
- Basics
- You must have
int main
, notvoid main
. - Don't put an entire program in main() - Split out the program into separate menu functions; ideally use a
Program
class that contains functions within it.
- You must have
- Naming conventions
- Variable, function, and class names should be descriptive.
- Arrays
- Do not use a variable for an array's size; some compilers might support this but not all do. Traditional C arrays and STL arrays must have hard-coded integer literals or named constant integers as its size.
- Functions
- Functions should perform the minimal amount of operations - a function should have a specific purpose.
- Structs and Classes
- Structs should be used for structures that only contain a few amount of variables and no functions. Classes should be used for more sophisticated structures that contain functions and variables.
- Prefer making member variables private with member functions as an interface for those items.
- try/catch
- The
try{}
statement should wrap the most minimal amount of code (NOT THE ENTIRE FUNCTION BODY!) - generally, try should wrap the one function that could throw an exception.
- The
- NEVER USE GLOBAL VARIABLES.
- NEVER USE
goto
STATEMENTS.
- Basics
- Naming conventions
- Cross platform compatibility
- Treat everything (including files) as case-sensitive
- When using an
#include
statement for a file in your project, make sure your casing matches the file itself. E.g., if the file isProduct.h
, use#include "Product.h"
, not#include "product.h"
.
- Use
#ifndef
fileguards, not#pragma once
… - Use the
#ifndef _LABEL
,#define _LABEL
,#endif
style of file guards as they are supported by more compilers.- Fileguards ONLY go in .h files.
system("cls");
only works on WindowsPrefer creating a cross-platform function like this instead:
void ClearScreen() { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) system( "cls" ); #else system( "clear" ); #endif }
system("pause");
only works on Windows.Prefer creating a cross-platform function like this instead:
// It's klugey but it's the simplest. void PressEnterToContinue() { cout << endl << "PRESS ENTER TO CONTINUE" << endl; string temp; getline( cin, temp ); getline( cin, temp ); }
- File guards
- Always use
ifndef
instead ofpragma once
for your file guards.
Yes:
#ifndef _MYFILE_H #define _MYFILE_H // My code #endif
No:
#pragma once // My code
- File organization
- Function/class declarations
- Function and class declarations should go in a header (.h) file.
- Function definitions
- Function definitions should go in a source (.cpp) file, EXCEPT TEMPLATED FUNCTIONS (those all go in .h).
- Each class/struct should have its own set of .h and .cpp (as needed) files
- Don't put multiple class declarations in one file.
- Function definitions must go in .cpp file
- Don't define class functions within the class or in the .h file.
- Except for templated classes - Everything goes in the .h file for templated classes.
- Don't define structs/classes inside other classes
- Each struct/class should have its own .h file/set of .h and .cpp files.]
- Never include .cpp files!
Includes should only include .h or .hpp header files.
- If a project has many files, separate them into folders
- Logically separate related files into subfolders, such as Exceptions, DataStructures, Menus, etc.
- Clean code
- Erase unused codeblocks
- If you want to make sure to be able to reference old code later, back it up to GitLab, then delete the comment. Don't leave commented out code blocks in turn-in assignments.
- Be consistent with naming conventions
- Choose either UpperCaseFunctionNames or lowerCaseFunctionNames but don't interchange them. Same with variable and class naming. Be consistent.
- Whitespace
- Adequate whitespace should be used to differentiate logical sections of code. At the same time, don't use too much whitespace. The goal is to have readable code.
- If ( true ) return true; else return false;
- If you're writing a condition to check if something is
true
in order to returntrue
, just return the result of the condition instead.
No:
if ( a == b ) return true; else return false;
Yes:
return ( a == b );
- Curly braces
- Follow the existing code base
- If you're writing code from scratch you can follow whatever style you'd like as long as it is consistent.
- When working with existing code-bases, use the same style as the existing code.
- See https://en.wikipedia.org/wiki/Indentation_style for indentation styles
Preferred style:
if ( a == b ) { DoThing(); }
GNU styling:
if ( a == b ) { DoThing(); }
K&R Styling ("JavaScript" style):
if ( a == b ) { DoThing(); }
- One-line contents
- Always surround your if statement and while loop contents within curly braces { } even though it's not required for one-line internals.
No:
if ( CONDITION ) DoThingA(); else if ( CONDITION2 ) DoThingB(); else DoThingC();
Yes:
if ( CONDITION ) { DoThingA(); } else if ( CONDITION2 ) { DoThingB(); } else { DoThingC(); }
Or:
if ( CONDITION ) { DoThingA(); } else if ( CONDITION2 ) { DoThingB(); } else { DoThingC(); }
C++ Quick Reference
- Starter C++ programs
Without arguments:
int main() { return 0; }
With arguments:
int main( int argCount, char* args[] ) { return 0; }
- Variables and named constants
Declare a variable
DATATYPE VARIABLENAME;
int myNumber; string myString; float myFloat;
Declare a variable and initialize it
DATATYPE VARIABLENAME = VALUE;
int myNumber = 10; string myString = "Hello!"; float myFloat = 9.99; char myChar = 'a'; bool myBool = true;
Declare a named constant
const DATATYPE NAME = VALUE;
const int NUMBER = 10; const string STATE = "Missouri";
Assign a value to a variable that has already been declared
VARIABLENAME = VALUE;
myNumber = 100; myString = "Goodbye";
Copy a value from one variable to another
UPDATEDVAR = COPYME;
vipStudent = student3;
- Console input and output
Output text to the console
cout << ITEM;
You can mix variables and string literals, as long as the stream operator
<<
is between each item.cout << "Text"; cout << myVariable; cout << "Label: " << myVariable << endl;
Get input from the keyboard and store it in a variable
cin >> VARIABLENAME;
cin >> myInteger; cin >> myString;
Get a full line of text (with spaces) and store in a variable (string only)
getline( cin, VARIABLENAME );
getline( cin, myString );
Note that if you have a
cin >>
statement immediately before the getline statement, your input will get skipped. In this case you need to add acin.ignore()
statement:cin >> myNumber; cin.ignore(); getline( cin, myString );
- Branching
If statement
If the condition evaluates to true, then execute the code within the if statement. Otherwise, skip that code completely.
if ( a == 1 ) { }
If/else statement
If the condition from if statement results to false, then the code in the else case is executed instead. No condition is written with the else case.
if ( a == 1 ) { } else { }
If/else if statement
Checks each condition in order. If one is true, then subsequent
else if
statements are ignored.if ( a == 1 ) { } else if ( a == 2 ) { }
If/else if/else statement
Similar to above, but if all
if
andelse if
statements are false, thenelse
is executed.if ( a == 1 ) { } else if ( a == 2 ) { } else { }
- Switch
switch( VARIABLE ) { case VALUE: break; }
switch( myNumber ) { case 1: cout << "It's one!" << endl; break; case 2: cout << "It's two!" << endl; break; default: cout << "I don't know what it is!" << endl; }
- Loops
Looping with While Loops
Runs 0 or more times, depending on whether the CONDITION is true.
while ( CONDITION ) { }
while ( a < b ) { cout << a << endl; a++; }
Looping with Do…While Loops
Runs at least once and then continues looping if the condition is true.
do { } while ( CONDITION );
do { cout << "Enter a number: "; cin >> input; } while ( input < 0 || input > max );
Looping with For Loops
Iterate some amount of times through the loop based on your counter variable and range.
for ( INIT; CONDITION; UPDATE ) { }
for ( int i = 0; i < 10; i++ ) { cout << i << endl; }
Looping with Range-Based For Loops
Iterates over all elements in a collection. Only moves forward, doesn't give access to index
for ( INIT : RANGE ) { }
vector<int> myVec = { 1, 2, 3, 4 }; for ( int element : myVec ) { cout << element << endl; }
- Arrays and Vectors
Declare a traditional C-style array
When declaring a vanilla array, you need to set its size. You can either hard-code the size with a number:
string arr[10];
Or use a named constant:
const int TOTAL_STUDENTS; string students[TOTAL_STUDENTS];
Declare an STL array object Remember that you will need
#include <array>
at the top of your file to use the array object.Declare an array object, passing in what the data type of it values are, and the size of the array:
array<float, 3> bankBalances;
Use the array documentation (https://cplusplus.com/reference/array/array/) for info on its functions.
Declare an STL vector object
vector<string> studentList;
Use the vector documentation (https://cplusplus.com/reference/vector/) for info on its functions.
Initialize array/vector with an initializer list
string cats1[] = { "Kabe", "Luna", "Pixel", "Korra" }; array<string,4> cats2 = { "Kabe", "Luna", "Pixel", "Korra" }; vector<string> cats3 = { "Kabe", "Luna", "Pixel", "Korra" };
Iterate over an array/vector
// C-style array: for ( int i = 0; i < TOTAL_STUDENTS; i++ ) { cout << "index: " << i << ", value: " << students[i] << endl; } // STL Array and STL Vector: for ( size_t i = 0; i < bankBalances.size(); i++ ) { cout << "index: " << i << ", value: " << students[i] << endl; }
size_t
is another name for anunsigned int
, which allows values of 0 and above - no negatives. - File I/O
Make sure to have
#include <fstream>
in any files usingifstream
orofstream
!Create an output file and write
ofstream output; output.open( "file.txt" ); // Write to text file output << "Hello, world!" << endl;
Create an input file and read
ifstream input; input.open( "file.txt" ); if ( input.fail() ) { cout << "ERROR: could not load file.txt!" << endl; } string buffer; // read a word input >> buffer; // read a line getline( input, buffer );
- Functions
Prevent file duplication
When creating .h/.hpp files, it is important to include these lines to prevent file duplication, which happens if you #include this file in more than one place.
#ifndef _FILENAME_H // LABEL SHOULD BE UNIQUE FOR EACH .h FILE! #define _FILENAME_H // Code goes here #endif
Function declaration
A function declaration contains the function header and no body. It declares that the function exists and will be defined elseware.
void DisplayMenu(); int Sum(int a, int b);
Function definition
A function definition defines how the function operates. It includes the function header and a function body, which has commands in it.
void DisplayMenu() { cout << "1. Deposit" << endl; cout << "2. Withdraw" << endl; cout << "3. Quit" << endl; } int Sum(int a, int b) { return a + b; }
Calling a function
Calling a function requires invoking the function's name and passing in any arguments.
DisplayMenu(); int result = Sum( 1, 2 ); // Passing in literal values int num1 = 2; int num2 = 5; int result = Sum( num1, num2 ); // Passing in variable values
- Classes
Declaring a class
Remember that classes must end with
;
on their closing curly brace!class CLASSNAME { public: // Public members protected: // Protected members private: // Private members };
class Student { public: // Constructor functions Student(); Student( string name, float gpa ); // Member functions void Setup( string name, float gpa ); void Display(); private: // Member variables string m_name; float m_gpa; };
Defining a class member function (method)
A class' member functions must be declared within the class declaration. Then, you define the member function within a .cpp file.
RETURNTYPE CLASSNAME::FUNCTIONNAME( PARAMETERS )
// Function definition void Student::Setup( string name, float gpa ) { m_name = name; m_gpa = gpa; }
Getter and Setter patterns
It is best practice to make member variables private to protect the integrity of the data. Private members cannot be accessed outside of the function, so instead you'll have to create interfacing functions to access (get) and mutate (set) data.
- Getter function, aka Accessor
- Doesn't take in any inputs (parameters)
- Returns the value of the member variable (return type should match the member variable)
- Getter functions can be good for formatting data before returning it
// Basic getter function float Student::GetGPA() { return m_gpa; } // Example of formatting before returning data string Person::GetFullName() { return m_lastname + ", " + m_firstname; }
- Setter function, aka Mutator
- Takes in an input value for a new value for the member variable - parameter should have the same data type as the member variable
- Doesn't return any data - void return type
- Setter functions should include any needed error checking and reject invalid data
// Basic setter function void Student::SetGPA( float newGpa ) { m_gpa = newGpa; } // Example of data validity check void Student::SetGPA( float newGpa ) { if ( newGpa < 0 || newGpa > 4 ) { cout << "Error! Invalid GPA!" << endl; return; // Return without saving data } else { m_gpa = newGpa; } }
- Pointers
Declare a pointer
DATATYPE* PTRNAME = nullptr;
Assign an address to a pointer
PTRNAME = &VARIABLE;
int * ptrInt = nullptr; string * ptrString = nullptr;
Pointer variables store addresses as their value. To get the address of a variable, prefix the variable name with the address-of operator
&
.int myInteger = 5; int * ptrInt = &myInteger; Student studentA; Student * ptrStudent = nullptr; ptrStudent = &studentA;
Dereference a pointer
cout << *ptrName; // Display contents that pointer is pointing to cin >> *ptrName; // Overwrite contents that pointer is pointing to
Dereference an object pointer and access a member variable
PTR->MEMBER
Student* newStudent = new Student; newStudent->name = "Hikaru"; cout << "Student name: " << newStudent->name << endl;
Check if pointer is pointing to an address
if ( ptrName != nullptr ) { // Pointer is safe to use... }
- Memory management
Allocate memory for a single variable
DATATYPE* PTRNAME = NEW DATATYPE;
int * num = new int; Node* newNode = new Node;
Deallocate memory of a single variable
DELETE PTRNAME;
delete num; delete newNode;
Allocate memory for an array
DATATYPE* PTRNAME = new DATATYPE[ SIZE ];
int * numList = new int[100]; Node* nodeList = new Node[10];
Deallocate memory of an array
DELETE [] PTRNAME;
delete [] numList; delete [] nodeList;
Common C++ issues
- Common build errors
- Undefined Reference to WinMain
- Explanation: Your program can't find
main()
, the main entry-point to the program. - Try:
- Make sure you've written
int main()
in your prgoram. - If working with Visual Studio, make sure you've opened a project (NOT A FILE/FOLDER!) - Is your Solution Explorer empty?
- Make sure you've written
- Explanation: Your program can't find
- Undefined reference to …
- Explanation: A variable or function either has not been declared or cannot be found at the current location in the program.
- Try: Check to make sure you don't have any typos, that your variables have been declared, that your
#include
are set up properly, and that any functions declared also are defined elseware.
- Use of undeclared identifier XYZ
- Explanation: You're trying to use a variable XYZ but you have not declared it at this point in the program.
- Try: Look for your variable declaration and make sure it shows up before any code that uses this variable.
- Unresolved external symbol ABC
- Explanation: This usually means you've made a call to a function that doesn't exist - perhaps you've declared it somewhere, but never wrote the function's definition.
- Try: Double checking that all your function declarations' and definitions' headers MATCH!
- Object of abstract class type is not allowed / Cannot instantiate abstract class
- Explanation: You're trying to create an object (that is, a variable whose data type is a class), and the class you're using is still an abstract class. This could be because you haven't overridden all of its parents' pure virtual functions, or perhaps a typo between the parent class' function signature and the child class' function signature.
- Try: Look at class' parent - for any pure virtual functions (e.g.,
virtual RETURN FUNC() = 0;
), make sure you have declared and defined them in the child class.
- cannot convert from ABC to XYZ
- Explanation: The program is expecting an XYZ data type in a location where you're giving it an ABC type instead.
- Try: If you're working with a class object, perhaps you need to pass a member variable of that class object instead?
- ABC already defined in XYZ
- Explanation: This error is saying that a function has already been defined elsewhere. There could be a few reasons.
- Try:
- Are you missing the
#ifndef
file guards in a .h file? - Have you defined a given function more than once?
- Run a Clean and Rebuild in your IDE.
- Make sure that you DO NOT HAVE
#include
FOR ANY .cpp FILES!!
- Are you missing the
- Operator -> applied to ABC instead of pointer type
- Explanation: You're trying to dereference an object that is not a pointer.
- Try: Perhaps you're storing a vector of pointers? Make sure you're accessing a single element.
- error: implicit instantiation of undefined template 'std::basicifstream
- Explanation: Missing an include for the fstream library.
- Try: Don't forget to put
#include <fstream>
in the code files where you're usingifstream
orofstream
.
- Common runtime errors
- Memory access violation
- Explanation: If the memory address it shows you is 0x00000 or something with a lot of zeroes, then you're trying to access a pointer that is pointing to nullptr.
- Try:
- Check to make sure you're not going outside of bounds on an array.
- Check to make sure you're checking if a pointer is NOT pointing to
nullptr
before de-referencing it.
- Weird software issues
- Windows maximum path length error
- Explanation: Windows has a setting that limits the maximum file path length. If your repository is deep down many folders, you may encounter this issue.
- Fixes:
- Enable long paths - The Windows documentation (https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation) has some information on enabling long paths.
- OR Move your project directory - If you move your project directory to something like
C:\
instead of the desktop (which is actuallyC:\Users\blahblahblah\Desktop
) or the default visual studio project path (C:\Users\blahblahblah\source\repos
) this will help avoid this maximum path length issue.
- Visual Studio: Fatal error LNK1104: cannot open file …exe
- Explanation: Visual Studio is trying to build the program but cannot overwrite the .exe file.
- Fixes:
- Try to close Visual Studio and re-open it - Sometimes if your program crashed last time you ran it, Visual Studio will be unable to update the .exe file and give this error.
- OR Turn off your virus scan - Sometimes your virus scan will see the .exe file you just built as an ``unknown threat'' and prevent it from opening, which also causes this error.
- Code::Blocks: error: ld returned 1 exit status
- Try: Make sure you do not have any
#include
statements that include a .cpp file. Includes only work with .h and .hpp files, or library files in < > brackets.
- Try: Make sure you do not have any
- Code::Blocks: Modern C++ features not working
- Fix: In this case you'll need to set up your compiler to build for a modern C++ version, rather than the default of C++98 (from 1998). In Code::Blocks, go to Settings > Compiler… Then, check the box that is next to the Have g+ follow the C++17 ISO C++ language standard [-std=c++17] option, or the C++14 one if that's not available.
- XCode: Cannot find functions
- Explanation: This is a result of creating a new file in XCode, but choosing the wrong file type. When adding .cpp files, make sure you select a C++ file object.
- XCode: Where are my output/input text files??
- You will need to set up a Working Path for your projects in XCode. You can get to this option by going to the menu bar: Scheme -> Edit Scheme. You will want to set your working directory to a specific path where you can locate the text files.
- Git issues
- Git: There is no tracking information for the current branch.
- Error message: There is no tracking information for the current branch. Please specify which branch you want to merge with.
- Explanation: Git isn't sure what branch you're working with; tell it explicitly.
- Try:
git pull origin main
- Git: [rejected] error: failed to push some refs
- Error message: ! [rejected] error: failed to push some refs hint: Updates were rejected because the tip fo your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull …') before pushing again. hint: See the 'Note about fast-forwards' in 'git push –help' for details.
- Explanation: There are changes on the server that you don't have on your local machine yet. A merge needs to happen.
- Try: The hint gives you the solution: Run
git pull
and then repeat yourgit push
after the merge.
- Git: fatal: not a git repository (or any of the parent directories): .git
- Error message: fatal: not a git repository (or any of the parent directories): .git
- Explanation: You are not running your git commands from within a repository folder.
- Try: Make sure you open Git Bash within a folder, or use the
cd
commands to navigate to your repository path.
- Git: error: Browse.VC.opendb Permission denied
- Error message: error: open("…./Browse.VC.opendb"): Permission denied error: unable to index file '…/Browse.VC.opendb' fatal: adding files failed
- Explanation: This happens because Visual Studio is still open and Visual Studio dislikes its project files changing.
- Try: Close Visual Studio before running
git add
.
C++ projects - Building and running from the terminal
C++ projects - Integrated Development Environments
- Visual Studio
- Create a project:
- π½οΈ Video: https://youtu.be/4f1UJSGAcT8
- Open Visual Studio
- Make sure the language dropdown is set to "C++".
- Select "Empty Project", then click "Next".
- Configure your new project page:
- Set the "Project name" to whatever you'd like; best to name it after the assignment you're working on.
- Set the "Location" to within your repository folder.
- I would recomment checking the "Place solution and project in the same directory" option, but it's not required.
- Click on "Create".
- Add a NEW file to your project:
- π½οΈ Video: https://youtu.be/9-VgiCXgdxk
- Make sure you can see the Solution Explorer pane in your IDE. If it doesn't show up, go to the View dropdown menu and select "Solution Explorer".
- Right-click your project in the Solution Explorer. Go to "Add", then "New item…".
- Type in a filename, such as "main.cpp", "Functions.h", etc. "Add" when done.
- Add an EXISTING file to your project:
- π½οΈ Video: https://youtu.be/0x-srqvdmXg
- Make sure you can see the Solution Explorer pane in your IDE. If it doesn't show up, go to the View dropdown menu and select "Solution Explorer".
- Right-click your project in the Solution Explorer. Go to "Add", then "Existing item…".
- Locate the file you wish to add to the project, and then click "Add".
- Building the program:*
- π½οΈ Video: https://youtu.be/DmrgpzXUk2w
- From the dropdown menu, select "Build", then click "Build" to start compiling.
- An Output window should show up at the bottom of the program with information. If any build errors occur, you can see them in the Error List.
- Running the program:
- π½οΈ Video: https://youtu.be/pP0SWeDHNaQ
- To run the program, you can click on the "βΆοΈ Local Windows Debugger" button.
- Reopening your project later:
- π½οΈ Video: https://youtu.be/cLKi1QgbeEo
- To reopen your project, you can either locate the .sln file and double-click it to open it in Visual Studio, OR
- You can open Visual Studio, and select "Open a project or solution", then locate your .sln file and open it.
- Opening code windows side-by-side:
- π½οΈ Video: https://youtu.be/wCc9LU4RZCM
- Go to declaration, definition, and find references:
- π½οΈ Video: https://youtu.be/CzoeUfOu6Ek
- Code::Blocks
- Create a project:
- π½οΈ Video: https://youtu.be/mGoCoV0L8hU
- Click on the "Create a new project" link.
- Select "Empty project" and click "Go".
- Set a Project title to whatever you'd like; best to name it after the assignment you're working on.
- Set the Folder to create project in: to a folder within your repository directory.
- Click "Next >".
- Use the default Compiler and Create Debug and Create Release config settings. Click "Finish".
- Add a NEW file to your project:
- π½οΈ Video: https://youtu.be/q9D8LIn0QCg
- Go to the File dropdown menu and select New and Empty file.
- It will ask if you want to save the file, select Yes.
- Give the file a name then click "Save".
- Add an EXISTING file to your project:
- π½οΈ Video: https://youtu.be/nCkNvLgf4e0
- Right-click on your project in the left pane and select "Add files…".
- Locate the files you want to add, then click "Open".
- Building and running the program:
- π½οΈ Video: https://youtu.be/OY1Pg7Ao990
- From the dropdown menu select Build and then Build.
- The build status will show up at the bottom under "Build log".
- If the build succeeds, you can run the program using the Build dropdown menu then Run.
- Reopening your project later:
- π½οΈ Video: https://youtu.be/DghoQhkgqc8
- To reopen your project, you can either locate the .cbp file and double-click it to open it in Code::Blocks, OR
- You can open Code::Blocks, and select "Open an existing project", then locate your .cbp file and open it.
- Opening code windows side-by-side:
- π½οΈ Video: https://youtu.be/XQqJ5ncS60s
- Go to declaration, definition, and find references:
- π½οΈ Video: https://youtu.be/4Ev9iDqba8I
- Xcode
(@ProgrammingKnowledge channel): https://www.youtube.com/watch?v=F6QZ2atZrDw
- Create a project:
- Open Xcode
- Click on "Create a new Xcode project"
- On the Choose a template for your new project: screen, click on the "macOS" option, then select "Command Line Tool". Click "Next".
- Set a Product Name, Organization Identifier, and make sure the Language is set to "C++". Click "Next".
- Select a location where to save your project (such as in your repository folder). Click "Create".
- Add a NEW file to your project:
- On the left pane, right-click on your project folder and click "New File…".
- On the Choose a template for your new file: screen, click on "macOS" (if it's not already there) and select either a header .h file or a source .cpp file.
- Add an EXISTING file to your project:
- On the left pane, right-click on your project folder and click "Add Files to (PROJECT)…".
- Building and running the program:
- Click on the Play button on the top of the left pane. It will automatically build the program and run it.
- The program output shows up in a small window at the bottom of Xcode.
- Reopening your project later:
- Open Xcode
- Click on "Open a project or file".
- Locate your project.
- Go to declaration, definition, and find references:
- VSCode
- Create a project:
- π½οΈ Video: https://youtu.be/rNF7ZZW5Biw
- Create a folder on your computer for your project. It should be located in your repository directory somewhere.
- Open VSCode, and select "Open Folder…" and open the folder you just created.
- Add a NEW file to your project:
- π½οΈ Video: https://youtu.be/obcAcHvAltk
- Click on the "Add new file…" button to create a new file in your project folder.
- Add an EXISTING file to your project:
- π½οΈ Video: https://youtu.be/LgvHQ7bvtFU
- Any files added to the project folder will show up in your project.
- Building and running the program:
- π½οΈ Video: https://youtu.be/lps2-W7B4H0
- Click on "View" and select "Terminal".
- In the terminal, type in your build command, such as
g++ *.h *.cpp
- To run the program afterwards, use
./a.out
(Linux/Mac) or.\a.exe
(Win)
- Reopening your project later:
- π½οΈ Video: https://youtu.be/iccpI3vpUck
- When you open VSCode, select "Open folder" and navigate to your folder.
- Opening code windows side-by-side:
- π½οΈ Video: https://youtu.be/LAt75CEOWJ4
- Go to declaration, definition, and find references:
- π½οΈ Video: https://youtu.be/d9FW0CdddNQ
Archive - Video links
- CS 200 Topics
- Introduction to C++
- 60 Second Review: https://www.youtube.com/shorts/ScaOW_f2Ig0
- Old lecture video: http://lectures.moosader.com/cs200/00-Introduction.mp4
- Class archive: http://lectures.moosader.com/cs200/2021-01_Spring/2021-01-26_cs200_lecture.mp4
- Variables and data types
- Old lecture video: http://lectures.moosader.com/cs200/02-CPP-Basics.mp4
- Input and output with cin/cout
- Old lecture video: http://lectures.moosader.com/cs200/02-CPP-Basics.mp4
- Control flow - Branching and looping
- Old lecture video:
- Class archive:
- http://lectures.moosader.com/cs200/2021-01_Spring/2021-02-02_cs200_lectureA_truth_tables.mp4
- http://lectures.moosader.com/cs200/2021-01_Spring/2021-02-02_cs200_lectureB_if_statements.mp4
- http://lectures.moosader.com/cs200/2021-01_Spring/2021-02-04_cs200_lecture.mp4
- http://lectures.moosader.com/cs200/2021-01_Spring/2021-02-09_cs200_lecture.mp4
- http://lectures.moosader.com/cs200/2021-01_Spring/2021-02-11_cs200_lecture.mp4
- http://lectures.moosader.com/cs200/2021-06_Summer/2021-06-17_cs200_lecture_branching.mp4
- http://lectures.moosader.com/cs200/2021-06_Summer/2021-06-22_cs200_lecture_whileloops.mp4
- http://lectures.moosader.com/cs200/2021-06_Summer/2021-06-24_cs200_lecture_forloops.mp4
- Arrays
- Old lecture video: http://lectures.moosader.com/cs200/08-Arrays.mp4
- Class archive:
- Strings
- Old lecture video: http://lectures.moosader.com/cs200/07-Strings.mp4
- Class archive: http://lectures.moosader.com/cs200/2021-01_Spring/2021-02-25_cs200_lectureB_strings.mp4
- File input and output
- Old lecture video: http://lectures.moosader.com/cs200/14-File-IO.mp4
- Class archive: http://lectures.moosader.com/cs200/2021-01_Spring/2021-03-02_cs200_lecture_fileio.mp4
- Functions
- Old lecture video: http://lectures.moosader.com/cs200/05-Functions.mp4
- Class archive:
- Const
- Structs
- Old lecture video:
- Classes
- Inheritance
- Pointers and memory
- Recursion
- Searching and sorting
- 60 Second Review:
- Old lecture video:
- Class archive:
- Introduction to C++
- CS 235 Topics
- Testing and Debugging
- Function overloading
- 60 Second Review:
- Old lecture video:
- Class archive:
- Operator overloading
- Old lecture video: http://lectures.moosader.com/cs200/20-Operator-Overloading.mp4
- Smart Pointers
- 60 Second Review:
- Old lecture video:
- Class archive:
- Polymorphism
- 60 Second Review:
- Old lecture video: http://lectures.moosader.com/cs200/22-Polymorphism.mp4
- Class archive:
- Exceptions
- Templates
- Anonymous Functions
- Static
- Friends
- The Standard Template Library
- Old lecture video: http://lectures.moosader.com/cs200/27-STL.mp4
- Class archive:
- CS 250 Topics
- Intro to Data Structures
- Old lecture video: https://www.youtube.com/watch?v=INGLTz6jBuk
- Algorithm Efficiency
- Smart Arrays
- Linked Lists
- Stacks and Queues
- Old lecture video: https://www.youtube.com/watch?v=hNfgrGFIAVs
- Intro to Trees
- Class archive: https://www.youtube.com/watch?v=7ZcZuYvBAVw
- Binary Search Trees
- Hash Tables
\newpage
- Intro to Data Structures
Syllabus
Course information
College | Johnson County Community College |
Division | CSIT (Computer Science/Information Technology) |
Instructor | Rachel Wil Singh (they/them) |
Semester | Spring 2024 (01/22/2024 - 05/13/2024) |
Course | CS 200: Concepts of Programming with C++ (4 credit hours) |
Section | Section 400 / CRN 10953 / HyFlex / Mondays, 6:00 - 8:00 pm |
Room | Regnier Center, room 347 |
- Course description
- This course emphasizes problem solving using a high-level programming language and the software development process. Algorithm design and development, programming style, documentation, testing and debugging will be presented. Standard algorithms and data structures will be introduced. Data abstraction and an introduction to object-oriented programming will be studied and used to implement algorithms. 3 hrs. lecture, 2 hrs. lab by arrangement/wk. Catalog link: https://catalog.jccc.edu/coursedescriptions/cs/#CS_200
- Prerequisites
- (CS 134 with a grade of "C" or higher or CIS 142 with a grade of "C" or higher or department waiver test and MATH 131 or higher) or MATH 241 or department approval.
- Drop deadlines
- To view the deadline dates for dropping this course, please refer to the schedule on the JCCC website under Admissions>Enrollment Dates> Dropping Credit Classes. After the 100% refund date, you will be financially responsible for the tuition charges; for details, search on Student Financial Responsibility on the JCCC web page. Changing your schedule may reduce eligibility for financial aid and other third party funding. Courses not dropped will be graded. For questions about dropping courses, contact the Student Success Center at 913-469-3803.
- Auto-withdraws
- Attendance for the first week of classes at JCCC are recorded and students marked as NOT IN ATTENDANCE get auto-withdrawn from the course. Please pay attention to course announcements / emails from the instructor for instructions on how to make sure you are marked as IN ATTENDANCE.
- To learn more about reinstatement, please visit: https://www.jccc.edu/admissions/enrollment/reinstatement.html
Instructor information
- Name: Rachel Wil Singh, aka R.W.
- Pronouns: they/them
- Office: RC 348 H
- Email: rsingh13@jccc.edu (please use Canvas email instead)
- Office phone: (913) 469-8500 x3671
Course delivery
This course is set up as a HyFlex course. This means the following:
- Courses have a scheduled "in-class" time each week.
- Students can choose to attend class in one of three ways:
- In person in the classroom during class time
- Remotely via Zoom during class time
- Watch the archived Zoom lecture after class time
- A Zoom link will be available for each class session. Please see the Canvas page, under "Zoom", for the link.
- Class sessions will be recorded and you can view them afterwards. Please see the Canvas page, under "Zoom", then "Cloud recordings".
To see more about JCCC course delivery options, please visit: https://www.jccc.edu/student-resources/course-delivery-methods.html
Office hours Office hours are weekly times that the instructor is available, either on-campus and/or via Zoom. If the pre-determined office hours don't work with your schedule, you can also schedule a one-on-one time to meet with the instructor.
Office hours are drop-in, and you can attend during any pre-scheduled times; you do not need to ask to join in. You may be placed in a waiting room if I am working with another student on something.
Scheduled office hours:
- Wednesdays, 12:00 - 2:30 pm, and 5:30 - 8:00 pm (ZOOM ONLY)
- I will be on campus on Mondays and Tuesdays, please email ahead to find out times I am able to meet in person if needed.
Class communication
- Please use Canvas email, not the @jccc email, to contact the instructor! I rely upon the Canvas email system for communication with students and only students. The direct @jccc email address also receives non-student communication such as automated campus updates, department emails, commitee emails, and so on. To ensure that I see your email in a timely manner, please email me via Canvas!
- Instructor will respond within 1 business day I do my best to respond to emails as quickly as possible, at most within 1 business day. Emails on Friday may not get a response until Monday. If I have not responded to your email within this time period it is possible I have not seen your email, please make sure to email me through Canvas and not to my @jccc email.
- Check course Announcements! I use the Announcements board as a way to give additional course information, assignment corrections, and other things. You can set up Canvas to email these announcements to you automatically. Please don't ignore class Announcements!
- Course supplies
- Textbook: Rachel's CS 200 course notes (https://moosadee.gitlab.io/courses/202401_Spring/book_corecpp.html)
- Zoom: Needed for remote attendance / office hours
- Tools: See the UNIT 00 SETUP assignments for steps on installation.
- WINDOWS: MinGW, a code editor
- LINUX/MAC: g++, a code editor
- You may need a document editor, such as LibreOffice Writer, MS Word, or Google Documents.
- Accounts: See the UNIT 00 SETUP assignments for steps on set up.
- GitLab (https://gitlab.com/) for code storage
- Optional: Things that might be handy
- Dark Reader plugin (Firefox/Chrome/Safari/Edge) to turn light-mode webpages into dark-mode. (https://darkreader.org/)
? What about IDEs like Visual Studio or Code::Blocks ? In this course we will be learning about building C++ programs from the command line. If you already know how to use other IDEs you are free to use them as well.
- Recommended experience
There are certain skills that will make your time in this class easier. Please look over this list and let me know if you need additional help with any of these things.
Computer skills - You should have a base level knowledge of using a computer, including:
- Navigating your Operating System, including:
- Installing software
- Running software
- Locating saved files on your computer
- Writing text documents, exporting to PDF
- Taking screenshots
- Editing .txt and other plaintext files
- Navigating the internet:
- Navigating websites, using links
- Sending emails
- Uploading attachments
Learning skills - Learning to program takes a lot of reading, and you will be building up your problem solving skills. You should be able to exercise the following skills:
- Breaking down problems - Looking at a problem in small pieces and tackling them one part at a time.
- Organizing your notes so you can use them for reference while coding.
- Reading an entire part of an assignment before starting - these aren't step-by-step to-do lists.
- Learning how to ask a question - Where are you stuck, what are you stuck on, what have you tried?
- Recognizing when additional learning resources are needed and seeking them out - such as utilizing JCCC's Academic Achievement Center tutors.
- Managing your time to give yourself enough time to tackle challenges, rather than waiting until the last minute.
How to ask questions - When asking questions about a programming assignment via email, please include the following information so I can answer your question:
- Be sure to let me know WHICH ASSIGNMENT IT IS, the specific assignment name, so I can find it.
- Include a SCREENSHOT of what's going wrong.
- What have you tried so far?
- Navigating your Operating System, including:
Course policies
- Grading breakdown
Assessment types are given a certain weight in the overall class. Breakdown percentages are based off the course catalog requirements (https://catalog.jccc.edu/coursedescriptions/cs/#CS_200)
- Labs: Weekly programming assignments to help practice new concepts (20%)
- Exercises: A variety of additional topics to help students learn and practice (5%)
- Debugging practice: Assignments to help students with diagnosing and debugging skills
- Nonograms: Small puzzles to help students practice problem solving and analysis
- Tech Literacy discussions: Discussions about tech related areas (5%)
- Check-ins: Weekly Check-Ins to let me know how you're doing in the course and if you need anything additional (5%)
- Quizzes: Concept Introductions help students review concepts read about in the textbook (10%)
- Projects: Larger programming assignments that combine multiple topics (15%)
- Exams: Mastery Checks to help the student and instructor assess how much about a topic has been learned (40%)
Final letter grade: JCCC uses whole letter grades for final course grades: F, D, C, B, and A. The way I break down what your receive at the end of the semester is as follows:
Total score Letter grade 89.5% \(\leq\) grade \(\leq\) 100% A 79.5% \(\leq\) grade < 89.5% B 69.5% \(\leq\) grade < 79.5% C 59.5% \(\leq\) grade < 69.5% D 0% \(\leq\) grade < 59.5% F - Tentative schedule
Week # Monday Topic A Topic B 1 Jan 22 Unit 00: Setup Unit 01: Exploring software 2 Jan 29 Unit 02: Command line Unit 03: C++ basics 3 Feb 5 Unit 04: Control flow 4 Feb 12 Unit 05: Structs 5 Feb 19 Unit 06: Functions 6 Feb 26 Unit 07: Strings Unit 08: File I/O 7 Mar 4 Unit 09: Pointers Unit 10: Arrays and vectors 8 Mar 11 SPRING BREAK 9 Mar 18 Unit 11: Classes Unit 12: Inheritance 10 Mar 25 Unit 13: Searching & sorting Unit 14: Recursion 11 Apr 1 Semester project v1 12 Apr 8 Semester project v1 13 Apr 15 Semester project v2 14 Apr 22 Semester project v2 - Due dates, late assignments, re-submissions
- Due dates are set as a guide for when you should have your assignments in by.
- End dates/available until dates are a hard-stop for when an assignment can be turned in. Assignments cannot be turned in after this date until The Reopening.
- The Reopening happens at the end of the semester once I have finished preparing all content for the rest of the semester.
This period allows you to turn in late assignemnts that you didn't get in by the Available Until Date for a slight reduction in
maximum total points.
- Assignments that WERE NOT TURNED IN by the Available Until Date will receive a maximum points penalty.
- Assignments that WERE TURNED IN on time will still have a 100% maximum potential grade. This is for resubmissions to fix previous issues.
- Resubmissions to some assignments are permitted:
- Concept Introductions are auto-graded and you can resubmit them as much as you'd like, with the highest score being saved.
- Labs are manually graded but you can turn in fixes after receiving feedback from the instructor.
- Attendance
JCCC requires us to take attendance during the first week of the semester. Students are required to attend class (if there is a scheduled class session) this first week. If there are scheduling conflicts during the first week of class, please reach out to the instructor to let them know. JCCC auto-drops students marked as not in attendance during the first week of class, but students can be reinstated. See https://www.jccc.edu/admissions/enrollment/reinstatement.html for more details.
HyFlex classes: The following three scenarios count as student attendance for my classes:
- Attending class in person during the class times, or
- Attending class remotely via Zoom during class times, or
- Watching the recorded Zoom class afterwards
Online classes: Attendance is counted as completion of assignments for a given week.
- Class format
Class sessions are flexible and can be changed to suit student requests. By default, class sessions are usually used for:
- Working through example code
- An overview of the assignments for the week
- In-class working time
Generally, I do not lecture during class times; there are video lectures and reading assignments that students can complete independently. Class times for this course are better used for students to get hands-on experience with the new topics while having the instructor available to answer questions and make clarifications.
- Academic honesty
The assignments the instructor writes for this course are meant to help the student learn new topics, starting easy and increasing the challenge over time. If a student does not do their own work then they miss out on the lessons and strategy learned from going from step A to step B to step C. The instructor is always willing to help you work through assignments, so ideally the student shouldn't feel the need to turn to third party sources for help.
Generally, for R.W. Singh's courses:
- OK things:
- Asking the instructor for help, hints, or clarification, on any assignment.
- Posting to the discussion board with questions (except with tests - please email me for those). (If you're unsure if you can post a question to the discussion board, you can go ahead and post it. If there's a problem I'll remove/edit the message and just let you know.)
- Searching online for general knowledge questions (e.g. "C++ if statements", error messages).
- Working with a tutor through the assignments, as long as they're not doing the work for you.
- Use your IDE (replit, visual studio, code::blocks) to test out things before answering questions.
- Brainstorming with classmates, sharing general information ("This is how I do input validation").
- Not OK Things:
- Sharing your code files with other students, or asking other students for their code files.
- Asking a tutor, peer, family member, friend, AI, etc. to do your assignments for you.
- Searching for specific solutions to assignments online/elseware.
- Basically, any work/research you aren't doing on your own, that means you're not learning the topics.
- Don't give your code files to other students, even if it is "to verify my work!"
- Don't copy solutions off other parts of the internet; assignments get modified a little bit each semester.
If you have any further questions, please contact the instructor.
Each instructor is different, so make sure you don't assume that what is OK with one instructor is OK with another.
- OK things:
- Student success tips
- I need to achieve a certain grade for my financial aid or student visa. What do I need to plan on?
- If you need to get a certain grade, such as an A for this course, to maintain your financial aid or student visa, then you need to set your mindset for this course immediately. You should prioritize working on assignments early and getting them in ahead of time so that you have the maximum amount of time to ask questions and get help. You should not be panicking at the end of the semester because you have a grade less than what you need. From week 1, make sure you're committed to staying on top of things.
- How do I contact the instructor?
- The best way to contact the instructor is via Canvas' email system. You can also email the instructor at rsingh13@jccc.edu, however, emails are more likely to be lost in the main inbox, since that's where all the instructor's work-related email goes. You can also attend Zoom office hours to ask questions.
- What are some suggestions for approaching studying and assignments for this course?
Each week is generally designed with this "path" in mind:
- Watch lecture videos, read assigned reading.
- Work on Concept Introduction assignment(s).
- Work on Exercise assignment.
Those are the core topics for the class. The Tech Literacy assignments can be done a bit more casually, and the Topic Mastery (exams) don't have to be done right away - do the exams once you feel comfortable with the topic.
- Where do I find feedback on my work?
- Canvas should send you an email when there is feedback on your work, but you can also locate assignment feedback by going to your Grades view on Canvas, locating the assignment, and clicking on the speech balloon icon to open up comments. These will be important to look over during the semester, especially if you want to resubmit an assignment for a better grade.
- How do I find a tutor?
- JCCC's Academic Achievement Center (https://www.jccc.edu/student-resources/academic-resource-center/academic-achievement-center/) provides tutoring services for our area. Make sure to look for the expert tutor service and you can learn more about getting a tutor.
- How do I keep track of assignments and due dates so I don't forget something?
- Canvas has a CALENDAR view, but it might also be useful to utilize something like Google Calendar, which can text and email you reminders, or even keeping a paper day planner that you check every day.
- Accommodations and life help
- How do I get accommodations? - Access Services
- https://www.jccc.edu/student-resources/access-services/ Access Services provides students with disabilities equal opportunity and access. Some of the accommodations and services include testing accommodations, note-taking assistance, sign language interpreting services, audiobooks/alternative text and assistive technology.
- What if I'm having trouble making ends meet in my personal life? - Student Basic Needs Center
- https://www.jccc.edu/student-resources/basic-needs-center/ Check website for schedule and location. The JCCC Student Assistance Fund is to help students facing a sudden and unforeseen emergency that has affected their ability to attend class or otherwise meet the academic obligations of a JCCC student. If you are experiencing food or housing insecurity, or other hardships, stop by COM 319 and visit with our helpful staff.
- Is there someone I can talk to for my degree plan? - Academic Advising
- https://www.jccc.edu/student-resources/academic-counseling/
JCCC has advisors to help you with:
- Choose or change your major and stay on track for graduation.
- Ensure a smooth transfer process to a 4-year institution.
- Discover resources and tools available to help build your schedule, complete enrollment and receive help with coursework each semester.
- Learn how to get involved in Student Senate, clubs and orgs, athletics, study abroad, service learning, honors and other leadership programs.
- If thereβs a hold on your account due to test scores, academic probation or suspension, you are required to meet with a counselor.
- Is there someone I can talk to for emotional support? - Personal Counseling
- https://www.jccc.edu/student-resources/personal-counseling/ JCCC counselors provide a safe and confidential environment to talk about personal concerns. We advocate for students and assist with personal issues and make referrals to appropriate agencies when needed.
- How do I get a tutor? - The Academic Achievement Center
- https://www.jccc.edu/student-resources/academic-resource-center/academic-achievement-center/ The AAC is open for Zoom meetings and appointments. See the website for their schedule. Meet with a Learning Specialist for help with classes and study skills, a Reading Specialist to improve understanding of your academic reading, or a tutor to help you with specific courses and college study skills. You can sign up for workshops to get off to a Smart Start in your semester or analyze your exam scores!
- How can I report ethical concerns? - Ethics Report Line
- https://www.jccc.edu/about/leadership-governance/administration/audit-advisory/ethics-line/ You can report instances of discrimination and other ethical issues to JCCC via the EthicsPoint line.
- What other student resources are there? - Student Resources Directory
- https://www.jccc.edu/student-resources/
Additional information
- ADA compliance / disabilities
JCCC provides a range of services to allow persons with disabilities to participate in educational programs and activities. If you are a student with a disability and if you are in need of accommodations or services, it is your responsibility to contact Access Services and make a formal request. To schedule an appointment with an Access Advisor or for additional information, you can contact Access Services at (913) 469-3521 or accessservices@jccc.edu. Access Services is located on the 2nd floor of the Student Center (SC202)
- Attendance standards of JCCC
Educational research demonstrates that students who regularly attend and participate in all scheduled classes are more likely to succeed in college. Punctual and regular attendance at all scheduled classes, for the duration of the course, is regarded as integral to all courses and is expected of all students. Each JCCC faculty member will include attendance guidelines in the course syllabus that are applicable to that course, and students are responsible for knowing and adhering to those guidelines. Students are expected to regularly attend classes in accordance with the attendance standards implemented by JCCC faculty.
The student is responsible for all course content and assignments missed due to absence. Excessive absences and authorized absences are handled in accordance with the Student Attendance Operating Procedure.
- Academic Dishonesty
No student shall attempt, engage in, or aid and abet behavior that, in the judgment of the faculty member for a particular class, is construed as academic dishonesty. This includes, but is not limited to, cheating, plagiarism or other forms of academic dishonesty.
Examples of academic dishonesty and cheating include, but are not limited to, unauthorized acquisition of tests or other academic materials and/or distribution of these materials, unauthorized sharing of answers during an exam, use of unauthorized notes or study materials during an exam, altering an exam and resubmitting it for re-grading, having another student take an exam for you or submit assignments in your name, participating in unauthorized collaboration on coursework to be graded, providing false data for a research paper, using electronic equipment to transmit information to a third party to seek answers, or creating/citing false or fictitious references for a term paper. Submitting the same paper for multiple classes may also be considered cheating if not authorized by the faculty member.
Examples of plagiarism include, but are not limited to, any attempt to take credit for work that is not your own, such as using direct quotes from an author without using quotation marks or indentation in the paper, paraphrasing work that is not your own without giving credit to the original source of the idea, or failing to properly cite all sources in the body of your work. This includes use of complete or partial papers from internet paper mills or other sources of non-original work without attribution.
A faculty member may further define academic dishonesty, cheating or plagiarism in the course syllabus.
- Campus Health Guidelines for COVID-19
Follow College COVID-19 safety guidelines: https://www.jccc.edu/media-resources/covid-19/
- Stay home when you're sick
- Wash hands frequently
- Cover your mouth when coughing or sneezing
- Clean surfaces
- Facial coverings are available and welcomed but not required
- Wear yoru name badge or carry your JCCC photo id while on campus
- College emergency response plan
- Student code of conduct policy
- Student handbook
- Campus safety
Information regarding student safety can be found at http://www.jccc.edu/student-resources/police-safety/. Classroom and campus safety are of paramount importance at Johnson County Community College and are the shared responsibility of the entire campus population. Please review the following:
- Report emergencies: to Campus Police (available 24 hours a day)
- In person at the Midwest Trust Center (MTC 115)
- Call 913-469-2500 (direct line) β Tip: program in your cell phone
- Phone app - download JCCC Guardian (the free campus safety app: www.jccc.edu/guardian) - instant panic button and texting capability to Campus Police
- Anonymous reports to KOPS-Watch - https://secure.ethicspoint.com/domain/en/report_company.asp?clientid=25868 or 888-258-3230
- Be Alert:
- You are an extra set of eyes and ears to help maintain campus safety
- Trust your instincts
- Report suspicious or unusual behavior/circumstances to Campus Police (see above)
- Be Prepared:
- Identify the red/white stripe Building Emergency Response posters throughout campus and online that show egress routes, shelter, and equipment
- View A.L.I.C.E. training (armed intruder response training - Alert, Lockdown, Inform, Counter and/or Evacuate) β Student training video: https://www.youtube.com/watch?v=kMcT4-nWSq0
- Familiarize yourself with the College Emergency Response Plan (https://www.jccc.edu/student-resources/police-safety/college-emergency-response-plan/)
- During an emergency: Notifications/Alerts (emergencies and inclement weather) are sent to all employees and students using email and text messaging
- students are automatically enrolled, see JCCC Alert - Emergency Notification (https://www.jccc.edu/student-resources/police-safety/jccc-alert.html)
- Weapons policy: Effective July 1, 2017, concealed carry handguns are permitted in JCCC buildings subject to the restrictions set forth in the Weapons Policy. Handgun safety training is encouraged of all who choose to conceal carry. Suspected violations should be reported to JCCC Police Department 913-469-2500 or if an emergency, you can also call 911.
- Report emergencies: to Campus Police (available 24 hours a day)
Course catalog info
Objectives:
- Describe computer systems and examine ethics.
- Solve problems using a disciplined approach to software development.
- Utilize fundamental programming language features.
- Implement procedures.
- Employ fundamental data structures and algorithms.
- Write code using object-oriented techniques.
- Write code according to commonly accepted programming standards.
- Utilize a professional software development environment.
Content Outline and Competencies:
I. Computer Systems and Ethics
A. Describe basic software components.
- Describe operating systems.
- Describe high-level and machine languages.
- Describe compilers.
B. Examine ethics.
- Examine ethics in the context of software development.
- Examine the impact of ethics violations on software developers.
- Examine the impact of ethics violations on software users.
II. Problem-Solving in Software Development
A. Define the problem.
B. Develop a solution.
- Utilize top-down design.
- Consider previous problems and solutions.
- Reuse pertinent algorithms.
- Represent algorithms with pseudo-code.
- Identify input, output, processing and modules.
C. Code the solution.
D. Test the solution.
- Perform unit and integration testing.
- Select appropriate test data.
- Trace code by hand (desk-checking) and with a debugger.
- Evaluate code efficiency and simplicity.
III. Fundamental Programming Features
A. Declare and initialize variables and constants.
B. Use built-in operators to create expressions and statements.
- Write assignment statements.
- Create expressions with arithmetic, relational and logical operators.
- Use the conditional (ternary) operator.
- Evaluate expressions using rules of operator precedence.
- Compare strings and numeric types.
- Dereference and assign values to pointers.
C. Perform input and output.
- Retrieve data from the keyboard.
- Retrieve data from input files.
- Write data to the console window.
- Write data to output files.
D. Call built-in mathematical functions.
E. Implement type-casting.
F. Control program flow.
- Implement selection statements.
a. Write code with if, else and else-if statements.
b. Use switch statements.
c. Write nested selection statements.
- Implement repetition statements
a. Write while, for and do loops.
b. Create nested loops.
c. Analyze break and continue semantics.
G. Trap errors using selection or repetition.
IV. Procedures
A. Define and call functions with void and non-void return values.
B. Declare functions (prototyping).
C. Implement pass-by-value and pass-by-reference parameters.
D. Differentiate between actual and formal parameters.
E. Analyze and write elementary recursive code.
F. Analyze variable scope and lifetime.
G. Implement static variables.
V. Fundamental Data Structures and Algorithms
A. Implement single dimensional arrays.
- Implement an array of integers.
- Implement null-terminated strings.
B. Implement two-dimensional arrays.
C. Implement dynamic arrays.
- Use new and delete to manage memory.
- Declare pointers.
D. Search arrays.
- Implement sequential search.
- Implement binary search.
E. Sort arrays.
- Sort data using bubble sort.
- Sort data using selection sort.
- Sort data using insertion sort.
F. Implement structures.
G. Implement an array of structures.
VI. Object-oriented Programming
A. Write code using the built-in string class and associated methods.
B. Write code using the built-in vector class and associated methods.
C. Implement encapsulation and data abstraction by writing user-defined classes.
D. Differentiate between private and public access modifiers.
E. Hide member data.
F. Write accessors, mutators and other member functions that process member data.
G. Write code that utilizes objects.
H. Implement an array of objects.
VII. Code Standards
A. Create descriptive identifiers according to language naming conventions.
B. Write structured and readable code.
C. Create documentation.
VIII. Professional Development Environment
A. Write code using a professional, integrated development environment (IDE).
B. Utilize key editor features.
C. Debug code using the integrated debugger.
D. Include and use standard libraries.