Skip to main content

Project 0: Simple Cipher

1348 words
Table of Contents

out of 100 points, 110 points hard cap

In this project, you will decrypt simple but uncommon cipher, which encodes a secret message in seemingly normal text. Given the encrypted message, the most frequent character of each line is a character of the original message. Each message will be preceded by a number on its own line, telling you how many lines are in the input.

Let’s look at the following text:

7
Unlike you I take umbrage with gnu!
To think and code well tantalizes the mind.
birds fly together and chirp.
George Orwell was wrong about 1984.
Can your cat code?
Kick the kilos.
snakes sneakily slither.
AAAaaaaAaaAaAAaaaaaaa!!!!!!

For this text, the output would be

u 4
t 5
r 3
o 4
c 3
k 3
s 4

Note that the last line is discarded because the initial line indicated that we should only use seven lines of input.

Description
#

Your program should read text from the standard input. For each line read, you should print out the most frequent character and its frequency to standard output. All characters should be printed out in lowercase. Here are additional rules to (hopefully) keep things simple:

  • Uppercase and lowercase characters are treated as the same, that is, “O” and “o” both contribute to the count of the letter “o”.
  • You may ignore punctuation and whitespace
  • If a line has no counted characters on it (e.g. is all punctuation or whitespace), ignore it and move on to the next one.
  • Ties should be resolved by picking the lowest valued ASCII character.

Direction and Hints
#

Reading Input
#

Before you start to code the main logic, first make sure you are able to get the input task working. Your first step should be to get your program to read the input. There are many ways to read text in C++, but the simplest approach for this program uses std::getline:

    std::string line;
    while (std::getline(std::cin, line)){
        // process the line
    }

std::getline reads a single line from std::cin (standard input) until there is no more input, at which point it will return false and the loop will terminate. The variable line holds the contents of the current line inside the loop body.

The std::string class has a lot of functions to access the characters, so read the documentation, talk to your peers, and ask questions on Piazza, in class, and at office hours!

Counting Letter Frequency
#

You should write a function that takes a std::string and returns the most frequent letter character, or some special character if the line is blank or only has non-letters. You may find the following functions useful: std::isalpha and std::tolower. You can write a separate function that takes a std::string and a character, and returns the number of times the character appears in the line.

Testing
#

When testing in interactive mode, your code may print one result for every line you enter. This can be a little hard to read. Instead, I suggest you pass your test case as a single block to echo, then pipe it to your test executable. For example,

echo "Let's get down to business
To defeat the Huns" | myprogram

This will make it easier to view your output, and is how your executable will be tested when actually grading.

A Note About std::string and const char*
#

Due to compatibility reasons dating all the way back to the 1970’s (no really!), C++ has two different string types: the std::string and the char * (sometimes shown as a char[] or a const char*)1. While we won’t dive too much into the details in this class, in modern C++, it’s considered good style to work with std::string as much as possible.

If you find that you have one of the following types:

  • const char*
  • char[]
  • char*

and would like to convert it into an std::string, you can wrap it in a constructor call, e.g. std::string my_str(my_char_arr).

Conversely, if you have an std::string and need to convert it into a char* for use with older library functions, use the c_str() method of std::string, e.g. char* my_char_ptr = my_str.c_str().

Submission And Grading
#

Make sure to read the general project grading rules.

For this project, you will need to submit two files: a cpp file and a README. In future projects, there will be skeleton code provided–for those, you will just submit your modifications to the skeleton code.

C++ File
#

The C++ file, as with all our projects, must compile with no warnings. Since warnings and errors vary between compilers and OSses, I will be using the basement lab computers to compile your code. The following command will be used on the basement computers:

clang++ --std=c++11 -Wall -Wextra -Werror -o project0 project0.cpp

If you code does not compile, you may receive zero points for this assignment.

README File
#

The README should include the following information:

  • Your name
  • Your EID
  • The number of slip days you’re using on this project
  • The number of slip days you’ve used in the course so far
  • Any stretch goals you attempted, and how to enable them in your code

Other Notes About Grading
#

You should submit a single tarball called project0.tar.gz which contains a folder inside called project0. Inside project0 should be a single source file called project0.cpp and your README.

I should be able to do the following in an automated manner:

  tar -xf project0.tar.gz
  cd project0
  clang++ --std=c++11 -Wall -Wextra -Werror -o project0 project0.cpp
  ./project0
  <test input>

If you have any questions about the assignment, please ask on Piazza.

Stretch Objectives
#

If you finish the project early and have time to burn, you might consider trying one of these stretch goals. They will give you small amounts of bonus points, capped at 10 points (that is, even if you do everything perfectly, you cannot possibly get more than 110/100 on this project).

Fair warning: these stretch goals are not easy, and are more designed so that those of you who want to learn a little more about the weird fringes of C++ can cut your teeth. You will get many more points from implementing the main project well and testing it thoroughly than you will get from these bonuses.

If you attempt these, you must make sure your code still compiles on the lab machines and does not interfere with the correctness of the results. For this project ONLY, you may make several different source files. Make sure to leave a comment in the README telling me how to build/run your stretch code.

Finally, note that stretch goals are here so that you can, if you so choose, explore more advanced programming/CS concepts. If you look at a stretch and think that it looks cool, but you’re not entirely sure how to get started, come talk to me! I can give you some hints and/or modify the stretch slightly to suit your goals.

Stretch A: iostream not included (4pts)
#

Rewrite your program so that you do not include iostream. There are several ways to accomplish this–the most common is to use stdio.h and printf/fgets, but there are other ways to do it as well.

Stretch B: Look Ma, No Loops! (10pts)
#

Rewrite your program without using loop constructs or recursion. To be clear: you may call standard library functions that use loops or recursion, but the loop statements or recursive functions may not appear in your code.

Note that to achieve this, you may find it helpful to write a lot of helper functions that aggregate work. In addition, the <algorithm> functions will be invaluable to you.

It may help for this Stretch if you use the C++14 standard for lambda function support. If you opt do this, you must note it in the README.



  1. This is an utter lie: C++ has a bajillion string types, including std::string, char*, wchar_t*, char16_t *, char32_t *, and at least one implementation of Twine. However, in most code that deals with ASCII, char* and std::string are the standard, and we will stick to these two string types for this class. ↩︎