Project 3: String 'Em Up

Due by: Friday, February 28, 2025 at 11:59 p.m.

Is string theory a futile exercise as physics, as I believe it to be?

-Phil Anderson

Introduction

No! It's a futile exercise as computer science. Or is it? Evil henchmen of unknown provenance (perhaps coming from the huge number of pocket dimensions predicted by string theory itself) have stolen the source code for the C standard string library. After the passage of time, a future generation of C programmers may not have a string library to use. They might break into tears, burst into flames, or worse yet, program in language other than C.

Your task, if it isn't blindingly obvious already, is to write a subset of the standard C string library. Not only will you save the world (as usual), you may also understand how the library works. (Not magic after all. If you hoped to study magic instead, consider transferring here.)

Overview

Strings in C are surprisingly simplistic. They're just arrays of characters terminated by a null ('\0') character. And even the null character is only there by convention. The language offers no built-in support for strings above and beyond this. As such, any higher level operations one might want to perform on a string, such as copying, comparing, or searching, must be done using functions. The C standard library has a string library that supplies many of these functions, and for this project you must implement your own version of the some of it.

You are called upon to implement the following functions:

  • char* new_strcpy(char* destination, const char* source)
    Copies the characters from source into destination.

  • char* new_strncpy(char* destination, const char* source, size_t n)
    Copies the first n characters from source into destination. If the function hits a null character in source before it has copied n characters, the remaining characters are filled with null characters.

  • int new_strcmp(const char* string1, const char* string2)
    Compares two strings. The return value is positive if string1 comes after string2 alphabetically, negative if string1 comes before string2 alphabetically, and 0 if the two strings are equal.

  • int new_strncmp(const char* string1, const char* string2, size_t n)
    Compares two strings exactly like new_strcmp(), except comparing at most the first n characters.

  • char* new_strcat(char* destination, const char* source)
    Adds the string contained in source to the end of the string contained in destination. The values in destination are modified, but a pointer to destination is also returned.

  • char* new_strncat(char* destination, const char* source, size_t n)
    Adds the string contained in source to the end of the string contained in destination, but adding a maximum of n characters.

  • size_t new_strlen(const char* string)
    Returns the number of characters in string before the null character.

  • char* new_strchr(const char* string, int character)
    Returns a pointer to the first occurrence of character in string or a NULL pointer if character cannot be found.

  • char* new_strstr(const char* haystack, const char* needle)
    Returns a pointer to the first occurrence of the string contained in needle in haystack or a NULL pointer if needle cannot be found.

Each of these functions should behave exactly like the standard C function which has the same name without new_ prepended to it.

Implementation Details

More Specifications

I haven't given you enough information to perfectly implement these functions. What about empty strings? What happens to the null character if the n characters you copy are before the null? There are two additional sources of information you should use to answer your questions:

  1. Man Pages
    Always check the man pages. These are the authoritative sources for information about the C library. For example, if you want more information about how to implement new_strncpy(), type man strncpy or man 3 strncpy into a terminal in Ubuntu.

  2. Standard C Library
    Once you feel you have the functions working, you should test them, a lot. There are a lot of corner cases with strings. Fortunately, you have a perfect reference implementation provided by the C gods to test against. Fortunately, again, the functions have different names so they can be used in the same program.

My Main Man... is Missing

You should not submit any code with a main() function in it. Your code is meant to serve as a library that other programs can link against. Of course, you should write your own main() function in a separate file for testing purposes, but do not turn it in. When we test your functions, we will compare their functionality to that of the string library in Ubuntu using our own main() function. We will deduct points for submissions which include a main() function.

Forced to Leave the Library

You may not use any library functions in your solution. If you didn't write the function, you can't use it. You shouldn't include anything other than stddef.h which gives the definition of size_t.

Strange Cases

For a variety of implementation reasons, the standard library version will crash on invalid input, such as certain types of malformed strings. You do not need to exactly replicate this crashing behavior. However, your version of the string library should not crash in any instances where the standard library version does not.

Testing

Learning how to test software well is a central theme in COMP 2400. Come up with a huge suite of test cases covering all kinds of odd situations. Test each function independently and in conjunction with each other. Test until you don't think you can take it anymore.

In order to test this project, we recommend that you write your own main() function that makes various calls to your library and as well as the regular string library and compares the results. Remember, your version of the functions must be functionally equivalent to the standard library's version. Be sure to check the man page for any strange functionality a particular function may have, especially error cases.

If you do not thoroughly test your functions with a variety of test cases, chances are high that you will do poorly.

Turn In

Zip the contents of your project directory, including the makefile, the source C file(s), and header files. Upload this zip file to Brightspace. You should include a header file called new_string.h containing prototypes for all nine functions, which should be included by all code using your string library. Although you should not include a source file with a main() method, your makefile should compile your library with a file called main.c (created by me during testing) and create an executable called string. Do not include any object files or executables.

Do not turn in main.c, but you should have your own for testing. We will supply our own main.c for grading.

All work must be submitted before Friday, February 28, 2025 at 11:59 p.m. unless you are going to use a grace day.

Grading

Your grade will be determined by the following categories.

Category Weight
new_strcpy Correctness 10%
new_strncpy Correctness 10%
new_strcmp Correctness 10%
new_strncmp Correctness 10%
new_strcat Correctness 10%
new_strncat Correctness 10%
new_strlen Correctness 5%
new_strchr Correctness 5%
new_strstr Correctness 15%
Correct Makefile and File Naming 5%
Programming Style 10%

Under no circumstances should any member of one team look at the code written by another team. Tools will be used to detect code similarity automatically.

Code that does not compile will automatically score zero points.