week 8 lab content, excluding concordance and tests for 4 string ptr

This commit is contained in:
Peter 2021-09-23 17:12:58 +08:00
parent f1e39f86a6
commit 0f05a2c1a5
10 changed files with 518 additions and 1 deletions

2
.gitignore vendored
View File

@ -4,3 +4,5 @@
*.out
.vscode/
concordance/

20
Week 8/4_str/README.md Normal file
View File

@ -0,0 +1,20 @@
Using the example strlen() and strcpy() functions of Lecture 13 as a guide, write pairs of functions to implement versions of the following standard C functions:
* strcat
* strcmp
* strncmp
* strchr
* strrchr
* 🌶 strpbrk
* 🌶 🌶 strstr
Maintain two separate C source files for this task: one file for the array-based versions of each function (named arrays.c), and one file for the pointer-based versions (named pointers.c). Develop two separate header files, one containing the prototypes of the array-based functions (named arrays.h), and the other containing the prototypes of the pointer-based functions (named pointers.h).
Create a single testing program named stringtest.c, containing the only main() function for this question, that tests each of the functions you write. The file stringtest.c should include both of your header files.
Approach the writing of each function by following these steps:
Firstly, read the appropriate online Linux manual entry for each function (e.g. run man strcat). Pay particular attention to the parameters of the function and its return value. Note that the online documentation will frequently use the (as yet not explained) keywords const and restrict. For now, simply ignore these and do not reproduce them in your functions (ask a demonstrator if interested in what they're for).
Next, develop a version of each function using arrays (not pointers), in arrays.c, As an example, name your first function strcat_a().
Write a short test function in stringtest.c file that calls your new function several times to test its execution. Depending on the function being tested, suitable parameters to the function will include simple short strings, long strings, empty strings, identical strings (when comparing them), very different strings, strings differing in only a single character, and strings containing, or otherwise, a required character (for strchr).
Next, develop a version of each function using pointers (not arrays) in pointers.c. As an example, name your first function strcat_p(). Undertake the same tests on your pointer-based functions as you did on your array-based ones.

98
Week 8/4_str/arrays.c Normal file
View File

@ -0,0 +1,98 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include "arrays.h"
// the dest string must have enough space for the result. If dest is not large
// enough, program behavior is unpredictable
char *strcat_a(char dest[], char src[])
{
size_t src_len = strlen(src);
size_t dest_len = strlen(dest);
for (size_t i = 0; i < src_len; i++) {
dest[i + dest_len] = src[i];
}
dest[src_len + dest_len] = '\0';
return dest;
}
int strncmp_a(char s1[], char s2[], size_t n)
{
size_t i = 0;
while ( (s1[i] != '\0' || s2[i] != '\0') && i < n ) {
if (s1[i] != s2[i]) {
return s1[i] - s2[i];
}
i++;
}
return 0;
}
int strcmp_a(char s1[], char s2[])
{
return strncmp_a(s1, s2, SIZE_MAX);
}
char *strchr_a(char s[], int c)
{
size_t str_len = strlen(s);
for (size_t i = 0; i < str_len; i++) {
if (s[i] == c) {
return &s[i];
}
}
return NULL;
}
char *strrchr_a(char s[], int c)
{
for (size_t i = strlen(s)-1; i >= 0; i--) {
if (s[i] == c) {
return &s[i];
}
}
return NULL;
}
char *strpbrk_a(char s[], char accept[])
{
size_t i = 0;
size_t accept_len = strlen(accept);
while (s[i] != '\0') {
for (size_t j = 0; j < accept_len; j++) {
if (s[i] == accept[j]) {
return &s[i];
}
}
i++;
}
return NULL;
}
bool __substring_match__(char str[], char substr[], size_t start)
{
size_t i = 0;
while (substr[i] != '\0') {
if (str[i+start] != substr[i]) {
return false;
}
i++;
}
return true;
}
char *strstr_a(char haystack[], char needle[])
{
size_t i = 0;
while (haystack[i] != '\0') {
if (__substring_match__(haystack,needle,i)) {
return &haystack[i];
}
i++;
}
return NULL;
}

18
Week 8/4_str/arrays.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _STR_ARRAYS_H
#define _STR_ARRAYS_H
extern char *strcat_a(char dest[], char src[]);
extern int strncmp_a(char s1[], char s2[], size_t n);
extern int strcmp_a(char s1[], char s2[]);
extern char *strchr_a(char s[], int c);
extern char *strrchr_a(char s[], int c);
extern char *strpbrk_a(char s[], char accept[]);
extern char *strstr_a(char haystack[], char needle[]);
#endif

100
Week 8/4_str/pointers.c Normal file
View File

@ -0,0 +1,100 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
// the dest string must have enough space for the result. If dest is not large
// enough, program behavior is unpredictable
char *strcat_p(char *dest, char *src)
{
char *return_ptr = dest;
dest += strlen(src);
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return return_ptr;
}
int strncmp_p(char *s1, char *s2, size_t n)
{
size_t i = 0;
while ( (*s1 != '\0' || *s2 != '\0') && i < n ) {
if (*s1 != *s2) {
return *s1 - *s2;
}
s1++;
s2++;
i++;
}
return 0;
}
int strcmp_p(char *s1, char *s2)
{
return strncmp_p(s1, s2, SIZE_MAX);
}
char *strchr_p(char *s, int c)
{
while (*s != '\0') {
if (*s == c) {
return s;
}
s++;
}
return NULL;
}
char *strrchr_p(char *s, int c)
{
char *s_ = *s + strlen(s) - 1;
while (s_ >= s) {
if (*s == c) {
return s;
}
s--;
}
return NULL;
}
char *strpbrk_p(char *s, char *accept)
{
size_t accept_len = strlen(accept);
while (*s != '\0') {
for (char *c = accept; c < accept+accept_len; c++) {
if (*s == *c) {
return s;
}
}
}
return NULL;
}
bool __substring_match__(char *haystack_start, char *needle)
{
while (*needle != '\0') {
if (*haystack_start != *needle) {
return false;
}
haystack_start++;
needle++;
}
return true;
}
char *strstr_p(char *haystack, char *needle)
{
while (*haystack != '\0') {
if (__substring_match__(haystack,needle)) {
return haystack;
}
haystack++;
}
return NULL;
}

18
Week 8/4_str/pointers.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _STR_POINTERS_H
#define _STR_POINTERS_H
extern char *strcat_p(char *dest, char *src)
extern int strncmp_p(char *s1, char *s2, size_t n)
extern int strcmp_p(char *s1, char *s2)
extern char *strchr_p(char *s, int c)
extern char *strrchr_p(char *s, int c)
extern char *strpbrk_p(char *s, char *accept)
extern char *strstr_p(char *haystack, char *needle)
#endif

79
Week 8/4_str/stringtest.c Normal file
View File

@ -0,0 +1,79 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "arrays.h"
#include "pointers.h"
void print_cmp(char s1[], char s2[], int n)
{
if (n == 0) {
printf("strcmp(%s,%s) = %i\n", s1, s2, strcmp(s1, s2));
printf("\tstrcmp_a(%s,%s) = %i\n", s1, s2, strcmp_a(s1, s2));
} else {
printf("strncmp(%s,%s,%i) = %i\n", s1, s2, n, strncmp(s1, s2, n));
printf("\tstrncmp_a(%s,%s,%i) = %i\n", s1, s2, n, strncmp_a(s1, s2, n));
}
}
void print_chr(char str[], char c)
{
char *strchr_ptr = strchr(str, c);
printf("strchr(): V %c; PTR %lu\n", *strchr_ptr, strchr_ptr-&str[0]);
strchr_ptr = strchr_a(str, c);
printf("\tstrchr_a(): V %c; PTR %lu\n", *strchr_ptr, strchr_ptr-&str[0]);
strchr_ptr = strrchr(str, c);
printf("strrchr(): V %c; PTR %lu\n", *strchr_ptr, strchr_ptr-&str[0]);
strchr_ptr = strrchr_a(str, c);
printf("\tstrrchr_a(): V %c; PTR %lu\n", *strchr_ptr, strchr_ptr-&str[0]);
}
void print_pbrk(char str[], char accept[])
{
char *strpbrk_ptr = strpbrk(str, accept);
printf("strpbrk(): V %c; PTR %lu\n", *strpbrk_ptr, strpbrk_ptr-&str[0]);
strpbrk_ptr = strpbrk_a(str, accept);
printf("\tstrpbrk_a(): V %c; PTR %lu\n", *strpbrk_ptr, strpbrk_ptr-&str[0]);
}
void print_strstr(char haystack[], char needle[])
{
char *strstr_ptr = strstr(haystack, needle);
printf("strstr(): PTR %lu\n", strstr_ptr-&haystack[0]);
strstr_ptr = strstr_a(haystack, needle);
printf("\tstrstr_a(): PTR %lu\n", strstr_ptr-&haystack[0]);
}
int main(int argc, char const *argv[])
{
char string_1[40] = "Hello ";
char string_2[] = "World!";
// TEST strcat()
char *dest = strcat_a(string_1, string_2);
printf("%s\n", dest);
// TEST strcmp()
print_cmp("ABC", "ABC", 0);
print_cmp("ABCD", "AB", 0);
print_cmp("AB", "ABC", 0);
print_cmp("ABA", "ABZ", 0);
print_cmp("ABJ", "ABC", 0);
// TEST strncmp()
print_cmp("ABC", "AB", 3);
print_cmp("ABC", "AB", 2);
// TEST strchr(), strrchr()
char string_3[] = "Sussy susser";
print_chr(string_3,'u');
// TEST strpbrk()
print_pbrk(string_3,"yer");
print_pbrk(string_3,"s");
// TEST strstr()
print_strstr(string_3,"sus");
print_strstr(string_3,"ss");
return 0;
}

View File

@ -0,0 +1,77 @@
/*
* 🌶 🌶 Write a function named sortPointers() that sets an array of integer
pointers to point to the elements of another array in ascending order.
* Your function should accept three parameters: the array of integers, the array
of integer pointers to assign, and the integer count of the number of elements
in the array, and hence should have the prototype:
void sortPointers(int src[], int *ptrs[], int n);
* Your function should not change the original array, nor create any other
arrays in completing this task.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#define TEST_LENGTH 16
void swap_pointers(int **a, int **b)
{
int *tmp = *a;
*a = *b;
*b = tmp;
}
bool sorted(int *ptrs[], int n)
{
for (size_t i = 1; i < n; i++) {
if (*ptrs[i-1] > *ptrs[i]) {
swap_pointers(&ptrs[i-1],&ptrs[i]);
return false;
}
}
return true;
}
// V. SLOW SORT
void sortPointers(int src[], int *ptrs[], int n)
{
for (size_t i = 0; i < n; i++) {
ptrs[i] = &src[i];
}
while (!sorted(ptrs,n)); // KEEP SWAPPING WHILE NOT SORTED - SLOW SORT.
}
// TEST sortPointers()
void intialize_rand_arr(int *arr)
{
putchar('[');
for (size_t i = 0; i < TEST_LENGTH; i++) {
int value = rand() % 512;
printf("%i, ", value);
arr[i] = value;
}
printf("]\n");
}
int main(int argc, char const *argv[])
{
srand(time(NULL));
int *ptrs[TEST_LENGTH];
int src[TEST_LENGTH];
intialize_rand_arr(src);
sortPointers(src, ptrs, TEST_LENGTH);
for (size_t i = 0; i < TEST_LENGTH; i++) {
printf("%i\t%lu\n",*ptrs[i],(long)ptrs[i]);
}
return 0;
}

View File

@ -0,0 +1,36 @@
/*
* Write a function named money that accepts a single integer parameter that
represents a total number of cents, and breaks the total down into its numbers
of dollars and cents. Your function should calculate the number of dollars,
and the number of "left-over" cents, and provide these to its calling function
through its parameters. For example, a value of 524 should be "returned" as 5
dollars and 24 cents.
* Your function should have the prototype:
void money(int total, int *dollars, int *cents);
* and be called as:
money(524, &dollars, &cents);
*/
#include <stdlib.h>
#include <stdio.h>
void money(int total, int *dollars, int *cents)
{
*dollars = total/100;
*cents = total % 100;
}
int main(int argc, char const *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: money [INT CENTS]\n");
exit(EXIT_FAILURE);
}
int dollars;
int cents;
money(atoi(argv[1]), &dollars, &cents);
printf("%i dollars, %i cents.\n", dollars, cents);
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,69 @@
/*
* Write a function named maximum_a() that accepts an integer array and the
number of elements in that array as parameters, returning a pointer to the
maximum integer in the array. It should have the prototype:
int *maximum_a(int values[], int n);
* Your function should access elements of values as an array.
* Write a (very similar) version of the maximum_a() function that now accepts
the integer array as a pointer. It should have the prototype:
int *maximum_p(int *values, int n);
* Use *pointer arithmetic* to complete this task.
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define TEST_LENGTH 16
int *maximum_a(int values[], int n)
{
int *max = &values[0];
for (size_t i = 0; i < n; i++) {
if (values[i] > *max) {
max = &values[i];
}
}
return max;
}
int *maximum_p(int *values, int n)
{
int *max = &values[0];
int *end = &values[0]+n;
for (int *v_ptr = max; v_ptr < end; v_ptr++) {
if (*v_ptr > *max) {
max = v_ptr;
}
}
return max;
}
// TEST maximum_a()
void intialize_rand_arr(int *arr)
{
putchar('[');
for (size_t i = 0; i < TEST_LENGTH; i++) {
int value = rand() % 512;
printf("%i, ", value);
arr[i] = value;
}
printf("]\n");
}
int main(int argc, char const *argv[])
{
srand(time(NULL));
int arr[TEST_LENGTH];
intialize_rand_arr(arr);
int *maximum_a_result = maximum_a(arr, TEST_LENGTH);
printf("maximum_a() : Maximum is %i\n", *maximum_a_result);
int *maximum_p_result = maximum_p(arr, TEST_LENGTH);
printf("maximum_p() : Maximum is %i\n", *maximum_p_result);
return 0;
}