C++ Notes
#include <cctype>.char variable directly.| Function | What It Checks or Does |
|---|---|
std::isalnum(c) | checkReturns non-zero if the character is a letter or a digit (alphanumeric). |
std::isalpha(c) | checkReturns non-zero if the character is a letter, uppercase or lowercase. |
std::isdigit(c) | checkReturns non-zero if the character is a decimal digit, 0 through 9. |
std::isblank(c) | checkReturns non-zero if the character is a space or horizontal tab. |
std::isupper(c) | checkReturns non-zero if the character is an uppercase letter. |
std::islower(c) | checkReturns non-zero if the character is a lowercase letter. |
std::toupper(c) | convertReturns the uppercase version of the character. The original is unchanged, store the result in a new variable. |
std::tolower(c) | convertReturns the lowercase version of the character. The original is unchanged, store the result in a new variable. |
#include <iostream> #include <cctype> int main() { char text[] = "Hey 123!"; for (char c : text) { if (c == '\0') break; // stop at null terminator std::cout << "Character: '" << c << "'\n"; if (std::isalnum(c)) std::cout << " isalnum : yes\n"; if (std::isalpha(c)) { std::cout << " isalpha : yes\n"; char upper = std::toupper(c); // original c is unchanged char lower = std::tolower(c); std::cout << " toupper : '" << upper << "'\n"; std::cout << " tolower : '" << lower << "'\n"; } if (std::isdigit(c)) std::cout << " isdigit : yes\n"; if (std::isupper(c)) std::cout << " isupper : yes\n"; if (std::islower(c)) std::cout << " islower : yes\n"; if (std::isblank(c)) std::cout << " isblank : yes\n"; std::cout << std::endl; } return 0; }
#include <cstring>.char message[]{"Hello, World!"};), a pointer to a string literal (const char* message{"Hello, World!"};, read-only), or a heap-allocated char array (char* p = new char[6]{'H','e','l','l','o','\0'};).std::size() and range-based for loops only work with stack arrays of known size. They do not work with raw pointers, whether heap or string literals.std::strlen(str) returns the number of characters in the string, not counting the null terminator '\0'.sizeof(arr) returns the total byte size of the array for stack arrays, which includes the null terminator slot.sizeof(pointer) returns the size of the pointer itself, 4 or 8 bytes, not the string length.strlen is therefore the correct, consistent way to measure C-string length regardless of how the string is actually stored.std::strcmp(a, b) compares two strings lexicographically, dictionary order based on ASCII values. Returns a negative value if a comes before b, 0 if they're equal, and a positive value if a comes after b.std::strcmp("ABC", "CBA") returns negative, because 'A' has a smaller ASCII value than 'C'.std::strncmp(a, b, n) compares only the first n characters, useful when you only care about a prefix.std::strchr(string, ch) searches for the first occurrence of character ch in the string.string here is a decayed array, a pointer to the first character, the base address.nullptr if it's not found before hitting '\0'.strchr again from the new position, and repeat until it returns nullptr.const char* text = "Try not. Do, or do not. There is no try."; char target = 'T'; const char* result = text; // start from beginning int count = 0; while ((result = std::strchr(result, target)) != nullptr) { std::cout << "Found at: \"" << result << "\"\n"; ++result; // move past current match ++count; } std::cout << "Total: " << count << std::endl;
std::strrchr(string, ch) searches through the entire string and returns the address of the last occurrence of ch.nullptr if no match is found.char path[] = "/home/user/hello.cpp"; char* output = std::strrchr(path, '/'); // points to last '/' if (output) std::cout << output + 1 << std::endl; // +1 skips past '/' --> prints: hello.cpp
#include <iostream> #include <cstring> int main() { char stackStr[] = "Hello, World!"; const char* literalStr = "Hello, World!"; char* heapStr = new char[6]{'H','e','l','l','o','\0'}; // 1) length std::cout << "strlen(stackStr): " << std::strlen(stackStr) << std::endl; // prints: 13 (no '\0') std::cout << "sizeof(stackStr): " << sizeof(stackStr) << std::endl; // prints: 14 (includes '\0') std::cout << "sizeof(literalStr): " << sizeof(literalStr) << std::endl; // prints: 8 (pointer size, not string) std::cout << std::endl; // 2) comparison int cmp = std::strcmp("ABC", "CBA"); std::cout << "strcmp(ABC, CBA): " << cmp << std::endl; // prints: negative int ncmp = std::strncmp("ABCDE", "ABCXY", 3); std::cout << "strncmp first 3 chars: " << ncmp << std::endl; // prints: 0 (first 3 match) std::cout << std::endl; // 3) search first occurrence + count total const char* text = "Try not. Do, or do not. There is no try."; char target = 'T'; const char* result = text; int count = 0; while ((result = std::strchr(result, target)) != nullptr) { std::cout << "Found '" << target << "' at: \"" << result << "\"\n"; ++result; // move past current match to continue searching ++count; } std::cout << "Total occurrences: " << count << std::endl << std::endl; // 4) search last occurrence char path[] = "/home/user/hello.cpp"; char* last = std::strrchr(path, '/'); if (last) std::cout << "Filename: " << last + 1 << std::endl; // prints: hello.cpp delete[] heapStr; return 0; }
#include <cstring>.std::strcat(dest, src) appends the contents of src to the end of dest.'\0' of dest and overwrites it with the first char of src. A new '\0' is written at the end automatically.dest must already be a valid C-string, containing at least one '\0', and must be large enough to hold the existing characters plus the appended characters plus the final '\0'. Failing this causes undefined behavior.src is not modified.std::strncat(dest, src, n) is the limited version. It appends at most n characters from src, then writes a '\0'. The destination must still have enough space.char a[50]{}; // all elements '\0' char b[]{"Hello"}; // {'H','e','l','l','o','\0'} std::strcat(a, b); std::strcat(a, " World!"); std::cout << a << '\n'; // prints: Hello World!
std::strcpy(dest, src) copies src into dest, including the null terminator '\0'. The destination is completely overwritten.dest must be a writable char array, not a string literal pointer, and must be large enough to hold src plus '\0', with memory already allocated.src must be a valid null-terminated C-string.std::strncpy(dest, src, n) copies at most n characters. It does not guarantee null termination if src's length is greater than or equal to n, manual '\0' insertion is often required afterward.char a[50]{}; char b[]{"Hello"}; std::strcpy(a, b); std::cout << a << '\n'; // prints: Hello // strncpy: manual null termination needed char e[50]{}; std::strncpy(e, "HelloWorld", 5); // copies only "Hello", no '\0' guaranteed e[5] = '\0'; // manual null termination
#include <iostream> #include <cstring> int main() { // strcat: append src to dest char a[50]{}; char b[]{"Hello"}; std::strcat(a, b); // a = "Hello" std::strcat(a, " World"); // a = "Hello World" std::cout << "strcat : " << a << '\n'; // prints: Hello World // strncat: append at most n characters char c[50]{"C++ "}; std::strncat(c, "Programming Language", 11); // appends only "Programming" std::cout << "strncat : " << c << '\n'; // prints: C++ Programming // strcpy: copy src into dest (overwrites completely) char d[50]{}; std::strcpy(d, "Copy this"); std::cout << "strcpy : " << d << '\n'; // prints: Copy this // strncpy: copy at most n characters, manual '\0' needed char e[50]{}; std::strncpy(e, "HelloWorld", 5); // copies "Hello", no '\0' guaranteed e[5] = '\0'; // manual null termination required std::cout << "strncpy : " << e << '\n'; // prints: Hello return 0; }
C-style char arrays come with a real list of problems: size must be manually kept in check, you must always work within bounds explicitly, you must track the null terminator '\0' manually, and many C-string functions don't perform any bounds checking at all.
std::string hides all of these low-level details. Memory management, resizing, and null termination are all handled internally.std::string object itself, not the text it holds, is typically 24 to 32 bytes on a 64-bit system.Requires #include <string>.
std::string name; // empty string, no garbage, size = 0 std::string name{"Hassan Ali"}; // initialized from string literal std::string copy{name}; // copies full contents of name std::string first{name, 6}; // copies first 6 characters ("Hassan") std::string repeated(4, 'i'); // "iiii" (note: parentheses, not braces) std::string part{name, 7, 3}; // from index 7, copy 3 chars ("Ali") std::string msg{"Hello "}; // must start with std::string, not literal msg += name; // appends name msg += "\nHow are you"; // appends more text
The repeated-character form uses parentheses, (4, 'i'), not braces. Using braces {4, 'i'} would be interpreted as an initializer list of two chars, ASCII 4 and ASCII 105, which is not what you want at all.
#include <iostream> #include <string> int main() { std::string name; // empty string std::cout << "name : \"" << name << "\"\n"; // prints: "" std::string full{"Hassan Ali"}; std::cout << "full : " << full << '\n'; // prints: Hassan Ali std::string copy{full}; // copy constructor std::cout << "copy : " << copy << '\n'; // prints: Hassan Ali std::string first{full, 6}; // from index 0, take 6 chars std::cout << "first : " << first << '\n'; // prints: Hassan std::string repeated(4, 'i'); // 4 copies of 'i' std::cout << "repeated : " << repeated << '\n'; // prints: iiii std::string part{full, 7, 3}; // from index 7, take 3 chars std::cout << "part : " << part << '\n'; // prints: Ali // concatenation std::string msg{"Hello "}; msg += full; msg += "\nHow are you"; std::cout << "msg : " << msg << '\n'; // prints: Hello Hassan Ali\nHow are you return 0; }
Everything in this post, from <cctype> checks to manual strcat bookkeeping, is the exact set of headaches std::string exists to make disappear. Worth knowing the raw mechanics, worth defaulting to std::string anyway. Next up, functions: the compilation model, argument passing, and overloading.