/* * midterm.c * * This "program" contains the solutions to the five problems * from the 2009 midterm. * * XXX: The unit tests do not free memory allocated by running * the tests yet. */ #include #include #include #include /** * Returns a new string with the characters of each interleaved. */ char* interleave(char* s, char* t) { int slength = strlen(s); int tlength = strlen(t); int ulength = slength + tlength; char* u = malloc(ulength + 1); int i = 0, j = 0, k = 0; while (k < ulength) { if (i < slength) u[k++] = s[i++]; if (j < tlength) u[k++] = t[j++]; } u[k] = '\0'; return u; } /** * Returns the dot product of a and b, where each of * a and b are arrays of n doubles. */ double dot_product(double a[], double b[], int n) { double sum = 0.0; for (int i = 0; i < n; i++) { sum += a[i] * b[i]; } return sum; } /** * A substring function that avoids using any * standard library functions except malloc. * The behavior of this function is as follows: * * - The from index is inclusive, the to index is * exclusive * - The input string is never changed * - The return value is always a newly allocated string, * so the caller is responsible for freeing it * - if from < 0, we interpret it as zero * - If to > strlen(s), we interpret it as strlen(s) * - If from >= to, we return a new empty string */ char* substring(char* s, int from, int to) { if (from < 0) from = 0; if (to > strlen(s)) to = strlen(s); if (from >= to) return ""; char* result = malloc(to - from + 1); char* p = result; char* q = s + from; for (int i = from; i < to; i++) *p++ = *q++; *p = '\0'; return result; } /** * Returns a new string containing every kth character in s, * starting with the first character (the one in position 0). * Returns NULL if k <= 0. */ char* everyKth(char* s, int k) { if (k <= 0) return NULL; int length = (strlen(s) / k) + 1; char* result = malloc(length + 1); int j = 0; for (int i = 0; i < strlen(s); i += k) { result[j++] = s[i]; } result[j] = '\0'; return result; } void assertEquals(char* s, char* t) { assert(strcmp(s, t) == 0); } /** * The main program writes its longest arg to stdout. */ int main(int argc, char** argv) { /* NOTE: NOT EFFICIENT, TOO MANY strlen CALLS. */ int longest = 0; for (int i = 1; i < argc; i++) { if (strlen(argv[i]) > strlen(argv[0])) { longest = i; } } printf("%s\n", argv[longest]); /* Unit tests*/ printf("Testing everyKth...\n"); assertEquals(everyKth("abcdefghij", 1), "abcdefghij"); assertEquals(everyKth("abcdefghij", 2), "acegi"); assertEquals(everyKth("abcdefghij", 3), "adgj"); assertEquals(everyKth("abcdefghij", 4), "aei"); assertEquals(everyKth("abcdefghij", 5), "af"); assertEquals(everyKth("abcdefghij", 6), "ag"); assertEquals(everyKth("abcdefghij", 7), "ah"); assertEquals(everyKth("abcdefghij", 8), "ai"); assertEquals(everyKth("abcdefghij", 9), "aj"); assertEquals(everyKth("abcdefghij", 10), "a"); assertEquals(everyKth("abcdefghij", 11), "a"); printf("Testing interleave...\n"); assertEquals(interleave("", "abc"), "abc"); assertEquals(interleave("ABC", "abc"), "AaBbCc"); assertEquals(interleave("e", "abc"), "eabc"); assertEquals(interleave("xy", "abc"), "xaybc"); assertEquals(interleave("ABCDEF", "abc"), "AaBbCcDEF"); assertEquals(interleave("", ""), ""); assertEquals(interleave("abc", ""), "abc"); assertEquals(interleave("ZZZ", "a"), "ZaZZ"); /* Testing dot product with == on floating point values * is actually bad, but we're using only small numbers * that are actually integer-valued so there will be * no loss of precision. */ printf("Testing dop_product...\n"); double a[] = {1.0, 2.0, -3.0, 4.0}; double b[] = {6.0, 2.0, 1.0, -2.0}; assert(dot_product(a, b, 0) == 0.0); assert(dot_product(a, b, 1) == 6.0); assert(dot_product(a, b, 2) == 10.0); assert(dot_product(a, b, 3) == 7.0); assert(dot_product(a, b, 4) == -1.0); printf("Testing substring...\n"); assertEquals(substring("abcdefghi", 2, 6), "cdef"); assertEquals(substring("abcdefghi", -2, 6), "abcdef"); assertEquals(substring("abcdefghi", 0, 6), "abcdef"); assertEquals(substring("abcdefghi", 2, 60), "cdefghi"); assertEquals(substring("abcdefghi", 1, 1), ""); assertEquals(substring("abcdefghi", 1, 2), "b"); assertEquals(substring("abcdefghi", 20, 6), ""); printf("All tests passed\n"); }