Week 9: Characters and Strings (2)

String-Manipulation Functions of the String-Handling Library

The String-Manipulation Functions in the String-Handling Library (<string.h>) provide a set of tools for manipulating strings efficiently. For example,

  • The string-handling library in C facilitates manipulation of string data through functions like copying strings (strcpy) and concatenating strings (strcat).

  • String comparison operations are supported via functions such as strcmp, allowing for easy comparison of two strings.

  • Searching functionality is provided through functions like strstr, enabling users to search for characters or other strings within a given string.

  • Tokenization of strings, separating them into logical pieces, is made possible by functions like strtok, allowing for parsing of input data.

  • Determining the length of strings is supported by the strlen function, which returns the number of characters in a string excluding the null terminator.

Example: basic string operation

Try to run the following example, and see if you understand the output:

#include <stdio.h>
#include <string.h>

int main() {
    char source[] = "Hello";
    char destination[20] = "";
    char string1[] = "Hello";
    char string2[] = "World";
    char search[] = "lo";

    // Example of strcpy
    strcpy(destination, source);
    printf("Copied string: %s\n", destination);

    // Example of strcat
    strcat(destination, " World!");
    printf("Concatenated string: %s\n", destination);

    // Example of strcmp
    int compare = strcmp(string1, string2);
    if(compare == 0)
        printf("Strings are equal.\n");
    else if(compare < 0)
        printf("String1 is less than String2.\n");
    else
        printf("String1 is greater than String2.\n");

    // Example of strstr
    char *substring = strstr(source, search);
    if(substring != NULL)
        printf("'%s' found in '%s' at position: %ld\n", search, source, substring - source);
    else
        printf("'%s' not found in '%s'\n", search, source);

    return 0;
}

Do you understand when the output says "String1 is less than String2"?

In C, when we say that "String1 is less than String2," we're referring to the result of comparing the strings using functions like strcmp.

The comparison is based on lexicographical ordering (aka dictionary order). In simple terms, it means comparing strings character by character from left to right until a difference is found or one string ends.

If the first differing character in string-1 has a lower ASCII value than the corresponding character in string-2, then string-1 is considered "less" than string-2. Conversely, if the ASCII value of the differing character in string-1 is higher, then string-1 is considered "greater" than string-2.

For example:

  • "apple" is less than "banana" because 'a' comes before 'b' in the ASCII table.

  • "bat" is less than "bats" because even though the first three letters are the same, the shorter string is considered "less" than the longer one.

Keep in mind that this comparison is case-sensitive, so uppercase letters have different ASCII values than their lowercase counterparts.

If you would like to do a compare up to n characters:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "apple";
    char str2[] = "banana";
    char str3[] = "apple pie";
    char str4[] = "apple";
    int result;

    // Example of strcmp
    result = strcmp(str1, str2);
    if (result < 0)
        printf("%s is less than %s\n", str1, str2);
    else if (result > 0)
        printf("%s is greater than %s\n", str1, str2);
    else
        printf("%s is equal to %s\n", str1, str2);

    // Example of strncmp
    result = strncmp(str1, str3, 5); // Compare first 5 characters
    if (result < 0)
        printf("%.*s is less than %.*s\n", 5, str1, 5, str3);
    else if (result > 0)
        printf("%.*s is greater than %.*s\n", 5, str1, 5, str3);
    else
        printf("%.*s is equal to %.*s\n", 5, str1, 5, str3);

    // Example of strcmp for equal strings
    result = strcmp(str1, str4);
    if (result == 0)
        printf("%s is equal to %s\n", str1, str4);
    else
        printf("%s is not equal to %s\n", str1, str4);

    return 0;
}

Example on tokenize the string:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "apple,papaya,banana,orange";
    const char delimiters[] = ","; // Define delimiters (comma in this case)
    char *token;

    // Tokenize the string using strtok
    token = strtok(str, delimiters);

    // Iterate over tokens and print them
    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok(NULL, delimiters); // Pass NULL to strtok to continue tokenizing the same string
    }

    return 0;
}

Note: strtok modifies the original string by inserting '\0' characters to separate tokens. Also, calling strtok with a NULL pointer as the first argument tells it to continue tokenizing the same string from where it left off.

Search Functions of the String-Handling Library

Function prototypes and descriptions

char *strchr(const char *s, int c); Locates the first occurrence of character c in string s. If c is found, strchr returns a pointer to c in s. Otherwise, a NULL pointer is returned.

size_t strcspn(const char *s1, const char *s2);

Determines and returns the length of the initial segment of string s1 consisting of characters not contained in string s2. size_t strspn(const char *s1, const char *s2); Determines and returns the length of the initial segment of string s1 consisting only of characters contained in string s2.

char *strpbrk(const char *s1, const char *s2);

Locates the first occurrence in string s1 of any character in string s2. If a character from s2 is found, strpbrk returns a pointer to that character in s1. Otherwise, it returns NULL.

char *strrchr(const char *s, int c); Locates the last occurrence of c in string s. If c is found, strrchr returns a pointer to c in string s. Otherwise, it returns NULL.

char *strstr(const char *s1, const char *s2);

Locates the first occurrence in string s1 of string s2. If the string is found, strstr returns a pointer to the string in s1. Otherwise, it returns NULL.

Example

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello, world!";
    char *found_char;
    size_t found_index;

    // Example of strchr
    found_char = strchr(str, 'o');
    if (found_char != NULL){
        printf("First 'o' found at index: %ld\n", found_char-str);
        printf("Index of found_char = %ld, str = %ld\n",(long int)found_char,(long int)str);
    }
    else
        printf("'o' not found\n");
    printf("\n");

    // Example of strcspn and strspn
    size_t cspn_index = strcspn(str, "o"); // Search for first occurrence of o
    size_t spn_index = strspn(str, "Hello"); // Find the length of the initial segment consisting of characters in "Hello"
    printf("Index of first o: %ld\n", cspn_index);
    printf("Length of initial segment with characters in 'Hello': %ld\n", spn_index);
    printf("\n");

    // Example of strpbrk
    char *pbrk = strpbrk(str, "o"); // Search for first occurrence of 'o'
    if (pbrk != NULL)
        printf("First occurrence of 'o' after index: %ld\n", pbrk - str);
    else
        printf("'o' not found\n");
    printf("\n");

    // Example of strrchr
    char *last_o = strrchr(str, 'o'); // Find last occurrence of 'o'
    if (last_o != NULL)
        printf("Last 'o' found at index: %ld\n", last_o - str);
    else
        printf("Last 'o' not found\n");
    printf("\n");

    // Example of strstr
    char *substr = strstr(str, "world");
    if (substr != NULL)
        printf("'world' found at index: %ld\n", substr - str);
    else
        printf("'world' not found\n");

    return 0;
}

Memory Functions of the String-Handling Library

The memory functions in the String-Handling Library provide a set of tools for manipulating memory efficiently. These functions include operations such as copying memory, filling memory with a constant byte, comparing memory blocks, or searching for a byte in a memory block. They are essential for tasks involving low-level memory operations, data copying, and memory manipulation in C programming.

Function prototypes and brief descriptions for memory functions:

  1. memcpy:

    void *memcpy(void *dest, const void *src, size_t n);
    • Description: Copies n bytes from the memory area pointed to by src to the memory area pointed to by dest. The memory areas must not overlap.

  2. memmove:

    void *memmove(void *dest, const void *src, size_t n);
    • Description: Copies n bytes from the memory area pointed to by src to the memory area pointed to by dest. The memory areas may overlap, and the copy is done in a non-destructive manner.

  3. memcmp:

    int memcmp(const void *s1, const void *s2, size_t n);
    • Description: Compares the first n bytes of the memory areas pointed to by s1 and s2. Returns an integer less than, equal to, or greater than zero if s1 is found to be less than, equal to, or greater than s2, respectively.

  4. memchr:

    void *memchr(const void *s, int c, size_t n);
    • Description: Searches for the first occurrence of the character c (interpreted as an unsigned char) in the first n bytes of the memory area pointed to by s. Returns a pointer to the matched byte or NULL if the character is not found.

  5. memset:

    void *memset(void *s, int c, size_t n);
    • Description: Sets the first n bytes of the memory area pointed to by s to the value of c (interpreted as an unsigned char).

Example:

#include <stdio.h>
#include <string.h>

int main() {
    // Example of memcpy
    char src[] = "Hello, world!";
    char dest[20];
    memcpy(dest, src, strlen(src) + 1);
    printf("Copied string using memcpy: %s\n", dest);

    // Example of memmove
    char buffer[] = "Example";
    memmove(buffer + 3, buffer, strlen(buffer) + 1); // Overlapping copy
    printf("Copied string using memmove: %s\n", buffer);

    // Example of memcmp
    char str1[] = "hello";
    char str2[] = "world";
    int cmp = memcmp(str1, str2, 3); // Compare first 3 characters
    if (cmp == 0)
        printf("First 3 characters of str1 and str2 are equal.\n");
    else if (cmp < 0)
        printf("First 3 characters of str1 are less than str2.\n");
    else
        printf("First 3 characters of str1 are greater than str2.\n");

    // Example of memchr
    char str[] = "Hello, world!";
    char *ch = memchr(str, 'o', strlen(str)); // Search for 'o' in the string
    if (ch != NULL)
        printf("Found 'o' at position: %ld\n", ch - str);
    else
        printf("Did not find 'o'\n");

    // Example of memset
    char buffer2[10];
    memset(buffer2, '*', 9); // Fill the buffer with '*'
    printf("Buffer after memset: %s\n", buffer2);

    return 0;
}

When will you use memset?

memset is used to initialized dynamically allocated memory or arrays to a specific value. Suppose you're developing a program that involves processing data in large arrays. Before you start using these arrays, you need to ensure that they are properly initialized to avoid any unexpected behavior. For instance, you might need to initialize an array of integers to all zeros or set all characters in a buffer to a specific value before using it to store data.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int *array;
    size_t size = 100;

    // Dynamically allocate memory for the array
    array = (int *)malloc(size * sizeof(int));
    if (array == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        return 1;
    }

    // Initialize the array to all zeros using memset
    memset(array, 0, size * sizeof(int));

    // Now you can use the array for further processing

    // Free dynamically allocated memory
    free(array);

    return 0;
}

In this example, memset is used to initialize the dynamically allocated array array to all zeros. This ensures that all elements of the array are set to a known initial state before further processing. This practice helps prevent uninitialized memory bugs and ensures predictable behavior of your program.

Classwork - Week 9

Part 1:

Dates are commonly printed in several different formats in business correspondence. Two of the more common formats are 03/18/2024 and 18 March 2004. Write a program that reads a date in the first format and prints it in the second format.

Part 2:

Read and summarize about Cryptography. This will be one of problem for group programming.

Last updated