Lab 3: Strings and Command Line Arguments | CS 2113 Software Engineering - Fall 2021

Lab 3: Strings and Command Line Arguments

Preliminaries

Development Environment

The repository comes with a .devcontainer folder that you can use with VSCode+Docker. Alternatively, you can develop using VSCode+SSH.

Test Script

To help you complete the lab, I have provide a test script that will run basic tests against your program. The script is not designed to be comprehensive, and you will graded based on a larger array of tests. To execute the test script, run it from anywhere within the lab directory.

./test.sh

README file

You are required to fill out the README.md file in your repository describing your programming process as well as answer any related lab questions.

Compiling your code:

To compile your code, use gcc the gnu c compiler using the following command:

gcc -Wall prog.c -o prog

The -Wall option will provide additional warnings, and prog is replaced with the program in question.

Part 1: Palindrome Checking (30 Points)

For this part of the lab, you will complete a small program to check if the input provided by the user is a palindrome. A palindrome is a string that is the same forward and backwards.

There are two main ways for testing if a string is a palindrome:

You will implement both; however, the challenge is working with C strings. The main portion of the program, provided to you, looks like such:

int main(int argc, char * argv[]){

  char str[1024];

  printf("Enter a string:\n");

  scanf("%1023s",str);

  if(check1(str)){
    printf("Palindrome according to check 1\n");
  }else{
    printf("NOT a palindrome according to check 1\n");
  }


  if(check2(str)){
    printf("Palindrome according to check 2\n");
  }else{
    printf("NOT a palindrome according to check 2\n");
  }

}

Note that the input is read into the str string and may be substantially shorter than the length 1024. It is also passed to the check1() and check2() functions without a length argument. You should make sure that you use strlen() somewhere.

Additionally, to complete check2() which requires making a copy of the string; don’t forget that C strings must be NULL terminated. If you do not NULL terminate, strcmp() will not work.

  • You must complete the palindrome program using two checks.

  • check1() and check2() must use two distinct algorithms:
    • check1() use two iterators, one from the start and one from the end of the string, to check if the front and back are the same
    • check2() copy the string to a new string, in reverse, and compare the two strings using strcmp()
  • (Extra Credit: 5 points): Complete both check1() and check2() algorithms only using pointer types, no integers. That is, you may not use integer indexing of the string like so: str[i]. If you complete the extra credit, be sure to indicate so in your README file.

Here is some sample output:

aviv@ubuntu: part1 $ ./palindrome 
Enter a string:
racecar
Palindrome according to check 1
Palindrome according to check 2
aviv@ubuntu: part1 $ ./palindrome 
Enter a string:
madamimadam
Palindrome according to check 1
Palindrome according to check 2
aviv@ubuntu: part1 $ ./palindrome 
Enter a string:
amanaplanacanalpanama
Palindrome according to check 1
Palindrome according to check 2
aviv@ubuntu: part1 $ ./palindrome 
Enter a string:
notapalindrome
NOT a palindrome according to check 1
NOT a palindrome according to check 2
aviv@ubuntu: part1 $ 

Part 2: Cryptanalysis (70 points)

This part of the lab can be found in the part2 folder in the repository.

In this part of the lab, you are going to write two small programs to perform cryptanalysis and cipher text cracking — this will come in the form of a letter frequency program freq and a letter substitution program sub. You will use both programs to decrypt a secret message provided to you cipher.txt that was encrypted with a substitution cipher, where each letter is replaced with a different letter.

Perhaps the most famous substitution cipher is the Caeser cipher, attributed to the Roman emperor Julius Caesar, where it was used for communicating with his generals in secret code. The cipher is rather simple, and describes shifting the alphabet by three letters such that A->C and B->D and C->E and so on; decryption requires shifting in the reverse direction. More advanced substitution cipher allow for arbitrary substitutions, not just by a shift, as long as those substations are consistent throughout the document.

Unfortunately, any substitution cipher is trivially broken with some basic tools and analysis because of one fatal flaw. The distribution of letters of the plain text will be identical to that of the cipher text (under the substitution). Consider that English text (if we assume the input, plain-text is English) has a known letter distribution: if we see that Q is now the most frequent letter in the cipher text, then it was probably subbed with S to get pack to the plain text.

Your task for this part of the lab is to write two programs: freq and sub. The freq program will take as input a text file and report the alpha letter frequencies of that file (ignoring non-alpha characters), and the sub program will print out the text of a file with letter substations based on a key-file, containing the substitution rules.

freq

Sub

Note, that your sub program can both encrypted and decrypt, depending on the key.

You should complete the following for this part of the lab

  1. freq.c based on the specifications above
  2. sub.c based on the specifications above
  3. Use freq program and the example swift.txt for your letter distribution to determine the key for cipher.txt
  4. Once you believe you’ve successfully decrypted the message, save it by running the following command:
      ./sub key.txt cipher.txt > plain.txt
    

    This will save the output to a file called plain.txt. Add that file to your repo for submission.