DPST1091 Revision Strings Sample Solutions
Revision Exercise: Count the number of words in a string
Assume the only non-word characters are space and newline.
All other characters should be considered word characters.
A word is defined as a maximal non-empty sequence of word characters.
Multiple spaces or newline characters may separate words.
Match the output format below exactly:
dcc -o word_count word_count.c
./word_count
The quick brown fox jumped over the lazy dog.
1 lines 9 words 46 characters
./word_count
only
three
words
3 lines 3 words 29 characters
./word_count
Are you saying 'Boo' or 'Boo-Urns'?
1 lines 6 words 36 characters
./word_count
In this house,
we obey the laws of thermodynamics!
2 lines 9 words 52 characters
./word_count
Simpson, Homer Simpson
He's the greatest guy in history
From the
Town of Springfield
He's about to hit a chestnut tree.
5 lines 21 words 125 characters
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest word_count
word_count.c
// Written 3/5/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// Counts lines, word & characters in standard input
//
// The mapping will be supplied as a command-line argument containing 10 characters:
#include <stdio.h>
int word_character(int character);
int main(int argc, char *argv[]) {
int line_count = 0;
int character_count = 0;
int word_count = 0;
int lastc = ' ';
int c = getchar();
while (c != EOF) {
character_count = character_count + 1;
if (word_character(c) && !word_character(lastc)) {
word_count = word_count + 1;
}
if (c == '\n') {
line_count = line_count + 1;
}
lastc = c;
c = getchar();
}
printf("%d lines %d words %d characters\n", line_count, word_count, character_count);
}
int word_character(int character) {
return character != ' ' && character != '\n';
}
Revision Exercise: Reverse the lines of text on input
reverse_lines.c which reads lines and writes them out
with the characters of each line in reverse order.
It should stop when it reaches the end of input.
For example:
dcc -o reverse_lines reverse_lines.c ./reverse_lines Two roads diverged in a yellow wood, ,doow wolley a ni degrevid sdaor owT And sorry I could not travel both htob levart ton dluoc I yrros dnA And be one traveler, long I stood doots I gnol ,relevart eno eb dnA To where it bent in the undergrowth; ;htworgrednu eht ni tneb ti erehw oT You don't make friends with salad. .dalas htiw sdneirf ekam t'nod uoYYou can assume lines will contain at most 256 characters.
You can assume lines are terminated with a newline ('\n') character,
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest reverse_lines
reverse_lines.c
// Written 3/5/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// Reads lines and writes them out with the characters of each line in reverse order.
// Stop when it reaches the end of input.
#include <stdio.h>
#define MAX_LINE_CHARS 4096
int main(void) {
char line[MAX_LINE_CHARS];
// get the lines
while (fgets(line, MAX_LINE_CHARS, stdin) != NULL) {
// find the size of this line
int size = 0;
while ((line[size] != '\n') && (line[size] != '\0')) {
// not the end yet
size = size + 1;
}
// now print in reverse
int j = size - 1;
while (j >= 0) {
printf("%c", line[j]);
j = j - 1;
}
printf("\n");
}
return 0;
}
Revision Exercise: String Length
string_length.
It takes a string,
and finds its length,
excluding the null-terminator.
Download string_length.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/26T1/activities/string_length/string_length.c .
Your task is to add code to this function in string_length.c:
// Takes a string and finds its length, excluding the null-terminator.
int string_length(char *string) {
// Your code goes here!
// Don't forget to return your result.
return 0;
}
assert-based tests
to help you build your solution:
int main(int argc, char *argv[]) {
// Some simple assert-based tests.
// You probably want to write some more.
assert(string_length("") == 0);
assert(string_length("!") == 1);
assert(string_length("Hello, world!") == 13);
assert(string_length("17... seventeen.\n") == 17);
printf("All tests passed. You are awesome!\n");
return 0;
}
Your string_length function will be called directly in marking. The main function is only to let you test your string_length function
You can add more assert tests to main to test your string_length function.
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest string_length
string_length.c
// How long is a (piece of) string?
// A sample solution.
#include <assert.h>
#include <stdio.h>
int string_length(char *string);
int main(int argc, char *argv[]) {
// Some simple assert-based tests.
// You probably want to write some more.
assert(string_length("") == 0);
assert(string_length("!") == 1);
assert(string_length("Hello, world!") == 13);
assert(string_length("17... seventeen.\n") == 17);
printf("All tests passed. You are awesome!\n");
return 0;
}
// Takes a string and finds its length, excluding the null-terminator.
int string_length(char *string) {
int i = 0;
while (string[i] != '\0') {
i = i + 1;
}
return i;
}
Revision Exercise: Show Letters
char values.
You should use printf("%c")
to print each character in the array.
Download show_letters.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/26T1/activities/show_letters/show_letters.c .
Your task is to add code to this function in show_letters.c:
// print size characters from array letters
void show_letters(int size, char letters[]) {
// Put your code here
}
Here is how show_letters.c should behave after you add the correct code to the function show_letters:
dcc show_letters.c -o show_letters ./show_letters Hello, world! Test message. sample text a string
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest show_letters
show_letters.c
// Display character arrays as text, by printing the individual
// characters -- a sample solution.
#include <assert.h>
#include <stdio.h>
#define ENOUGH_SPACE 100
void show_letters(int size, char letters[]);
int main(int argc, char *argv[]) {
char letters_a[13] = {0};
letters_a[0] = 72;
letters_a[1] = 101;
letters_a[2] = 108;
letters_a[3] = 108;
letters_a[4] = 111;
letters_a[5] = 44;
letters_a[6] = 32;
letters_a[7] = 119;
letters_a[8] = 111;
letters_a[9] = 114;
letters_a[10] = 108;
letters_a[11] = 100;
letters_a[12] = 33;
show_letters(13, letters_a);
printf("\n");
char letters_b[13] = {
84, 101, 115, 116, 32,
109, 101, 115, 115, 97,
103, 101, 46
};
show_letters(13, letters_b);
printf("\n");
char letters_c[11] = {
's', 'a', 'm', 'p', 'l', 'e',
' ', 't', 'e', 'x', 't'
};
show_letters(11, letters_c);
printf("\n");
char letters_d[ENOUGH_SPACE] = "a string";
show_letters(8, letters_d);
printf("\n");
return 0;
}
// print size characters from array letters
void show_letters(int size, char letters[]) {
int i = 0;
while (i < size) {
putchar(letters[i]);
i = i + 1;
}
}
Revision Exercise: Show Terminated Letters
char values.
You should use printf("%c")
to print each character in the array.
Your function will not be given the number of characters to show,
instead, you must display characters from the array
until you find a null terminator (0 or '\0')
in the array.
Download show_terminated_letters.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/26T1/activities/show_terminated_letters/show_terminated_letters.c .
Your task is to add code to this function in show_terminated_letters.c:
void show_terminated_letters(char *letters) {
// Your code here
}
Here is how string_reverse.c should behave after you add the correct code to the function string_reverse:
dcc show_terminated_letters.c -o show_terminated_letters ./show_terminated_letters Hello, world! Test message. sample text a string
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest show_terminated_letters
show_terminated_letters.c
// Displaying arrays as text
// A sample solution.
#include <assert.h>
#include <stdio.h>
#define ENOUGH_SPACE 100
// Print out each character in a NUL-terminated array of characters.
void show_terminated_letters(char *letters);
int main(int argc, char *argv[]) {
char letters_a[14] = {0};
letters_a[0] = 72;
letters_a[1] = 101;
letters_a[2] = 108;
letters_a[3] = 108;
letters_a[4] = 111;
letters_a[5] = 44;
letters_a[6] = 32;
letters_a[7] = 119;
letters_a[8] = 111;
letters_a[9] = 114;
letters_a[10] = 108;
letters_a[11] = 100;
letters_a[12] = 33;
letters_a[13] = 0;
show_terminated_letters(letters_a);
putchar('\n');
char letters_b[14] = {
84, 101, 115, 116, 32,
109, 101, 115, 115, 97,
103, 101, 46, 0
};
show_terminated_letters(letters_b);
putchar('\n');
char letters_c[12] = {
's', 'a', 'm', 'p', 'l', 'e',
' ', 't', 'e', 'x', 't', '\0'
};
show_terminated_letters(letters_c);
putchar('\n');
char letters_d[ENOUGH_SPACE] = "a string";
show_terminated_letters(letters_d);
putchar('\n');
return 0;
}
void show_terminated_letters(char *letters) {
int i = 0;
while (letters[i] != '\0') {
putchar(letters[i]);
i = i + 1;
}
}
Revision Exercise: String Copy
string_copy
It takes a string in the source buffer,
and copies it to the destination buffer,
which is dest_size elements in size.
If there are more characters in source
than there is array space in destination,
you should stop after you have filled the array.
You should always make sure that
your function null-terminates
the destination array.
Download string_copy.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/26T1/activities/string_copy/string_copy.c .
Your task is to add code to this function in string_copy.c:
// Takes a string in `source`, and copies it to `destination`, which
// is `destSize` elements in size; only copies up to `destSize` bytes.
// Ensures the `destination` array is null-terminated.
void string_copy(char *destination, char *source, int destination_size) {
// Put your code here
}
int main(int argc, char *argv[]) {
// Declare a buffer. In this case, we're declaring and using a
// 64-byte buffer, but this could be any length you like, and in
// our tests you will be required to handle arrays of any length.
char buffer[BUFFER_LENGTH] = {0};
// Copy a string into the buffer ...
string_copy(buffer, "Seventeen bytes.\n", BUFFER_LENGTH);
// ... and print it out. The `%s` format code prints a string.
printf("<%s>\n", buffer);
return 0;
}
Your string_copy function will be called directly in marking. The main function is only to let you test your string_copy function
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest string_copy
string_copy.c
// Copy a String
// A sample solution.
#include <stdio.h>
#define BUFFER_LENGTH 64
void string_copy(char *destination, char *source, int destination_size);
int main(int argc, char *argv[]) {
// Declare a buffer. In this case, we're declaring and using a
// 64-byte buffer, but this could be any length you like, and in
// our tests you will be required to handle arrays of any length.
char buffer[BUFFER_LENGTH] = {0};
// Copy a string into the buffer ...
string_copy(buffer, "Seventeen bytes.\n", BUFFER_LENGTH);
// ... and print it out. The `%s` format code prints a string.
printf("<%s>\n", buffer);
return 0;
}
// Takes a string in `source`, and copies it to `destination`, which
// is `destSize` elements in size; only copies up to `destSize` bytes.
// Ensures the `destination` array is null-terminated.
void string_copy(char *destination, char *source, int destination_size) {
int i = 0;
// stop before last array element so we can add '\0'
while (i < destination_size - 1 && source[i] != '\0') {
destination[i] = source[i];
i = i + 1;
}
destination[i] = '\0';
}
Revision Exercise: String To Upper
string_to_upper.
It takes a string and converts it to upper case
Download string_to_upper.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/26T1/activities/string_to_upper/string_to_upper.c .
Your task is to add code to this function in string_to_upper.c:
// Convert the characters in `buffer` to upper case
void string_to_upper(char *buffer) {
// YOUR CODE GOES HERE!
}
int main(int argc, char *argv[]) {
// NOTE: THIS WON'T WORK:
// char *str = "Hello!"
// string_to_upper(str)
//
// str only points to a string literal, which it is not legal to change.
// If you attempt to modify it on Linux you will get a runtime error.
// Instead, you need to create an array to store the string in, e.g.:
//
// char str[] = "Hello!"
// string_to_upper(str)
char str[] = "Seventeen... SEVENTEEN, I SAY!";
string_to_upper(str);
printf("%s\n", str);
return 0;
}
Your string_to_upper function will be called directly in marking. The main function is only to let you test your string_to_upper function
int main(int argc, char *argv[]) {
// NOTE: THIS WON'T WORK:
// char *str = "Hello!"
// string_to_upper(str)
//
// str only points to a string literal, which it is not legal to change.
// If you attempt to modify it on Linux you will get a runtime error.
// Instead, you need to create an array to store the string in, e.g.:
//
// char str[] = "Hello!"
// string_to_upper(str)
char str[] = "Seventeen... SEVENTEEN, I SAY!";
string_to_upper(str);
printf("%s\n", str);
return 0;
}
Your string_to_upper function will be called directly in marking. The main function is only to let you test your string_to_upper function
Here is how string_to_upper.c should behave after you add the correct code to the function string_to_upper:
dcc string_to_upper.c -o string_to_upper ./string_to_upper SEVENTEEN... SEVENTEEN, I SAY!
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest string_to_upper
string_to_upper.c
// CONVERT A STRING TO UPPERCASE
// CREATED BY
// ... (Z0000000)
// CREATED ON 2019-??-??
#include <stdio.h>
void string_to_upper(char *buffer);
int uppercase(int c);
int main(int argc, char *argv[]) {
// NOTE: THIS WON'T WORK:
// char *str = "Hello!"
// string_to_upper(str)
//
// str only points to a string literal, which it is not legal to change.
// If you attempt to modify it on Linux you will get a runtime error.
// Instead, you need to create an array to store the string in, e.g.:
//
// char str[] = "Hello!"
// string_to_upper(str)
char str[] = "Seventeen... SEVENTEEN, I SAY!";
string_to_upper(str);
printf("%s\n", str);
return 0;
}
// Convert the characters in `buffer` to upper case
void string_to_upper(char *buffer) {
int i = 0;
while (buffer[i] != '\0') {
buffer[i] = uppercase(buffer[i]);
i = i + 1;
}
}
int uppercase(int c) {
if (c >= 'a' && c <= 'z') {
return c - 'a' + 'A';
} else {
return c;
}
}
Revision Exercise: Rotate Thirteen
rotate_thirteen.
It takes a string,
and rotates each character by thirteen positions
in the alphabet.
To see more about this algorithm, check out the wikipedia article.
Download rotate_thirteen.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/26T1/activities/rotate_thirteen/rotate_thirteen.c .
Your task is to add code to this function in rotate_thirteen.c:
void rotate_thirteen(char *string) {
// YOUR CODE HERE
// See: https://en.wikipedia.org/wiki/ROT13
}
assert-based tests
to help you build your solution:
int main(int argc, char *argv[]) {
// Example tests
char test_a[MAX_LENGTH] = "Hello, world!";
rotate_thirteen(test_a);
assert(strings_equal("Uryyb, jbeyq!", test_a));
char test_b[MAX_LENGTH] = "abcdefghijklmnopqrstuvwxyz";
rotate_thirteen(test_b);
assert(strings_equal("nopqrstuvwxyzabcdefghijklm", test_b));
char test_c[MAX_LENGTH] = "The quick brown fox jumped over the lazy dog.";
rotate_thirteen(test_c);
assert(strings_equal("Gur dhvpx oebja sbk whzcrq bire gur ynml qbt.", test_c));
// Add your own tests here
printf("All tests passed. You are awesome!\n");
return 0;
}
Your rotate_thirteen function will be called directly in marking. The main function is only to let you test your rotate_thirteen function
You can add more assert tests to main to test your rotate_thirteen function.
You will need to use your strings_equal function
from the strings_equal activity
for tests to work.
You may want to use your rotate_one function
from the rotate_one activity.
You may want to use your rotate_thirteen function
from the rotate_thirteen activity.
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest rotate_thirteen
rotate_thirteen.c
// Perform the ROT13 algorithm on a string -- sample solution.
#include <stdio.h>
#include <assert.h>
#include <string.h>
// Add your own #defines here
#define ALPHABET_LENGTH 26
#define LOWER_START 'a'
#define LOWER_END (LOWER_START + ALPHABET_LENGTH)
#define UPPER_START 'A'
#define UPPER_END (UPPER_START + ALPHABET_LENGTH)
#define MAX_LENGTH 256
void rotate_thirteen(char *string);
int rotate_one(int c);
int string_length(char *string);
int strings_equal(char *string_a, char *string_b);
// Add your own function prototypes here
int is_lower_letter(char l);
int is_upper_letter(char l);
int main(int argc, char *argv[]) {
// Example tests
char test_a[MAX_LENGTH] = "Hello, world!";
rotate_thirteen(test_a);
assert(strings_equal("Uryyb, jbeyq!", test_a));
char test_b[MAX_LENGTH] = "abcdefghijklmnopqrstuvwxyz";
rotate_thirteen(test_b);
assert(strings_equal("nopqrstuvwxyzabcdefghijklm", test_b));
char test_c[MAX_LENGTH] = "The quick brown fox jumped over the lazy dog.";
rotate_thirteen(test_c);
assert(strings_equal(
"Gur dhvpx oebja sbk whzcrq bire gur ynml qbt.",
test_c
));
// Add your own tests here
printf("All tests passed. You are awesome!\n");
return 0;
}
// See: https://en.wikipedia.org/wiki/ROT13
void rotate_thirteen(char *string) {
int l = 0;
int length = string_length(string);
while (l < length) {
int i = 0;
while (i < 13) {
string[l] = rotate_one(string[l]);
i = i + 1;
}
l = l + 1;
}
}
// Use your code from the rotate_one warmup here.
int rotate_one(int c) {
int letter_num = 0;
int base = '\0';
// Deal with lowercase and uppercase letters separately.
if (is_lower_letter(c)) {
letter_num = c - LOWER_START;
base = LOWER_START;
} else if (is_upper_letter(c)) {
letter_num = c - UPPER_START;
base = UPPER_START;
} else {
// If it's not lowercase or uppercase, it remains unchanged.
return c;
}
// rotate by 1, wrap around alphabet
letter_num = letter_num + 1;
letter_num = letter_num % ALPHABET_LENGTH;
return base + letter_num;
}
int string_length(char *string) {
// Use your code from the string_length activity here.
// Lazy tutor solution: use string.h
return strlen(string);
}
int strings_equal(char *string_a, char *string_b) {
// Use your code from the strings_equal activity here.
// Lazy tutor solution: use string.h
return strcmp(string_a, string_b) == 0;
}
int is_lower_letter(char l) {
return (l >= LOWER_START && l < LOWER_END);
}
int is_upper_letter(char l) {
return (l >= UPPER_START && l < UPPER_END);
}
Revision Exercise: Reverse the contents of a string
string_reverse.
It takes a string and reverses it in place.
Download string_reverse.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/26T1/activities/string_reverse/string_reverse.c .
Your task is to add code to this function in string_reverse.c:
// Takes a string in `buffer`, and reverses it in-place.
void string_reverse(char *buffer) {
// YOUR CODE GOES HERE!
}
int main(int argc, char *argv[]) {
// NOTE: THIS WON'T WORK:
// char *str = "Hello!"
// string_reverse(str)
//
// str only points to a string literal, which it is not legal to change.
// If you attempt to modify it on Linux you will get a runtime error.
// Instead, you need to create an array to store the string in, e.g.:
//
// char str[] = "Hello!"
// string_reverse(str)
char str[] = ".'neetneves' :egassem terces A";
string_reverse(str);
printf("%s\n", str);
return 0;
}
Your string_reverse function will be called directly in marking. The main function is only to let you test your string_reverse function
Here is how string_reverse.c should behave after you add the correct code to the function string_reverse:
dcc string_reverse.c -o string_reverse ./string_reverse A secret message: 'seventeen'.
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest string_reverse
string_reverse.c
// gnirts a esreveR (Reverse a string)
// A sample solution.
#include <stdio.h>
void string_reverse(char *buffer);
int string_length(char *string);
int main(int argc, char *argv[]) {
// NOTE: THIS WON'T WORK:
// char *str = "Hello!"
// string_reverse(str)
//
// str only points to a string literal, which it is not legal to change.
// If you attempt to modify it on Linux you will get a runtime error.
// Instead, you need to create an array to store the string in, e.g.:
//
// char str[] = "Hello!"
// string_reverse(str)
char str[] = ".'neetneves' :egassem terces A";
string_reverse(str);
printf("%s\n", str);
return 0;
}
// Takes a string in `buffer`, and reverses it in-place.
void string_reverse(char *buffer) {
int length = string_length(buffer);
int i = 0;
while (i < length/2) {
// swap array elements
char tmp = buffer[i];
buffer[i] = buffer[length - i - 1];
buffer[length - i - 1] = tmp;
i = i + 1;
}
}
// Takes a string and finds its length, excluding the null-terminator.
int string_length(char *string) {
int i = 0;
while (string[i] != '\0') {
i = i + 1;
}
return i;
}
Revision Exercise: Swap the case of letters in a string.
Download swap_case.c here
Or, copy these file(s) to your CSE account using the following command:
1091 fetch-activity swap_case
Your task is to add code to this function in swap_case.c:
int swap_case(int character) {
// TODO: Write this function, which should:
// - return character in lower case if it is an upper case letter
// - return character in upper case if it is an lower case letter
// - return the character unchanged otherwise
return 'x';
}
Edit the C program swap_case.c (linked above) which reads characters from its
input and writes the same characters to its output with lower case letters
converted to upper case and upper case letters converted to lower case.
Your program should stop only at the end of input.
which:
- returns the character in lowercase if it is an uppercase letter
- returns the character in uppercase if it is a lowercase letter
- returns the character unchanged otherwise
Note: Your program will not pass autotests if it does not contain this function.
Examples
dcc swap_case.c -o swap_case ./swap_case Are you saying 'Boo' or 'Boo-Urns'? aRE YOU SAYING 'bOO' OR 'bOO-uRNS'? In this house, we obey the laws of thermodynamics! iN THIS HOUSE, WE OBEY THE LAWS OF THERMODYNAMICS! UPPER !@#$% lower upper !@#$% LOWER
Assumptions/Restrictions/Clarifications
- You need only a single int variable. Don't use an array.
- Make sure you understand this example program which reads characters until end of input.
- Make sure you understand this example program which reads characters, printing them with lower case letters converted to uppercase.
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest swap_case
swap_case.c
// Written 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// Write stdin to stdout with upper case letters converted to lower case
// and lower case converted to upper case
//
#include <stdio.h>
#include <stdlib.h>
int swap_case(int character);
int main(int argc, char *argv[]) {
int character = getchar();
while (character != EOF) {
int swapped_character = swap_case(character);
putchar(swapped_character);
character = getchar();
}
return 0;
}
int swap_case(int character) {
if (character >= 'A' && character <= 'Z') {
return 'a' + character - 'A';
} else if (character >= 'a' && character <= 'z') {
return 'A' + character - 'a';
} else {
return character;
}
}
Revision Exercise: Encrypting Text with a Substitution Cipher
Write a C program substitution.c which reads characters from its input and
writes the characters to its output encrypted with a
Substitution cipher.
A Substitution cipher maps each letter to another letter.
The mapping will be given to your program via the command line as a command line argument
(no spaces between any characters). This is all on one line. This input will contain 26
characters: an ordering of the letters 'a'..'z'.
Characters other than letters should not be encrypted.
Your program should stop only at the end of input.
Your program should contain at least one function other than main.
Examples
dcc substitution.c -o substitution ./substitution qwertyuiopasdfghjklzxcvbnm Enter text: I was scared of dentists and the dark O vql leqktr gy rtfzolzl qfr zit rqka I was scared of pretty girls and starting conversations O vql leqktr gy hktzzn uoksl qfr lzqkzofu egfctklqzogfl ./substitution abcdefghijklmnopqrstuvwxyz Enter text: The identity cipher!!! The identity cipher!!! ./substitution bcdefghijklmnopqrstuvwxyza Enter text: The Caesar cipher is a subset of the substitution cipher! Uif Dbftbs djqifs jt b tvctfu pg uif tvctujuvujpo djqifs!
Your program will only be tested with an appropriate and valid mapping input for marking - but a good programmer would check the input is present and appropriate.
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest substitution
substitution.c
// Substitution.c
// Write stdin to stdout encrypted with a Substitution cipher
// https://en.wikipedia.org/wiki/Substitution_cipher
//
// The mapping will be supplied as a command-line argument containing 26 characters:
// These will be an an ordering of the letters 'a'..'z'.
//
// Written 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// and adapted for 23T2 by Sofia De Bellis, z5418801 on July 2023
#include <stdio.h>
#include <string.h>
#define ALPHABET_SIZE 26
int encrypt(char character, char mapping[ALPHABET_SIZE]);
int main(int argc, char *argv[]) {
char mapping[ALPHABET_SIZE + 1];
for (int i = 0; i < ALPHABET_SIZE; i++) {
mapping[i] = argv[1][i];
}
mapping[ALPHABET_SIZE] = '\0';
// Error checking - not necessary in student solution or tested
if (mapping[0] == '\0') {
printf("Usage: ./substitution <mapping>\n");
return 1;
}
if (strlen(mapping) != ALPHABET_SIZE) {
printf("./substitution: mapping must contain %d letters\n", ALPHABET_SIZE);
return 1;
}
printf("Enter text:\n");
char character;
while (scanf("%c", &character) == 1) {
int encrypted_character = encrypt(character, mapping);
printf("%c", encrypted_character);
}
return 0;
}
// encrypt letters with a substitution cipher with the specified mapping
int encrypt(char character, char mapping[ALPHABET_SIZE]) {
if (character >= 'A' && character <= 'Z') {
return mapping[character - 'A'] - 'a' + 'A';
} else if (character >= 'a' && character <= 'z') {
return mapping[character - 'a'];
} else {
return character;
}
}
Revision Exercise: Is it a Palindrome - the Sequel
punctuated_palindrome.c, which reads a string and tests if
it is a palindrome.
Characters which are not letters should be ignored .
Differences between upper case and lower case are ignored. For example:
./punctuated_palindrome Enter a string: Do geese see God? String is a palindrome ./punctuated_palindrome Enter a string: Do ducks see God? String is not a palindrome ./punctuated_palindrome Enter a string: Madam, I'm Adam String is a palindrome ./punctuated_palindrome Enter a string: Madam, I'm Andrew String is not a palindromeHint: you might find C library functions in
#include <ctype.h> useful.
You can assume lines contain at most 4096 characters.
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest punctuated_palindrome
punctuated_palindrome.c
// Read a string and then print the letters one per line
// written by Andrew Taylor andrewt@cse.unsw.edu.au
// April 2018 as a COMP1511 lab exercise
//
#include <stdio.h>
#include <ctype.h>
#define MAXLINE 5000
int is_palindrome(char line[]);
int main(void) {
char line[MAXLINE] = {0};
printf("Enter a string: ");
fgets(line, MAXLINE, stdin);
if (is_palindrome(line)) {
printf("String is a palindrome\n");
} else{
printf("String is not a palindrome\n");
}
return 0;
}
// return 1 is line is palindromic, 0 otherwise
// line is terminated by either '\n' or '\0'
// case and non-alphabetic characters are ignored
// an empty line is considered a palindrome
int is_palindrome(char line[]) {
int right = 0;
while (line[right] != '\0' && line[right] != '\n') {
right = right + 1;
}
right = right - 1;
int left = 0;
while (left < right) {
int left_char = tolower(line[left]);
int right_char = tolower(line[right]);
if (!isalpha(left_char)) {
left = left + 1;
} else if (!isalpha(right_char)) {
right = right - 1;
} else if (left_char != right_char) {
return 0;
} else {
left = left + 1;
right = right - 1;
}
}
return 1;
}
Revision Exercise: Frequency Analysis
Write a C program frequency_analysis.c which reads characters from its input
until end of input.
It should then print the occurrence frequency for each of the 26 letters
'a'..'z'.
The frequency should be printed as a decimal value and an absolute number in exactly the format below.
Note upper and lower case letters are counted together.
Examples
dcc frequency_analysis.c -o frequency_analysis ./frequency_analysis Hello and goodbye. 'a' 0.066667 1 'b' 0.066667 1 'c' 0.000000 0 'd' 0.133333 2 'e' 0.133333 2 'f' 0.000000 0 'g' 0.066667 1 'h' 0.066667 1 'i' 0.000000 0 'j' 0.000000 0 'k' 0.000000 0 'l' 0.133333 2 'm' 0.000000 0 'n' 0.066667 1 'o' 0.200000 3 'p' 0.000000 0 'q' 0.000000 0 'r' 0.000000 0 's' 0.000000 0 't' 0.000000 0 'u' 0.000000 0 'v' 0.000000 0 'w' 0.000000 0 'x' 0.000000 0 'y' 0.066667 1 'z' 0.000000 0 ./frequency_analysis Hey! Hey! Hey! I don't like walking around this old and empty house So hold my hand, I'll walk with you my dear 'a' 0.072289 6 'b' 0.000000 0 'c' 0.000000 0 'd' 0.084337 7 'e' 0.084337 7 'f' 0.000000 0 'g' 0.012048 1 'h' 0.096386 8 'i' 0.072289 6 'j' 0.000000 0 'k' 0.036145 3 'l' 0.084337 7 'm' 0.036145 3 'n' 0.060241 5 'o' 0.084337 7 'p' 0.012048 1 'q' 0.000000 0 'r' 0.024096 2 's' 0.036145 3 't' 0.048193 4 'u' 0.036145 3 'v' 0.000000 0 'w' 0.036145 3 'x' 0.000000 0 'y' 0.084337 7 'z' 0.000000 0
Hint: use an array to store counts of each letter.
Hint: make sure you understand this example program which counts integers from the range 0..99.
Manually Cracking a Substitution Cipher
This English text was encrypted with a substitution cipher.
Di jd, vdl'ht xtqa dh O qn Vdl rdlwk O'ss wdkith htqromu omkd ok O fhdwqwsv xdm'k Styk kd nv dxm rtzoetj Wlk kiqk'j kit royythtmet om dlh dfomodmj Vdl'ht q ndlkiyls Kiqk qndlmkj ydh qmdkith xtta dm nv dxm Mdx O'n q mdzts nqrt htjdlhetyls O jkqhk q eiqom xoki nv kidluik Kqsa oj eitqf, nv rqhsomu Xitm vdl'ht yttsomu houik qk idnt O xqmmq nqat vdl ndzt xoki edmyortmet O xqmmq wt xoki vdl qsdmt
What was the original text?
Mapping: qwertyuiopasnmdfghjklzxcvb
Oh so, you're weak or I am You doubt I'll bother reading into it I probably won't Left to my own devices But that's the difference in our opinions You're a mouthful That amounts for another week on my own Now I'm a novel made resourceful I start a chain with my thought Talk is cheap, my darling When you're feeling right at home I wanna make you move with confidence I wanna be with you alone
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest frequency_analysis
frequency_analysis.c
// Written 3/3/2018 by Andrew Taylor (andrewt@unsw.edu.au)
// Read characters from stdin until of input then print the frequency of letters
#include <stdio.h>
#define NOT_A_LETTER (-1)
#define ALPHABET_SIZE 26
int get_letter_frequencies(int letter_count[ALPHABET_SIZE]);
int letter_index(int character);
void print_frequencies(int letter_count[ALPHABET_SIZE], int n_letters_read);
int main(int argc, char *argv[]) {
int letter_count[ALPHABET_SIZE] = {0}; // 1 array element for each English letter
int n_letters_read = get_letter_frequencies(letter_count);
print_frequencies(letter_count, n_letters_read);
return 0;
}
// read characters from stdin, and for uppercase and lower case letters updating
// accumulating count a letter_count in letter_frequencies
// number of uppercase and lower case letters read is returned
int get_letter_frequencies(int letter_count[ALPHABET_SIZE]) {
char character;
int n_letters_read = 0;
while (scanf(" %c", &character) == 1) {
int index = letter_index(character);
if (index != NOT_A_LETTER) {
letter_count[index] = letter_count[index] + 1;
n_letters_read = n_letters_read + 1;
}
}
return n_letters_read;
}
// return position of letter in English alphabet (0..25)
// for lower case and upper case letter
// return NOT_A_LETTER for other characters
int letter_index(int character) {
if (character >= 'A' && character <= 'Z') {
return character - 'A';
} else if (character >= 'a' && character <= 'z') {
return character - 'a';
} else {
return NOT_A_LETTER;
}
}
void print_frequencies(int letter_count[ALPHABET_SIZE], int n_letters_read) {
if (n_letters_read == 0) {
return;
}
int i = 0;
while (i < ALPHABET_SIZE) {
printf("'%c' %lf %d\n", 'a'+i, letter_count[i]/(double)n_letters_read, letter_count[i]);
i = i + 1;
}
}
Revision Exercise: Noname
When you think your program is working you can use autotest to run some simple automated tests:
1091 autotest NONAME