Character Inspection and Case Transformation
The <ctype.h> header provides a suite of routines for evaluating character properties and performing case adjustments. Functions such as islower inspect ASCII ranges to determine character classification, while toupper and tolower return modified characters only when applicable, leaving digits and punctuation untouched.
#include <stdio.h>
#include <ctype.h>
int main(void) {
char message[] = "C programming emphasizes memory control.";
size_t idx = 0;
while (message[idx] != '\0') {
if (islower((unsigned char)message[idx])) {
message[idx] = toupper((unsigned char)message[idx]);
}
idx++;
}
printf("Result: %s\n", message);
return 0;
}
String Length Measurement (strlen)
This utility calculates the distance from the starting address to the first null terminator. It strictly counts printable and non-printable characters preceding \0, excluding the terminator itself. The return type is size_t, an unsigned integer, which prevents accidental negative values during arithmetic operations.
#include <stdio.h>
/* Custom length calculation using pointer arithmetic */
size_t custom_strlen(const char* sequence) {
const char* tracker = sequence;
while (*tracker != '\0') {
tracker++;
}
return (size_t)(tracker - sequence);
}
int main(void) {
char data[] = "Hello World";
printf("Character count: %zu\n", custom_strlen(data));
return 0;
}
String Duplication and Controlled Copying (strcpy / strncpy)
Unbounded duplication copies charatcers until the null terminator is encountered, automatically transferring \0 to the destination. The target buffer must be pre-allocated and writable to prevent segmentation faults. The length-limited variant acccepts a count parameter; if the source is shorter, the remainder is zero-padded. If longer, no implicit terminator is added, requiring manual insertion.
#include <stdio.h>
char* replicate_string(char* dest, const char* source) {
char* origin = dest;
while ((*dest++ = *source++) != '\0');
return origin;
}
char* bounded_replicate(char* target, const char* input, size_t limit) {
char* backup = target;
size_t written = 0;
while (written < limit && *input != '\0') {
*target++ = *input++;
written++;
}
/* Pad remaining space if source exhausted early */
while (written++ < limit) {
*target++ = '\0';
}
return backup;
}
int main(void) {
char destination[32] = {0};
char source[] = "Standard Library";
replicate_string(destination, source);
printf("Full copy: %s\n", destination);
return 0;
}
Sequence Appending and Length-Limited Concatenation (strcat / strncat)
Appending locates the existing null terminator in the destination, then overwrites it with characters from the source until another null terminator is copied. The limited version appends at most n bytes and always guarantees a null terminator at the end, preventing buffer overflows when the source exceeds the specified limit.
#include <stdio.h>
char* concatenate_sequences(char* base, const char* suffix) {
char* cursor = base;
while (*cursor != '\0') cursor++;
while ((*cursor++ = *suffix++) != '\0');
return base;
}
char* limited_append(char* destination, const char* addition, size_t max_chars) {
char* write_pos = destination;
while (*write_pos) write_pos++;
size_t copied = 0;
while (copied < max_chars && *addition) {
*write_pos++ = *addition++;
copied++;
}
*write_pos = '\0';
return destination;
}
int main(void) {
char storage[64] = "Initial ";
limited_append(storage, "Data Processing", 10);
printf("Appended: %s\n", storage);
return 0;
}
Lexicographical Comparison and Partial Comparison (strcmp / strncmp)
Comparison routines evaluate character pairs sequentially based on ASCII values. They halt upon encountering a mismatch or a null terminator, returning a positive, zero, or negative integer. The bounded variant restricts evaluation to a specific character count, useful for fixed-length fields or version strings.
#include <stdio.h>
int compare_text(const char* left, const char* right) {
while (*left != '\0' && *left == *right) {
left++;
right++;
}
return *(const unsigned char*)left - *(const unsigned char*)right;
}
int limited_compare(const char* s1, const char* s2, size_t limit) {
if (!limit) return 0;
while (--limit > 0 && *s1 && *s1 == *s2) {
s1++;
s2++;
}
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}
int main(void) {
const char* alpha = "abc";
const char* beta = "abd";
printf("Comparison result: %d\n", compare_text(alpha, beta));
return 0;
}
Substring Location (strstr)
This function scans a primary sequence for the first occurrence of a secondary pattern. It returns a pointer too the initial match within the primary buffer or NULL if no alignment is found. An empty pattern string immediately returns the primary sequence address.
#include <stdio.h>
const char* find_pattern(const char* text, const char* pattern) {
if (!text || !pattern) return NULL;
if (!*pattern) return text;
for (const char* pos = text; *pos; ++pos) {
const char* match = pos;
const char* needle = pattern;
while (*match && *needle && *match == *needle) {
match++;
needle++;
}
if (*needle == '\0') return pos;
}
return NULL;
}
int main(void) {
const char* document = "Search for critical errors in logs.";
const char* keyword = "errors";
const char* location = find_pattern(document, keyword);
if (location) {
printf("Found: \"%s\"\n", location);
}
return 0;
}
String Tokenization (strtok)
Tokenization splits a mutable string using a delimiter set. The routine modifies the original buffer by replacing delimiters with \0, allowing sequential extraction. It retains internal state between calls; passing NULL after the initial invocation resumes scanning from the last recorded position until no tokens remain.
#include <stdio.h>
#include <string.h>
int main(void) {
char raw_input[] = "name:John;age:30;city:Berlin|country:DE";
const char* delimiters = ":|;";
char* segment = strtok(raw_input, delimiters);
while (segment != NULL) {
printf("Parsed segment: %s\n", segment);
segment = strtok(NULL, delimiters);
}
return 0;
}
Error Code Translation (strerror)
System calls populate the global errno variable when failures occur. This utility maps the numeric error code to a human-readable diagnostic message, facilitating debugging and logging without hardcoding string literals.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main(void) {
int fd = open("nonexistent_file.txt", O_RDONLY);
if (fd == -1) {
printf("Failure detected: %s\n", strerror(errno));
}
return 0;
}