CS 200: Concepts of Programming using C++ (Spring 2024 version)

Table of Contents

\newpage

topic-corecompsci.png

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

l1-contents.png

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

topic-setup.png

UNIT 00: Welcome & setup

πŸ…°οΈ Pre-test (PRETEST.202401.CS200)

❓ Unit 00 Setup - GitLab Username

πŸ“–οΈ 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.

    u00_WelcomeAndSetup_gatekeepingbaby.png

    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.

    u00_WelcomeAndSetup_justwork.png

    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.

    u00_WelcomeAndSetup_buildingblocks.png

    Roadmap

    u00_WelcomeAndSetup_roadmap.png

    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.

    u00_WelcomeAndSetup_search.png

    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:

    1. All course information is in one singular place
    2. At the end of the semester, you can download the entire course's "stuff" in a single PDF file for easy referencing later on
    3. 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
    4. 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?

    hit-computer.png

    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:
    1. What kind of program is needed to convert human-readable code into computer binary executables?
    2. Computer CPUs only understand what "language"?
    3. 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 using g++ from the PowerShell or other Shell/Terminal.
      • Running the a.out program using ./ in the PowerShell or other Shell/Terminal.
  • 2. A link (URL) to your u00_Welcome folder in your repository.
  • 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.

    creating_a_gitlab_account_register.png

    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.

    creating_a_gitlab_account_gotoprofile.png

    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.

    creating_a_gitlab_account_viewprofileurl.png

  • 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.

    accessing_your_gitlab_repo_repoview.png

    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.

    gitlab_download_zip.png

    After the zip file is downloaded, make sure to extract it to your hard drive.

    gitlab_zip_windows.png

    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.

    https://www.youtube.com/watch?v=gnq8VUGRV68

    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.

      mingw_webpage.png

      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.

      mingw_install1.png

      5. It will download some needed items. Click "Continue" once it's done.

      mingw_install2.png

      6. On the main installer page, click the checkbox next to the "mingw32-gcc-g++" option.

      mingw_install3.png

      mingw_install4.png

      7. Then, click on the "Installation" dropdown menu and select "Apply Changes".

      mingw_install5.png

      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.

      mingw_path.png

      10. Next, click on the Windows start bar and type in "Environment" and look for the option "Edit the system environment variables".

      windows_envar1.png

      11. In the System Properties screen, click on the "Environment Variables…" button.

      windows_envar2.png

      12. Highlight the Path field and then click the "Edit…" button.

      windows_envar3.png

      13. Paste your MinGW bin path into this editor then click "OK". You can then close out of the rest of the windows.

      windows_envar4.png

      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.

      installing_compiler_synaptic.png

      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.

  • Build and run a test program

    Within the project folder, in the u00_Welcome you'll find the file test-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".

    openterminal1.png

    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.

    terminal_build_cpp.png

    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:

    terminal_run_cpp.png

    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 the world 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:

    terminal_build_cpp2.png

  • 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.

    gitlab_web_editfile1.png

    Next, you can click on the "Edit" dropdown menu. Select "Edit single file".

    gitlab_web_editfile2.png

    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.

    gitlab_web_editfile3.png

    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".

    gitlab_web_upload1.png

    Select the file to upload, add a comment about the file, and click Upload file.

    gitlab_web_upload2.png

    Your file will now be in the repository.

    gitlab_web_upload3.png

    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.

    gitlab_web_editfile5.png

    In Canvas, locate the assignment with the matching name. Click on the "Start Assignment" button.

    canvas-start2.png

    Next, make sure you're on the Website URL tab. Paste in the file's URL that you just copied, then click "Submit Assignment".

    canvas-submit.png

    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

πŸ“–οΈ 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).

    c2_u01_inputoutput.png

    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.

      c2_u01_variables.png

      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 or cartTotal, 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:

      c2_u01_branching.png

      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 some amount of money from the bankBalance.

      c2_u01_looping.png

      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;
      
  • 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!";
              }
          }
        
  • Diagnosing, testing, and debugging

    c2_u01_debugging2.png

    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.

    • 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:

      1. Programs take in __ and return __.
      2. Variables are used to…
      3. Branching is used to…
      4. Loops are used to…

πŸ”Ž 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 becomes 72 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

    tec01_ExploringSoftware_vic20.png

    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.

    tec01_ExploringSoftware_vic20box.jpg

    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

    tec01_ExploringSoftware_Macintosh.png

    Figure 8: Original Apple Macintosh desktop sample, unattributed (File:Apple_Macintosh_Desktop.png)

    tec01_ExploringSoftware_Windows.png

    Figure 9: Screenshot of Microsoft Windows 1.0 operating environment showing MS-DOS Executive and other applications, screenshot taken by Remember the dot. (File:Windows1.0.png)

    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

    tec01_ExploringSoftware_Phone.png

    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.

    tec01_ExploringSoftware_Burger.png

    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:

    1. 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.
    2. Play at least two of the following games for at least a few minutes:
    3. 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

πŸ‹οΈ 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.

nonogram-01.png

Hint: Among Us

nonogram-02.png

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

🧠 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))

    Used_Punchcard_(5151286161).jpg

    Figure 11: By Pete Birkinshaw from Manchester, UK - Used Punchcard, CC BY 2.0, index.php?curid=49758093Used_Punchcard_(5151286161).jpg

    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.

    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.

    vic20.jpg

    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 - The ping 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, use ping 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 - The mkdir (make-directory) program allows you to create 1 or more folders within the directory that you're currently in.
    • ls - The ls (list) program shows you all the files and folders in the directory that you're currently in.
    • pwd - The pwd (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

UNIT 03: C++ basics

πŸ“–οΈ 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 the main 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 have return 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 like return 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 the return 0;, but the code given above is the absolute, bare-minimum required to write a C++ program.

    Review:

    1. What function is the starting point of every C++ program?
    2. What is a code-block?
    3. 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:

    1. When should a line of code end with a semicolon ;, and when will it have a code block {} instead?
    2. How do you write a single-line comment?
    3. How do you write a multi-line comment?
    • Syntax errors and logic errors

      c2_u01_debugging2.png

      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

      coding-strategy.png

      • 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.

  • Review questions
    1. What are syntax errors?
    2. What are logic errors?

  • Variables and data

    c2_u01_variables.png

    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 or false 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.

  • Declaring variables and assigning values to variables

    Variable declaration

    When we're declaring a variable, it needs to follow one of these formats:

    1. DATATYPE VARIABLENAME;
    2. DATATYPE VARIABLENAME = VALUE;
    3. DATATYPE VARIABLENAME1, VARIABLENAME2, VARIABLENAME3;
    4. 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

    1. VARIABLENAME = LITERAL; - Stores the LITERAL value in VARIABLENAME.
    2. 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;
    

    c2_u01_assignment1.png


    • 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 named userName (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 use auto, 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;
        

        c2_u01_cats.png

        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'
        

    • 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.

    c2_u01_terminal.png

    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.

    c2_u01_terminal-hi.png

    • 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 that cout statement and the next one. For example, if we write two cout 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; and getline(cin, var);

        If you mix cin >> var; and getline(cin, var);, you might encounter issues with the input buffer. To avoid this, use cin.ignore(); before getline(cin, var); if you used cin >> 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!
        

  • Review questions
    1. What is the output stream operator?
    2. 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.

    lab_u03_CPPBasics_StarterCode1.png

    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:

    1. Replace NAME with your name
    2. Replace COLOR with your favorite color
    3. 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:

    1. Replace NAME with your name
    2. Replace COLOR with your favorite color
    3. 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 and num2. The program already contains some cin statements to get values into unm1 and num2.

    There are also four "results" float variables declared: sum, difference, product, and quotient. Under teach comment that says TODO, write down a math operation:

    1. Add num1 and num2 and store the result in the sum variable.
    2. Subtract num1 and num2 and store the result in the difference variable.
    3. Multiply num1 and num2 and store the result in the product variable.
    4. Divide num1 and num2 and store the result in the quotient 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:

    1. Declare a float variable named width
    2. Declare a float variable named length
    3. Display a message to the user, saying "Enter a width:"
    4. Get input from the keyboard, store the result in the width variable
    5. Display a message to the user, saying "Enter a length:"
    6. Get input from the keyboard, store the result in the length variable
    7. Declare a float variable named perimeter, assign it the result of 2 * width + 2 * length
    8. Declare a float variable named area, assign it the result of width * length
    9. Display "Perimeter:" and then the value of the perimeter variable
    10. 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 and int 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:

    1. Declare an integer varaible named slices_per_person.
    2. Calculate how many slices of pizza each guest gets, assign the result to the slices_per_person variable. (the math here is pizza_slices / guest_count.)
    3. Display "Total guests:" and then the guest_count variable.
    4. Display "Total slices of pizza:" and then the pizza_slices variable.
    5. Display "Each guest gets", then the slices_per_person, then "slices of pizza".
    6. 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 and pizza_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.


  • Turning in your work:

    On your GitLab page, go into the u03_CPPBasics folder, and then into whichever program folder you want to update:

    lab_u03_CPPBasics_Turnin1.png

    Click on your program's .cpp file to open it, then click "Edit" and "Single file":

    lab_u03_CPPBasics_Turnin2.png

    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).

    lab_u03_CPPBasics_Turnin3.png

    After you've updated all the files you want to edit,

    lab_u03_CPPBasics_Turnin4.png

    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:

    lab_u03_CPPBasics_Turnin5.png

πŸ‹οΈ 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.

nonogram-03.png

Hint: Happy

nonogram-04.png

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.

      project1_geanynewfile.png

      • This will create a new empty file for us.

      project1_geanyemptyfile.png

      • 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".

      project1_geanysavefile.png

      Now we can get started on our program.


  • 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:

    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

    project1_diagram1.png

    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, but 11ozVanilla 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.

      project1_backup1.png

      • No files are here yet. Click on the "+" button, then click "Upload new file".

      project1_backup2.png

      • 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.

      project1_backup3.png

      • 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

    project1_diagram2.png

    • 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.

      project1_backup1.png

      • Our "project1.cpp" file should be here. Click on it.

      project1_backup4.png

      • Click on the "Edit" button, then click "Edit single file".

      project1_backup5.png

      • 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.

      project1_backup6.png

      Now you can return to your code editor (like Geany) and start on version 3.


  • Recipe program version 3 - arithmetic

    project1_diagram3.png

    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:

      1. Declare a new float variable. Its name should be batches.
      2. Display a message to the user using the cout command. Ask: How many batches to make?
      3. Get input from the keyboard using the cin >> command. Store the user's answer in the batches variable.

    • 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:

      1. Go to your GitLab repository and click on the "PROJECTS" folder.
      2. Click on your "project1.cpp" file.
      3. Click on the "Edit" button, then click "Edit single file".
      4. Copy and paste your code from "project1.cpp" on your computer into the editor on GitLab.
      5. Add a "commit message" like "Project 1 FINAL VERSION".
      6. Click "Commit changes" to finish.

      We're not done with GitLab yet, let's look around before finishing up the assignment.


  • Exploring your file's history
    • From your file's page on GitLab, click on the "History" button.

    project1_gitlabexplore1.png

    • This shows a list of all the changes you've made to this file, including those commit messages that describe what was updated.

    project1_gitlabexplore2.png

    • 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.

    project1_gitlabexplore3.png


  • Turning in the assignment
    • On the GitLab webpage go to your "project1.cpp" file. Copy the URL of this file.

    project1_turnin1.png

    • 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.

    project1_turnin2.png

    Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3907325

WEEK 4 - FEB 12

UNIT 04: Control flow - Branching and looping

πŸ“–οΈ 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"

    reading_u03_CPPBasics_cat.png

    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 and b 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.


    • 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:

        1. \(p\) is true and \(q\) is true.
        2. \(p\) is true and \(q\) is false.
        3. \(p\) is false and \(q\) is true.
        4. \(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:

        1. gameSaved is true and wantToQuit is true: Quit the game. βœ…
        2. gameSaved is true and wantToQuit is false: The user doesn't want to quit; don't quit. ❌
        3. gameSaved is false and wantToQuit is true: The user wants to quit but we haven't saved yet; don't quit. ❌
        4. gameSaved is false and wantToQuit 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:

        1. hasCake is true and hasIcecream is true: The store has desserts; suggest it to the user. βœ…
        2. hasCake is true and hasIcecream is false: The store has cake but no ice cream; suggest it to the user. βœ…
        3. hasCake is false and hasIcecream is true: The store has no cake but it has ice cream; suggest it to the user. βœ…
        4. hasCake is false and hasIcecream is false: The store doesn't have cake and it doesn't have ice cream; don't suggest it to the user. ❌

    • 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:

        1. \(a\) is false and \(b\) is true, or
        2. \(a\) is true and \(b\) is false, or
        3. \(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:

        1. 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.


    • 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.

      reading_u04_ControlFlow_evilbug.png


  • 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/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 the result variable to "can't vote". If that boolean expression is false, that means age is \(\geq\) 18, and then it will set the result to "can vote". Finally, either way, it will display "Result: " with the value of the result 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 means grade < 90. Since the next statement checks if grade > 80=, if this one is true I know that grade < 90 AND grade > 80=.


  • 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
            }
        }
      

  • 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; statement

    The end of each case should have a break; statement at the end. If the break 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 called operation and then use the switch 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:
    1. A boolean expression can be…
    2. What do each of these expressions represent?
      1. b
      2. !b
      3. a = b=
      4. a > b
      5. a = b
    3. What are each of the following operators?
      1. &&
      2. ||
      3. !
    4. When does the expression a && b evaluate to true? false?
    5. When does the expression when a || b evaluate to true? false?
    6. An if statement's code block will be executed when the if statement's condition evaluates to…
    7. 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)
  • 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 variable remaining.
  • 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 the if 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 and printer_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 and translated. Initialize english 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, set translated to one of the values below.
  • After the switch statement, display the english word and the translated 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 to years. 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 and updated_salary.
    • Increment current_year by 1 before the end of the while loop.
  • 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 to a
    • Long way: a = a + 1; will do the same thing.

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
    1. Go to your GitLab webpage.
    2. Select the folder for this unit in the main view. Locate the file you want to update and click on it.
    3. Click on the blue "Edit" button, then click "Edit single file".

      gitlab_web_editfile2.png

    4. 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.
    5. Go back to the unit folder and COPY the URL for this unit.

      gitlab_web_editfile5b.png

    6. On Canvas, locate the assignment. Click "Start assignment".
    7. Paste the copied URL into the box and click "Submit assignment".

      canvas-submit.png

🧠 Tech Literacy - Filesystems (U04.TEC)

  • Before computers

    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

      tec_u04_Filesystems_File.png

      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.

      tec_u04_Filesystems_FileScreenshot.png

      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:

      tec_u04_Filesystems_TextDocument.png

      For an image file, its contents is data about the image itself - what color is at each position.

      tec_u04_Filesystems_PngDocument.png

      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:

      tec_u04_Filesystems_HtmlDocument.png

      And a C++ program's code can be opened in a text editor:

      tec_u04_Filesystems_CppDocument.png

      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

      tec_u04_Filesystems_Folder.png

      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:

      tec_u04_Filesystems_Tree.png

      A screenshot of several folders opened up on my computer:

      tec_u04_Filesystems_FolderTree.png

      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.


  • 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/

      tec_u04_Filesystems_TreeView.png

      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.


  • 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.

nonogram-05.png

Hint: Love

nonogram-06.png

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

πŸ“–οΈ Reading - Structs (U05.READ)

  • Introduction to objects

    reading_u05_Structs_menuitems.png

    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.

  • 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

    reading_u05_Structs_structfiles.png

    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;
      }
      

  • Review questions:
    1. File guards are needed because…
    2. 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
    3. If we declared an object variable like Course cs200; , How would we assign "cs" to the department member variable and 200 to the code 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
    1. Go to your GitLab webpage.
    2. Select the folder for this unit in the main view. Locate the file you want to update and click on it.
    3. Click on the blue "Edit" button, then click "Edit single file".

      gitlab_web_editfile2.png

    4. 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.
    5. Go back to the unit folder and COPY the URL for this unit.

      gitlab_web_editfile5b.png

    6. On Canvas, locate the assignment. Click "Start assignment".
    7. Paste the copied URL into the box and click "Submit assignment".

      canvas-submit.png

πŸ‹οΈ 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.

nonogram-07.png

Hint: Tree

nonogram-08.png

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

πŸ“–οΈ Reading - Functions (U06.READ)

reading_u06_Functions_image.png

  • Program Structure

    errorinmain.png

    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.

    reading_u06_Functions_functioncall.png

    reading_u06_Functions_programbreakout.png


  • 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 );
      

      nocomp.png


      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.

      badcode.png


    • 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 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 the width and height variables being passed in. Once GetArea returns its output, that output is then stored in the area 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 within room1Width is copied from that variable and stored in the parameter variable width within the function's definition.

        Common function errors:

        1. 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 );
        2. Functions must have parentheses ()! If you're missing the parentheses, your program isn't going to call the function!
          • YES: DisplayMenu();
          • NO: DisplayMenu;
        3. 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 );

  • 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 of main(), 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 in Example( 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 the Example function changes (which is valid), that change doesn't affect myNumber 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.

      copyparameter.png


    • 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
      1. X is pass-by-value, which is fine for primitive data types like ints, floats, chars, and bools.
      2. X is passed by const-reference because X is a mose sophisticated data type like a string or other class-based object. (Longer time to copy if passed by value.)
      3. 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.

  • 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:
    1. 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
    2. 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 );
        
    3. 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…

πŸ”Ž 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
  • To run the program:
    • Windows: .\a.exe
    • Linux/Mac: ./a.out

  • 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, and GetPricePlusTax 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():

    1. Create a float variable to store a new price.
    2. Ask the user to enter the price of the new item.
    3. Get their input and store it in your float variable.
    4. return your float variable at the end.

    int GetChoice( int min, int max ):

    1. Create an integer variable to store the user's input.
    2. Ask the user to enter a number.
    3. Get their input and store it in your integer variable.
    4. WHILE their input is less than min OR greater than max, do:
      1. Display an error message ("Outside valid range!")
      2. Get the user's input again and store it in your integer variable (the same one).
    5. 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 the transaction_total. (DON'T use a cout on this line!)
      • Call the DisplayMenu function.
      • Call the GetChoice function passing in 1 and 2 as the arguments. Store the return data in the choice variable.
      • If choice is 1:
        1. Call the GetNewPrice function and store its return data in the new_price variable.
        2. Add new_price to the transaction_total, making sure to update the transaction_total's value.
      • Otherwise if choice is 2:
        1. Set running to false so that the loop will end and the program will continue.
    • After the while loop is over, display the text "RECEIPT".
    • Call the GetPricePlusTax function, passing in transaction_total and GetTaxPercent() as its arguments. Store its return data in the final_price funnction.
    • Display "Transaction total:".
    • Call DisplayFormattedUSD, passing in the transaction_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 the final_price. (Do not use cout here.)
    • Finally, return the final_price at the end of this function.

  • 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):

      project2_newfile.png

      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:

      project2_files.png

      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":

      project2_newdirectory.png

      Name the new folder "project2" and click "Create directory":

      project2_newdirectory2.png

      project2_newfolder.png

      Go into the folder, then click the "+" button again and choose "Upload file":

      project2_uploadfile.png

      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:

      project2_projectdirectory.png

      They're currently blank, but we'll make backups as we complete each version of the program.



  • 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 string
    • amount, a float
    • unit, 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> and using 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 to false, or use the break; 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 a switch 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> and using 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 of recipe1_ing1.name, you can use ing1.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:

    1. Create an integer variable to store the user's input.
    2. Use a cin statement to get the user's input.
    3. While their input is less than min or greater than max, do:
      1. Display an error message. ("Selection is invalid!")
      2. Use cin to get the user's input again, store in the same input variable.
    4. 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 in main().

    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 the SetupRecipes 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 !!!


  • 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

WEEK 8 - MAR 11 - SPRING BREAK

Take a break!

WEEK 9 - MAR 18

UNIT 07: Strings

πŸ“–οΈ Reading - Strings (U07.READ)

reading_u07_Strings_image.png

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. The size_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!
    

    reading_u07_Strings_catsdogs.png

    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!
    

    reading_u07_Strings_wizard.png


  • 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 and petName, 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
    

    reading_u07_Strings_luna.png

    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 the findMeString within bigString, or the value of string::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 of len.

    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".
    

    reading_u07_Strings_bob.png


  • 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
    

    reading_u07_Strings_compare.png


  • 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 position pos.

    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 of len.

    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
    

  • Review questions:
    1. A string is technically an array of…
    2. How would you output the letter at position 0 in a string? At position 2?
    3. What function is used to get the amount of characters in a string?
    4. What operator is used to combine (concatenate) two strings together?
    5. 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 the position 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 the haystack; 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 and str2 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 and str2 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 the original string at the position 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 the position given, and going for length 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 at position, going for the length given, replacing the text with the insert_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)

    reading_u08_FileIO_image.png

    • Output streams

      In C++ we've been using cout to stream information to the console window in our programs. Using cout requires including the iostream 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 the ofstream (output-file-stream) object. Streaming out to a file works in the same way as with cout, except that we need to declare a ofstream 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 the getline() 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 the readNumber 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?"
        

    • 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 into gameFileName.
        • Else if firstWord is "LEVEL", then read the next word into level.

        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.


  • Review questions:
    1. What library is required in order to use file I/O in C++?
    2. What data type is used to create a file that inputs (reads in) text from an outside file?
    3. What data type is used to create a file that outputs (writes out) text to an outside file?
    4. How do you write out the string literal "Hello world" to an output file?
    5. How do you write out the value of a variable to an output file?
    6. How do you read in one word from an input file?
    7. How do you read in one line from an input file?

    https://canvas.jccc.edu/courses/68294/modules/items/3918408

  • πŸ”Ž 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:

      1. Create an ofstream object named output.
      2. Open the "results.txt" file.
      3. updated_salary has already been declared and initialized to 0.
      4. Write "Starting salary:" and the starting_salary to the output file.
      5. Use a for loop that goes from counter = 1 to years. With the loop:
        1. Update the salary: updated_salary = updated_salary + ( updated_salary * raise_per_year );
        2. Output the current information (counter and updated_salary) to the output file.
      6. 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:

      1. Create an input file stream (ifstream) object.
      2. Use the open function, passing in the filename variable instead of a hard-coded string.
      3. Call the input's fail function to see if opening the file failed. Display an error message and return ""; on failure.
      4. You'll probably want to create a string variable at this point to load data into.
      5. 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.)
      6. 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)

    reading_u06_Pointers_pointer.png

    • 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 or nullptr.

        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 used cout 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 pointer ptr that points to var'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 address 0x7ffc3d6028b0.
        • ptr stores its data at its address 0x7ffc3d6028b4.
        • var's value is 10, since it's an integer.
        • ptr's value is the address of var, since it's a pointer-to-an-integer.

        c2_u08_ptrmemory.png

      • 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 of var. Outputting ptr will give us var's address, and outputting *ptr (ptr dereferenced) will give us the value stored at var'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 through var or through the ptr, we can see that the value of var has been overwritten:

        cout << "var value:        " << var << endl;
        cout << "*ptr value:       " << *ptr << endl;
        
        var value:        20
        *ptr value:       20
        

    • 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 know nullptr means that the pointer is not pointing to anything.


    • Review questions:
      1. Given the variable declaration: int num = 10; What kind of memory is the num variable stored in?
      2. Given the variable declaration: int* num = new int; What kind of memory is the num variable stored in?
      3. How do you declare a pointer?
      4. How do you access the address of a variable?
      5. How do you assign the address of a variable to a pointer?
      6. How do you dereference a pointer to display the value of the address it's pointing to?
      7. How do you dereference a pointer to store a new value in the memory block pointed to?
      8. When a pointer is not currently in use, it should be initialized to…

    πŸ”Ž 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 and string for this program, so make sure to have #include <iostream>, #include <string>, and using 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

    • 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> and using 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, and int5.

      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.


    • 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 and string for this program, so make sure to have #include <iostream>, #include <string>, and using 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"

      my-cats.jpg

      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 because nullptr 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 the ptrStudent 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).


    • 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 to practice4_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; and ptrStudent = &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 and Project_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 the graded_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, and student3. It also contains a ptrVip pointer variable that is currently initialized to nullptr. This function takes in int vip, the student # who is VIP, and returns a string, 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 parameter Address to point ptrVip to
      1 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 to nullptr, then return the string literal "UNKNOWN". Otherwise, dereference the ptrVip 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.

    nonogram-09.png

    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.

    • Arrays

      reading_u10_ArraysVectors_Title.png

      • 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] or student[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 1 2 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 an array object instead of a traditional array to store data. They are basically interchangible, ecxept the array object gives us access to the .size() function, making our job slightly easier. However, the array 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 of student for each element.

        for ( auto & student : students )
        {
          cout << student << endl;
        }
        

    • Review questions:
      1. What are the 3 parts of a for loop's header?
      2. Do all items in an array need to be the same data type in C++?
      3. What is an element of an array?
      4. What is an index?
      5. The subscript operator is…
      6. What code would you write to display the item at position 0 in an array?
      7. What code would you write to display the item at position 2 in an array?
      8. Given an array of size \(n\), the valid indices of the array are…
      9. 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 a high 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 the low value.
      • The condition is to keep looping while i is less than or equal to the high 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 the high value.
      • The condition is to keep looping while i is greater than or equal to the low 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 the low value.
      • The condition is to keep looping while i is less than or equal to the high value.
      • The update action is to multiple i by 2 each time and assign it back to the i variable: i*=2;

    • 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 than ARRAY_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 a cin 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 by my_classes[i]) in a nice format.


    • 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 of ARRAY_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 the break; command to exit the loop.
        • Otherwise (else), use the vector's push back function to add the new class: my_classes.push_back( input );
      • After the while loop, use the for loop to display all the items in the my_classes vector. Use my_classes.size() for the size.

    • 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 a string name and float 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:

      1. Create an integer named index.
      2. Ask the user what they weant to eat. Use a cin statement and store their response in the index variable.
      3. Display the name and price of what they chose. Use product_list[index].MEMBER to access each member variable (name and price) in your cout statement.

    • 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 of char items called course_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 the total 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 of Recipe 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 old SetupIngredientsForRecipe1 type functions we will call the LoadRecipes() 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 of Ingredient 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:

            1. Create a Recipe struct
            2. Create a Recipe object variable in main()
            3. Update the program to use the Recipe struct
              1. Update DisplayRecipe to take a Recipe item
              2. Don't need the SetupIngredientsForRecipe functions anymore
            4. Use the LoadRecipes function to load the recipes in from recipe-data.txt - this goes at the BEGINNING of the program.
            5. Use the SaveRecipes function to save the recipes to recipe-data.txt - this goes at the END of the program.


        • 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:

          1. int GetChoice( int min, int max )
          2. void MainMenu( vector<Recipe>& recipes )
          3. void ViewRecipesMenu( vector<Recipe>& recipes )

          The GetChoice function:

          • Output return type: Integer, the user's valid input
          • Input parameters:
            • int min, the minimum valid choice
            • int 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; and while( 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:

          1. Initialize running to true.
          2. While running is true, do the following:
            1. Display the header "RECIPES".
            2. Use a for loop to display a list of all recipe names.
            3. Display the header "MAIN MENU"
            4. Display options listed in the example output:
              • 0. Quit program
              • 1. View recipe
              • 2. Save recipes to text file
              • 3. Add new recipe
            5. Ask the user where they want to go. Get their input with the GetChoice function, store the result in an integer variable.
            6. Use an if statement or switch statement to determine what to do based on their decision:
              • Choice was 0, set running to false.
              • Choice was 1, call ViewRecipesMenu function, pass in the recipes variable.
              • We will work on Choice 2 and Choice 3 later!
          3. 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:

          1. Draw the header, "VIEW RECIPE".
          2. Use a for loop to display each recipe's index (+1) and name.
          3. Ask the user which recipe to display, use the GetChoice function and store it in a variable.
          4. If their choice was 0, you can use return; to exit this menu early.
          5. Otherwise, you can get the index of the recipe by taking the user's choice minus 1.
          6. Also ask the user how many batches they'd like to make and store it in a float variable.
          7. Call the DisplayRecipe function, passing in the recipes 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:

          1. Display header "NEW RECIPE"
          2. Create a new Recipe object named new_recipe
          3. Create a new Ingredient object named new_ing
          4. Ask the user to enter the recipe's name. Store it into new_recipe.name.
          5. Ask the user to enter the recipe's URL. Store it into new_recipe.url
          6. Create an integer named total_ings.
          7. Ask the user how many ingredients there are. Store their answer into total_ings.
          8. Create a for loop, iterating from i equals 1 to total_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 its push_back function, passing in new_ing.
          9. After the for loop is over, use the recipes' push_back function, passing in the new_recipe.

          Calling the function:

          Within the MainMenu function, when the user selects "3. Add new recipe" from the main menu, then call the AddNewRecipeMenu function, passing in the recipes 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:

          1. Display header "PRINT RECIPES"
          2. Ask the user to enter a filename. Store their response in a string variable, such as filename.
          3. Create an ofstream variable named output. Open the filename given.
          4. 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, and name to the text file.
          5. 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 the PrintRecipesMenu function, passing in the recipes vector.

          Turn in: https://canvas.jccc.edu/courses/68294/modules/items/3948052

    WEEK 12 - APR 8

    UNIT 11: Classes

    πŸ“–οΈ Reading - Classes (U11.READ)

    reading_u11_Classes_titleimage.png

    • 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.

      • 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.

        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 the Movie 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 a MovieLibrary variable for our single library - or, we could make an array of MovieLibrary 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 the Setup() function for the next Movie 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:

        reading_u11_Classes_LibraryDiagram.png


      • Additional OOP examples

        Here are a few more examples of using object oriented design in different types of programs:

        Video game

        reading_u11_Classes_Game.png

        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

        reading_u11_Classes_Campus.png

        A college could be separated into multiple different objects, where a College might have different Campuses (such as KU-Lawrence, KU-Edwards or the different MCCKC campuses), and each campus has an array of different Departments (CSIS, MATH, ENG, etc.), each department has an array of Teachers and an array of Courses. A course would generally have one Teacher and an array of Students.

        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.


    • 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 is private 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.


    • 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 want x 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 a GetName 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.

          reading_u11_Classes_ShallowCopy.png

          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.

          reading_u11_Classes_DeepCopy.png

          Example of a deep copy: A new block of memory has been allocated for the int * numArr. The values from InstanceA's numArr would be copied to InstanceB's numArr via a for loop during construction.


      • 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 room name, width, and length, and a House, which contains an array of rooms. In the main() 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, and length 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.


    • 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 the this 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() and C() do the same thing, but B() explicitly uses this.


    • Review questions:
      1. True or false: A class can have member variables and functions (methods).
      2. Class declarations go in what kind of file?
      3. Class function (method) definitions go in what kind of file?
      4. A class' public members can be accessed by…
      5. A class' protected members can be accessed by…
      6. A class' private members can be accessed by…
      7. When defining a function that is a member of a class, the function name needs to be prefixed with…
      8. What does a getter (accessor) function do?
      9. What does a setter (mutator) function do?
      10. When does a constructor function run?
      11. When does a destructor function run?
      12. 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.

    πŸ‹οΈ 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.

    nonogram-10.png

    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()

        reading_u12_Inheritance_FileTypes.png


      • The iostream and fstream

        reading_u12_Inheritance_iosfam.png

        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 and cout, and our file input/output streams, ifstream and ofstream. Working with each of these works largely the same way.

        When we overload the << and >> stream operators, we use a base type of istream and ostream so that our class can handle cin / cout AND ifstream / 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:

        reading_u12_Inheritance_apple.png

        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…

        reading_u12_Inheritance_brick.png

        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(...)  

        reading_u12_Inheritance_player.png

        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.

        reading_u12_Inheritance_npc.png

        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:

        reading_u12_Inheritance_objectree.png

        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.

        reading_u12_Inheritance_screenshot.png


    • 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;
        };
        

    WEEK 13 - APR 15

    UNIT 13: Searching and sorting

    πŸ“–οΈ Reading - Searching and sorting (U13.READ)

    • Introduction to searching and sorting

      reading_u09_SearchSort_algorithms.png

      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

      reading_u09_SearchSort_goose.png

      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


    • 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

    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

    πŸ“–οΈ Reading - Recursion (U14.READ)

    reading_u08_Recursion_recursionB.png

    • 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.

        reading_u08_Recursion_recursivefactorial.png


    • 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:

        1. 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\).
        2. 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

        reading_u08_Recursion_recursionstress.png

        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? Since amount is the one parameter we have, let's have the recursion stop once it is 0. Each time we recurse, we can pass in amount-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 and end 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

          reading_u08_Recursion_filesystem.png

          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:"
          reading_u08_Recursion_traverse1.png reading_u08_Recursion_traverse2.png reading_u08_Recursion_traverse1.png
          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"
          reading_u08_Recursion_traverse3.png reading_u08_Recursion_traverse4.png reading_u08_Recursion_traverse5.png
          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.
          reading_u08_Recursion_traverse6.png reading_u08_Recursion_traverse8.png reading_u08_Recursion_traverse9.png
          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:"  
          reading_u08_Recursion_traverse10.png reading_u08_Recursion_traverse11.png  
          Return Recursion. Return Recursion.  

          For find functionality, terminating cases would be:

          1. Have we found the item? Return it.
          2. Are we out of places to search? Return nothing.

          And the recursive case would be:

          1. Has a subfolder? Call Find() on that folder.

    • Review questions:
      1. Recursion of a means of problem solving that…
      2. Each recursive function needs at least one … case and at least one … case.
      3. 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?

      4. 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

    l1-about.png

    About

    About this book

    book-cute-center.png

    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

    about-course-center.png

    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

    rachel1.png

    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:

    \newpage

    Reference

    Basic Computer Skills

    • Basic computer skills

      How to take a screenshot

      computer_skills_printscreen.jpg

      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

      computer_skills_extensions.png

      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: computer_skills_workingdir_visualstudio.png

      Code::Blocks: computer_skills_workingdir_codeblocks.png

      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.


    • 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 with m_ 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, not void 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.
        • 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.
        • NEVER USE GLOBAL VARIABLES.
        • NEVER USE goto STATEMENTS.

    • 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 is Product.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 Windows

      Prefer 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 of pragma 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 return true, 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 a cin.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 and else if statements are false, then else 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 an unsigned int, which allows values of 0 and above - no negatives.

    • File I/O

      Make sure to have #include <fstream> in any files using ifstream or ofstream!

      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?
      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!!
      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 using ifstream or ofstream.
    • 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 actually C:\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.
      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.
      • codeblocks-compiler.png
      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.
      • reference-cannotfind.png
      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.
      • xcode-working-directory.png
    • 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-specifybranch.png
      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 your git push after the merge.
      • git-pushfail.png
      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-notarepo.png
      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.
      • permission-denied.png

    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:
      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:
      Go to declaration, definition, and find references:

    • 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:
      Go to declaration, definition, and find references:

    • 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:
      Add an EXISTING file to 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:
      Opening code windows side-by-side:
      Go to declaration, definition, and find references:

    Archive - Video links

    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.

    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:
      1. In person in the classroom during class time
      2. Remotely via Zoom during class time
      3. 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
      1. Textbook: Rachel's CS 200 course notes (https://moosadee.gitlab.io/courses/202401_Spring/book_corecpp.html)
      2. Zoom: Needed for remote attendance / office hours
      3. 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.
      4. Accounts: See the UNIT 00 SETUP assignments for steps on set up.
      5. 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:

      1. Be sure to let me know WHICH ASSIGNMENT IT IS, the specific assignment name, so I can find it.
      2. Include a SCREENSHOT of what's going wrong.
      3. What have you tried so far?

    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:

      1. Attending class in person during the class times, or
      2. Attending class remotely via Zoom during class times, or
      3. 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.

    • 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:

      1. Watch lecture videos, read assigned reading.
      2. Work on Concept Introduction assignment(s).
      3. 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:
      • During an emergency: Notifications/Alerts (emergencies and inclement weather) are sent to all employees and students using email and text messaging
      • 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.

    Course catalog info

    Objectives:

    1. Describe computer systems and examine ethics.
    2. Solve problems using a disciplined approach to software development.
    3. Utilize fundamental programming language features.
    4. Implement procedures.
    5. Employ fundamental data structures and algorithms.
    6. Write code using object-oriented techniques.
    7. Write code according to commonly accepted programming standards.
    8. Utilize a professional software development environment.

    Content Outline and Competencies:

    I. Computer Systems and Ethics

    A. Describe basic software components.

    1. Describe operating systems.
    2. Describe high-level and machine languages.
    3. Describe compilers.

    B. Examine ethics.

    1. Examine ethics in the context of software development.
    2. Examine the impact of ethics violations on software developers.
    3. Examine the impact of ethics violations on software users.

    II. Problem-Solving in Software Development

    A. Define the problem.

    B. Develop a solution.

    1. Utilize top-down design.
    2. Consider previous problems and solutions.
    3. Reuse pertinent algorithms.
    4. Represent algorithms with pseudo-code.
    5. Identify input, output, processing and modules.

    C. Code the solution.

    D. Test the solution.

    1. Perform unit and integration testing.
    2. Select appropriate test data.
    3. Trace code by hand (desk-checking) and with a debugger.
    4. 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.

    1. Write assignment statements.
    2. Create expressions with arithmetic, relational and logical operators.
    3. Use the conditional (ternary) operator.
    4. Evaluate expressions using rules of operator precedence.
    5. Compare strings and numeric types.
    6. Dereference and assign values to pointers.

    C. Perform input and output.

    1. Retrieve data from the keyboard.
    2. Retrieve data from input files.
    3. Write data to the console window.
    4. Write data to output files.

    D. Call built-in mathematical functions.

    E. Implement type-casting.

    F. Control program flow.

    1. Implement selection statements.

    a. Write code with if, else and else-if statements.

    b. Use switch statements.

    c. Write nested selection statements.

    1. 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.

    1. Implement an array of integers.
    2. Implement null-terminated strings.

    B. Implement two-dimensional arrays.

    C. Implement dynamic arrays.

    1. Use new and delete to manage memory.
    2. Declare pointers.

    D. Search arrays.

    1. Implement sequential search.
    2. Implement binary search.

    E. Sort arrays.

    1. Sort data using bubble sort.
    2. Sort data using selection sort.
    3. 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.

    Author: Rachel Wil Sha Singh

    Created: 2024-04-15 Mon 10:56

    Validate