Starting from:

$115

CIT593 Module 10 Assignment Solution

C Strings
Table of Contents
Assignment Overview 3
Learning Objectives 3
Advice 3
Getting Started 4
Codio Setup 4
Starter Code 4
my_string.h 4
my_string.c 4
program1.c 4
Background - Introduction and my_strlen 5
Problem 1 - Creating Your Own Library of String Functions 6
Overview 6
Requirements 6
Hints 7
Problem 2 - Adding Non-Standard String Functions to Your Library 8
Overview 8
Requirements 9
Problem 3 - Parsing Strings 11
Overview 11
The sscan and sprintf functions 11
Arguments to main 11
Problem 3 Task 12
Requirements 12
Problem 4 (Extra Credit) - my_strtok 14
Overview 14
Requirements 14
A Hint 14
Testing Your Functions 15
Submission 16
Submission Checks 16
Consistency Checks 16
The Actual Submission 16
Grading 17
Main Assignment 17
Extra Credit 17
Hints or FAQs 18
Resources 19



Assignment Overview
The goal of this assignment is to give you experience with strings in C and with the library of functions designed to work with strings, give you an appreciation of how those functions work, and also continue to help you work with pointers and arrays (in the context of C Strings).

Learning Objectives
● Implement a library of functions based on requirements
● Program with pointers using array notation and pointer arithmetic
● Practice with C Strings
● Make working makefiles

Advice
● Test with many examples, not just one
● Start early and ask questions early. Do not wait until the last minute to do this assignment!
● Remember that C Strings require a null terminator ('')
● Don't return pointers to stack arrays from functions. The compiler will probably warn you about this too. Always compile with the -Wall option.


Getting Started
Codio Setup
● Open the Codio assignment via Canvas. This is necessary to link the two systems.
● We have provided three starter code files.
● We have not provided a makefile. Part of the assignment is for you to do this yourself. You can refer to the previous assignment for an example about building a C project that includes multiple .c files.

Starter Code
We have provided a basic framework and several function definitions that you must implement.
my_string.h
This file contains the function declarations you must implement. Aside from adding the required declarations for my_strrev, my_strccase, and optionally my_strtok, do not modify this file.

my_string.c
This file contains empty implementations for the functions defined in my_string.h. We have provided the implementations of my_strlen using array notation and pointer arithmetic for you. You will provide the remaining implementations in this file.

program1.c
This is a test environment program only. We will not review it or even look at it and it will not be used for grading. You are free to write any code necessary to test your implementations.



Background - Introduction and my_strlen
char my_string [100] = "Tom" ;
strlen(my_string) would return 3.
Even though there are 100 bytes allocated on the stack for the string, since there are only 3 characters (followed by a NULL), the length of the string is indeed 3.
my_strlen_array treats the incoming argument (char* string) as if it is an array using array
notation (i.e. with square brackets [ and ])
size_t my_strlen_array(const char *str) int len = 0 ;
while (str[len] != '') { len++ ;
} return (len) ;
}

my_strlen_pointer treats the incoming argument as the pointer it truly is, using pointer
arithmetic to determine the string’s length.
size_t my_strlen_pointer(const char *str) const char* s; for (s = str; *s; ++s) ; return (s - str);
}
Note: size_t is not an actual C type; is a “typedef’ed”, that is, it is a shortcut for unsigned long.

Your task for this assignment is to implement your own library of string functions to mimic the standard C library string functions.
In Codio, we have provided a header file called my_string.h. In that header file, we have declared several functions: my_strlen_array, my_strcpy_pointer, etc.
In my_string.c, we have implemented only two of the many functions:
my_strlen_array and my_strlen_pointer, as described above. You will implement the remaining functions.
In a third file: program1.c, we have provided some basic code that calls the functions in your my_string library and compares the output of them to functions in the standard C-library string.h. This is one way to quickly check if your output is correct. Look carefully at these three files before continuing.

Problem 1 - Creating Your Own Library of String Functions
For this problem, your task is to implement your own library of string functions to mimic the standard C library string functions.

Overview
● Your job is to complete the implementation of my_string.c and test the functionality in program1.c.
● Notice that you must make two versions of the same function, one using array notation and the other using pointer notation.
○ As an example, my_strlen_array uses array notation to calculate the length of the string, while my_strlen_pointer uses a much more efficient
implementation using pointers to do the same thing. This is your chance to truly play with pointers and see if you can come up with more efficient techniques to solve problems than were done using array notation.
● Since many of these functions will be new for you, we have included helpful links in the Resources section so you can learn to use each of these functions before you try to implement them!
○ The main concept you need to understand is that, if a function declares a variable as const, that means the function promises to not modify that variable.

Requirements
● You MUST NOT modify my_string.h in any way, except to add the required function declarations my_strrev, my_strccase, and (optionally) my_strtok.
● You MUST NOT use the standard library string.h in your implementations.
● You MUST complete the implementations of the my_string library in my_string.c.
○ You MUST implement my_strcpy_array using array notation and my_strcpy_pointer using pointer notation.
○ You MUST implement my_strchr_array using array notation and my_strchr_pointer using pointer notation.
○ You MUST implement my_strcat_array using array notation and my_strcat_pointer using pointer notation.
○ You MUST implement my_strcmp_array using array notation and
my_strcmp_pointer using pointer notation.
● You MUST create a makefile called makefile with the following targets:
○ my_string.o
○ program1
○ all
○ clean, which MUST remove all .o files only
○ You MUST NOT use a _array function inside a _pointer function
○ You MUST NOT use a _pointer function inside a _array function
● You MUST NOT have "debug print statements" in any implementation. If you choose to use print statements inside your functions, you MUST comment them out or remove them before submission. We discourage print statements in general and suggest learning gdb as your debugging tool.
● Your implementations MUST function the same as the standard library functions.
○ Part of the assignment is to explore these functions and see how they work with different kinds of inputs. This means you will need to think critically about edge cases, see how the standard library handles them, and implement the same functionality on your own. Therefore, we will not provide a set of requirements for these functions.
○ You MUST return a NULL pointer in other scenarios, which you will need to discover by investigating the string.h standard library functions.
● You SHOULD comment your code since this is a programming best practice.

Hints
● For my_strcmp, the return value just needs to be the correct sign (-, 0, or +), not the actual char difference. The specific magnitude of the negative or positive number returned does not matter.



Problem 2 - Adding Non-Standard String Functions to Your Library

Overview
● In the previous section you implemented and tested functions that mimic those in the standard C-library. Now you’ll add two functions that don’t exist in the C-library, but will exist in your own my_string library!
● my_strrev
○ This function takes a single string argument, reverses the contents of the string that is passed in, and returns a pointer to the resulting string.
○ As an example:
char my_string [] = "Tom" char* ptr = my_strrev(my_string) ;
After my_strrev returns, my_string contains "moT", and ptr points to the first element in my_string. ● my_strccase
○ This function takes a single string argument, converts each character of the string to the opposite case, and returns a pointer to the resulting string.
○ As an example:
char my_string [] = "Tom" char* ptr = my_strccase(my_string) ;
After my_strccase returns, my_string contains "tOM" and ptr, points to the first element in my_string.
○ As a hint, examine the ASCII table, you will see that if you work on the hexadecimal characters directly, you can very easily convert them to their upper or lowercase equivalents!
● You do not need to make two versions of these functions (pointers and array). You can implement them anyway you see fit. You will need to modify my_string.h (adding the proper declaration statement for each of these new functions) and my_string.c (adding the proper definition of each of these new functions). And you will need to create program2.c to properly test these new function’s you’ve created.
● Create a new program called program2.c to test these new functions.
● Be sure to add a “program2” directive to your existing Makefile.


Requirements
● You MUST call the two functions my_strrev and my_strccase.
● my_strrev MUST
○ take a single char* argument (the string to reverse) ○ reverse the characters "in place"
■ It MUST NOT return a new pointer but rather modify the contents of the original string
● my_strccase MUST
○ be called my_strccase (yes, there are two cs, for "change case")
○ take a single char* argument (the string to change cases)
○ change the case of the characters "in place" (lowercase becomes uppercase and uppercase becomes lowercase)
■ It MUST NOT return a new pointer but rather modify the contents of the original string
■ It MUST NOT use ctype.h. We are explicitly forbidding this header since it trivializes the assignment.
○ return a pointer that points to the start of the modified string.
○ take no action on non-letter characters (e.g. numbers or symbols).
● You MUST add function declarations for the two functions to my_string.h.
○ You MUST NOT modify my_string.h in any other way.
● You MUST NOT use the standard library string.h in your implementations.
● You MUST complete the implementations of the two functions in my_string.c.
○ You MUST implement the functions using either array notation or pointer notation. You are free to choose either method for these functions.
● You MUST update your makefile for the following targets:
○ program2
○ all
○ clean
○ clobber
● You MUST NOT have "debug print statements" in any implementation. If you choose to use print statements inside your functions, you must comment them out or remove them before submission. We discourage print statements in general and suggest learning gdb as your debugging tool.

● You SHOULD comment your code since this is a programming best practice.

Problem 3 - Parsing Strings

Overview
The sscan and sprintf functions
● sscanf and sprintf and are two very useful functions related to scanf and printf frequently used to parse strings and convert data from strings into different data types.
● sscanf works identically to scanf except, instead of reading the keyboard for input, it reads a C String as its input
● sprintf works identically to printf except, instead of using the ASCII display for output, it uses a C String as its output.
● Since you already know how to use scanf and printf, this problem will feel familiar. The two links in the Resources section provide a reference for their arguments/returns and basic function.
○ DO NOT use your version of my_strcat; use the official library strcat in string.h for the problem.
○ You should be familiar with this function by now, but we have a reference link for it in the Resources section.
Arguments to main
● Recall from the lectures on the stack, that the function main always has a blank spot for arguments, but our declaration of main never has any arguments. Well, it’s actually possible for main to take arguments. BUT, they can only be specified as follows: int main (int argc, char** argv) ;
○ The first argument: argc (argument count) contains the number of arguments passed to main.
○ The second argument: argv (argument vector) is actually a pointer to an array of strings. Each element of the array is a single char* for one of the arguments.
● How exactly do you pass arguments to main? You do it when you start your program in the terminal.
● Take the following code and put it in a file called program3.c int main (int argc, char** argv) { printf ("# of arguments passed: %d ", argc) ; for (int i=0; i< argc ; i++) { printf ( "argv[%d] = %s ", i, argv[i] ) ;
} return (0) ;
}
● Compile it, and then run it with this command:
./program3 arg1 2 arg3 4 arg5
● Watch the output and look at the code above to see how it works! Try it with different arguments and watch how things change.
Problem 3 Task
● Notice that all the arguments passed in are treated as C Strings in your program. Even though 2 is a number, it is treated as a NULL terminated character array (a C String) inside the argv array.
● You will be adding additional code to program3.c to
○ read each char* argument in the argv array,
○ determine if it is an integer or a string,
○ store the integers into a new array,
○ store the strings into a single large string,
○ print the contents of the integer array with each integer on a new line, ○ and then print the combined large string.
● You will also need to remove any other print statements from the program.

Requirements
● You MUST write your solution to the task in program3.c.
● Your program MUST do the following:
○ Process all arguments provided to your program.
○ Remove the ./ characters from the zeroth argument of argv.
○ Convert any argument that is actually an integer from its string form into an integer using sscanf.
■ As a small hint, look at the return type of sscanf (notice that it returns the number of matches it made to your string)
○ Store any integer arguments into an array of integers.
■ For the above example, your program would generate an array: {2, 4}
■ We will not be testing strings that start with integers (e.g. 123abc). If an argument begins with an integer, you can assume that it is always an integer and not a string.
○ Store any non-integer argument into 1 large string, each argument separated by spaces
■ You MUST use either strcat or sprintf.
■ For the above example, your program would generate a string: "program3 arg1 arg3 arg5".
○ Print the contents of your integer array with each element on a new line.
○ Print the contents of your single string.
○ Print ONLY the integers and string, without any labels or any other additions. For the above example, your program MUST print exactly:
2 4
program3 arg1 arg3 arg5

● You MUST update your makefile for the following targets:
○ program3
○ all
○ clean
○ clobber
● You MUST NOT have "debug print statements" in your program. If you choose to use print statements as part of debugging, you MUST comment them out or remove them before submission. We discourage print statements in general and suggest learning gdb as your debugging tool.
● You SHOULD comment your code since this is a programming best practice.



Problem 4 (Extra Credit) - my_strtok

Overview
● One of the more difficult string functions to use and to implement is strtok(). This function takes a string and "tokenizes" it; that is, it separates the original string into a series of tokens. This is similar to the Java or Python split method.
● Since this is an extra credit problem, we will provide minimal guidance. But we do have a resource in the Resources section.

Requirements
● You MUST add function declarations for this function to my_string.h.
○ You MUST NOT modify my_string.h in any other way.
● You MUST add a function definition for this function to my_string.c.
● You MUST NOT use the standard library string.h in your implementations.
● You MUST implement the functions using either array notation or pointer notation. You are free to choose either method for this function.
● You MUST update your makefile for the following targets:
○ program4
○ all
○ clean
○ clobber
● You MUST NOT have "debug print statements" in any implementation. If you choose to use print statements inside your functions, you must comment them out or remove them before submission. We discourage print statements in general and suggest learning gdb as your debugging tool.
● You SHOULD comment your code since this is a programming best practice.

A Hint
● On the first call to my_strtok, we pass a string we want to tokenize and a delimiter.
my_strtok must return the first token (the portion of the string up to but not including the first occurrence of the delimiter).
● On each subsequent call to my_strtok, we pass a NULL pointer instead of the string, and my_strtok must return the next token.
● When no more tokens are found, my_strtok must return NULL. This indicates that my_strtok must “remember” the string passed in when first called.

Testing Your Functions
● program1.c and program2.c are for student testing only. We will not review them or test them in any way.
● Remember to test the return results from functions like my_strrev and my_strccase that both modify the string in place and also return a ptr to the modified string.
● You can assume that we will not pass any NULL pointers to your string functions. You will have to return NULL in some cases, but you do not have to check if any arguments to your functions are NULL. You can also assume that if we wish to modify the string, a string literal will not be passed.
● We recommend testing your functions against the standard library string functions (string.h). The output and return values should be the same.
● Note that my_strcat_array and my_strcat_pointer modify the original string, so you will want to test with different strings to avoid confusion between test runs



Submission
Submission Checks
There is a single "submission check" test that runs once you upload your code to Gradescope. This test checks that you have submitted all required files and also that your program compiles and any autograder code compiles successfully. It does not run your program or provide any input on whether it works or not. This check just ensures that all the required components exist. This test is performed after uploading to Gradescope.
Consistency Checks
The autograder will also show the results of six tests:
1. testStrCatArrayHelloWorld
2. testStrCatPointerHelloWorld
3. testStrchrArrayFirstChar
4. testStrchrPointerFirstChar
5. testStrcmpArraySameWord
6. testStrcmpPointerSameWord
The remaining tests will be hidden until after grades are published.

The Actual Submission
You will submit this assignment to Gradescope in the assignment entitled Assignment 10: Strings in C.
Download the required .c source and .h header files (as well as any additional helper files required) and your Makefile from Codio to your computer, then Upload all of these files to the Gradescope assignment. We expect my_string.c, my_string.h, program3.c, and makefile. Do not submit program1.c, program2.c., or program4.c.
Do not not submit intermediate files (anything .o).
We will only grade the last submission uploaded.
Do not mark your Codio workspace complete. Only the submission in Gradescope will be used for grading purposes.


Grading
This assignment is worth 127.5 points, normalized to 100% for gradebook purposes.
Main Assignment
Problem 1 (standard functions) is worth 72 points (each function is 9 points, with equally weighted sub-tests per function).
Problem 2 (custom functions) is worth 18 points (each function is 9 points, with equally weighted sub-tests per function).
Problem 3 (parsing strings) is worth 10 points.

Problems 1, 2, and the Extra Credit are tested with Unit Testing. We will run different scenarios for each function to validate the functionality (partial credit based on which tests fail).
Problem 3 checks the final output produced by your program and compares that output to the expected output. It must match exactly for credit: double check that your program does not have any extra output.
We will only grade the last submission, regardless of the results of any previous submission.
We will not be providing partial credit for autograder tests.

Extra Credit
The Extra Credit is worth 6 percentage points so the highest grade on the assignment is 106%.
Your extra credit must not break functionality for the non-extra credit requirements.
There is no partial credit. It must work completely for any credit.
We will not give guidance on how to do this since it is designed to be challenge problem.


Hints or FAQs
Hints from previous semesters
● Don't mis-spell my_strccase
● Write many test cases. A common cause of low grades is not being thorough in testing ● Don't forget the NULL terminator in your strings.
● You will need to add -g to your makefile for all intermediate steps to use gdb for debugging those intermediate object files.
● You no longer need to log gdb output to gdb.txt. That was only for Assignment 9.
You will probably never log gdb output again and we do not expect to see this anymore.


Resources
strlen reference https://www.tutorialspoint.com/c_standard_library/c_function_strlen.htm

strcpy reference https://www.tutorialspoint.com/c_standard_library/c_function_strcpy.htm

strchr reference https://www.tutorialspoint.com/c_standard_library/c_function_strchr.htm

strcat reference
https://www.tutorialspoint.com/c_standard_library/c_function_strcat.htm

strcmp reference https://www.tutorialspoint.com/c_standard_library/c_function_strcmp.htm

sscanf reference
https://www.tutorialspoint.com/c_standard_library/c_function_sscanf.htm
sprintf reference https://www.tutorialspoint.com/c_standard_library/c_function_sprintf.htm

strtok reference
https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm

strtok reference (Linux manual pages) https://man7.org/linux/man-pages/man3/strtok_r.3.html

The const modifier http://www.geeksforgeeks.org/const-qualifier-in-c/


More products