diff --git a/homework06/Makefile b/homework06/Makefile new file mode 100644 index 0000000..8b7bc93 --- /dev/null +++ b/homework06/Makefile @@ -0,0 +1,72 @@ +CC= gcc +CFLAGS= -Wall -g -std=gnu99 -fPIC +LD= gcc +LDFLAGS= -L. +LIBS= -lstr +AR= ar +ARFLAGS= rcs +TARGETS= libstr.so libstr.a trit.dynamic trit.static + +all: $(TARGETS) + +#------------------------------------------------------------------------------- +# TODO: Add rules for libstr.a libstr.so +#------------------------------------------------------------------------------- + +str.o: + +libstr.so: + +libstr.a: + +#------------------------------------------------------------------------------- +# TODO: Add rules for trit.dynamic trit.static +#------------------------------------------------------------------------------- + +trit.o: + +trit.dynamic: + +trit.static: + +#------------------------------------------------------------------------------- +# DO NOT MODIFY BELOW +#------------------------------------------------------------------------------- + +test: + @$(MAKE) -sk test-all + +test-all: test-gitignore test-libstr test-trit + +test-gitignore: + @echo "*.a" > .gitignore + @echo "*.o" >> .gitignore + @echo "*.py" >> .gitignore + @echo "*.sh" >> .gitignore + @echo "*.dynamic" >> .gitignore + @echo "*.static" >> .gitignore + @echo "*.so" >> .gitignore + @echo "*.unit" >> .gitignore + +test-libstr: test-libstr.so test-libstr.a + +test-libstr.so: libstr.so + @curl -sLO https://www3.nd.edu/~pbui/teaching/cse.20289.sp25/static/txt/homework06/str.test.py + @chmod +x str.test.py + @./str.test.py -v + +test-libstr.a: str.unit + @curl -sLO https://www3.nd.edu/~pbui/teaching/cse.20289.sp25/static/txt/homework06/str.unit.sh + @chmod +x str.unit.sh + @./str.unit.sh + +str.unit: str.unit.c libstr.a + @$(CC) $(CFLAGS) -o str.unit str.unit.c libstr.a + +test-trit: trit.dynamic trit.static + @curl -sLO https://www3.nd.edu/~pbui/teaching/cse.20289.sp25/static/txt/homework06/trit.test.sh + @chmod +x trit.test.sh + @./trit.test.sh + +clean: + @rm -f str.o libstr.so libstr.a str.test.py str.unit str.unit.sh trit.o trit.dynamic trit.static trit.test.sh diff --git a/homework06/str.c b/homework06/str.c new file mode 100644 index 0000000..c05daa3 --- /dev/null +++ b/homework06/str.c @@ -0,0 +1,69 @@ +/* str.c: string library */ + +#include "str.h" + +#include +#include +#include + +/* Functions */ + +/** + * Convert string to lowercase. + * @param s String to convert + * @param w Pointer to buffer that holds result of conversion + **/ +void str_lower(const char *s, char *w) { + // TODO +} + +/** + * Convert string to uppercase. + * @param s String to convert + * @param w Pointer to buffer that holds result of conversion + **/ +void str_upper(const char *s, char *w) { + // TODO +} + +/** + * Convert string to titlecase. + * @param s String to convert + * @param w Pointer to buffer that holds result of conversion + **/ +void str_title(const char *s, char *w) { + // TODO +} + +/** + * Strip characters from back of string (if present). + * @param s String to strip + * @param chars Characters to strip (if NULL, then all whitespace) + * @param w Pointer to buffer that holds result of strip + **/ +void str_rstrip(const char *s, const char *chars, char *w) { + // TODO +} + +/** + * Delete characters from string. + * @param s String to delete from + * @param chars Characters to delete + * @param w Pointer to buffer that holds result of deletion + **/ +void str_delete(const char *s, const char *chars, char *w) { + // TODO +} + +/** + * Translate characters in 'from' with corresponding characters in 'to'. + * @param s String to translate + * @param from String with characters to translate + * @param to String with corresponding translation characters + * @param w Pointer to buffer that holds result of translation + **/ +void str_translate(const char *s, const char *from, const char *to, char *w) { + // TODO +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework06/str.h b/homework06/str.h new file mode 100644 index 0000000..4ed4394 --- /dev/null +++ b/homework06/str.h @@ -0,0 +1,12 @@ +/* str.h: string library */ + +#pragma once + +void str_lower(const char *s, char *w); +void str_upper(const char *s, char *w); +void str_title(const char *s, char *w); +void str_rstrip(const char *s, const char *chars, char *w); +void str_delete(const char *s, const char *chars, char *w); +void str_translate(const char *s, const char *from, const char *to, char *w); + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework06/str.unit.c b/homework06/str.unit.c new file mode 100644 index 0000000..dd23962 --- /dev/null +++ b/homework06/str.unit.c @@ -0,0 +1,207 @@ +/* str.unit.c: string library unit test */ + +#include "str.h" + +#include +#include +#include +#include +#include + +/* Structures */ + +typedef struct { + const char *source; + const char *target; +} Pair; + +typedef struct { + const char *source; + const char *chars; + const char *target; +} Triple; + +typedef struct { + const char *source; + const char *from; + const char *to; + const char *target; +} Quad; + +/* Macros */ + +#define streq(a, b) (strcmp(a, b) == 0) + +/* Tests */ + +int test_00_str_lower() { + Pair cases[] = { + {"", ""}, + {" " , " "}, + {"abc", "abc"}, + {"ABC", "abc"}, + {"AbC", "abc"}, + {NULL, NULL}, + }; + + for (Pair *c = cases; c->source && c->target; c++) { + char writer[BUFSIZ]; + str_lower(c->source, writer); + + assert(streq(writer, c->target)); + } + + return EXIT_SUCCESS; +} + +int test_01_str_upper() { + Pair cases[] = { + {"", ""}, + {" " , " "}, + {"abc", "ABC"}, + {"ABC", "ABC"}, + {"AbC", "ABC"}, + {NULL, NULL}, + }; + + for (Pair *c = cases; c->source && c->target; c++) { + char writer[BUFSIZ]; + str_upper(c->source, writer); + + assert(streq(writer, c->target)); + } + + return EXIT_SUCCESS; +} + +int test_02_str_title() { + Pair cases[] = { + {"", ""}, + {"abc", "Abc"}, + {"ABC", "Abc"}, + {"AbC", "Abc"}, + {"a b c", "A B C"}, + {"aa b0b c!!c", "Aa B0B C!!C"}, + {NULL, NULL}, + }; + + for (Pair *c = cases; c->source && c->target; c++) { + char writer[BUFSIZ]; + str_title(c->source, writer); + + assert(streq(writer, c->target)); + } + + return EXIT_SUCCESS; +} + +int test_03_str_rstrip() { + Pair cases1[] = { + {"", ""}, + {"\n", ""}, + {" abc ", " abc"}, + {" abc\n", " abc"}, + {"\na b c", "\na b c"}, + {NULL, NULL}, + }; + + for (Pair *c = cases1; c->source && c->target; c++) { + char writer[BUFSIZ]; + str_rstrip(c->source, NULL, writer); + + assert(streq(writer, c->target)); + } + + Pair cases2[] = { + {"", ""}, + {"\n", ""}, + {" abc ", " abc "}, + {" abc\n", " abc"}, + {"\na b c", "\na b c"}, + {NULL, NULL}, + }; + + for (Pair *c = cases2; c->source && c->target; c++) { + char writer[BUFSIZ]; + str_rstrip(c->source, "\n", writer); + + assert(streq(writer, c->target)); + } + + return EXIT_SUCCESS; +} + +int test_04_str_delete() { + Triple cases[] = { + {"", "", ""}, + {"hello", "", "hello"}, + {"hello", "le", "ho"}, + {"hello world", "le", "ho word"}, + {" hello world ", " aeiou", "hllwrld"}, + {NULL, NULL, NULL}, + }; + + for (Triple *c = cases; c->source && c->target; c++) { + char writer[BUFSIZ]; + str_delete(c->source, c->chars, writer); + + assert(streq(writer, c->target)); + } + + return EXIT_SUCCESS; +} + +int test_05_str_translate() { + Quad cases[] = { + {"", "", "", ""}, + {"hello", "", "430", "hello"}, + {"hello", "aeo", "", "hello"}, + {"hello", "aeo", "430", "h3ll0"}, + {" hello world ", "aeo", "430", " h3ll0 w0rld "}, + {" hello world ", "aeol", "4301", " h3110 w0r1d "}, + {" hello ", "oleh", "ymam", " mammy "}, + {NULL, NULL, NULL, NULL}, + }; + + for (Quad *c = cases; c->source && c->target; c++) { + char writer[BUFSIZ]; + str_translate(c->source, c->from, c->to, writer); + + assert(streq(writer, c->target)); + } + + return EXIT_SUCCESS; +} + +/* Main Execution */ + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s NUMBER\n\n", argv[0]); + fprintf(stderr, "Where NUMBER is right of the following:\n"); + fprintf(stderr, " 0 Test str_lower\n"); + fprintf(stderr, " 1 Test str_upper\n"); + fprintf(stderr, " 2 Test str_title\n"); + fprintf(stderr, " 3 Test str_rstrip\n"); + fprintf(stderr, " 4 Test str_delete\n"); + fprintf(stderr, " 5 Test str_translate\n"); + return EXIT_FAILURE; + } + + int number = atoi(argv[1]); + int status = EXIT_FAILURE; + + switch (number) { + case 0: status = test_00_str_lower(); break; + case 1: status = test_01_str_upper(); break; + case 2: status = test_02_str_title(); break; + case 3: status = test_03_str_rstrip(); break; + case 4: status = test_04_str_delete(); break; + case 5: status = test_05_str_translate(); break; + default: fprintf(stderr, "Unknown NUMBER: %d\n", number); break; + } + + return status; +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework06/trit.c b/homework06/trit.c new file mode 100644 index 0000000..3a9301f --- /dev/null +++ b/homework06/trit.c @@ -0,0 +1,46 @@ +/* trit.c: translation utility */ + +#include "str.h" + +#include +#include +#include + +/* Constants */ + +enum { + LOWER = 1<<1, + UPPER = 0, // TODO: Modify + TITLE = 0, // TODO: Modify + STRIP = 0, // TODO: Modify + DELETE = 0, // TODO: Modify +}; + +/* Functions */ + +void usage(int status) { + fprintf(stderr, "Usage: trit SET1 SET2\n\n"); + fprintf(stderr, "Post Translation filters:\n\n"); + fprintf(stderr, " -l Convert to lowercase\n"); + fprintf(stderr, " -u Convert to uppercase\n"); + fprintf(stderr, " -t Convert to titlecase\n"); + fprintf(stderr, " -s Strip trailing whitespace\n"); + fprintf(stderr, " -d Delete letters in SET1\n"); + exit(status); +} + +void translate_stream(FILE *stream, const char *set1, const char *set2, int flags) { + // TODO +} + +/* Main Execution */ + +int main(int argc, char *argv[]) { + // TODO: Parse command line arguments + + // TODO: Translate standard input + return EXIT_SUCCESS; +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ +