Skip to content

Commit 15e0e12

Browse files
committed
strings updated
1 parent 35a7a35 commit 15e0e12

File tree

3 files changed

+183
-16
lines changed

3 files changed

+183
-16
lines changed

docs/string.md

Lines changed: 134 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* [Difference between char * and char[]](#difference-between-char---and-char--)
1515
* [size of string](#size-of-string)
1616
* [strdup](#strdup)
17+
* [strstr](#strstr)
1718
* [String copying](#string-copying)
1819
- [C++ String](#c---string)
1920
* [warning iso c++ forbids converting a string constant to ‘char*’ -wwrite-strings](#warning-iso-c---forbids-converting-a-string-constant-to--char----wwrite-strings)
@@ -346,23 +347,87 @@ std::cout<<"size of string is: "<<strlen( my_str )<<" bytes and string is: "<< m
346347
3. `str.size()` also return the size of c++ strings.
347348

348349
## strdup
349-
String Duplicate,
350350

351+
In C++, the `strdup` function (from C) is used to duplicate a string by allocating memory and copying the content of an existing string to that new memory. You would need to use `strdup` when you want to create a copy of a string that you plan to manage manually (for instance, when working with raw pointers and dynamic memory allocation).
351352

352-
Each call to `strdup` creates a new `char *` of the size matching the length of the string. You should bind it to a raw pointer `char*` and remove it at some point.
353+
Here is an example of when you might use `strdup`:
353354

355+
### Example:
354356
```cpp
355-
char* temp = strdup("foo");
357+
#include <iostream>
358+
#include <cstring> // for strdup and free
356359

357-
if(temp)
358-
{
359-
free(temp);
360+
int main() {
361+
// Original string
362+
const char* original = "Hello, World!";
363+
364+
// Duplicate the string using strdup
365+
char* duplicate = strdup(original);
366+
367+
// Print both strings
368+
std::cout << "Original: " << original << std::endl;
369+
std::cout << "Duplicate: " << duplicate << std::endl;
370+
371+
// Free the memory allocated by strdup
372+
free(duplicate);
373+
374+
return 0;
375+
}
376+
```
377+
378+
When to use `strdup`:
379+
380+
- **C-style strings**: If you're working with raw C-style strings (`char*`) and need to make a copy of the string that requires its own memory management.
381+
- **Manual memory management**: When the duplicated string will be used independently and may need to be freed later.
382+
383+
Important notes:
384+
385+
1. `strdup` allocates memory using `malloc`, so you must free it with `free` when you're done using the duplicated string.
386+
2. In C++, you generally don't need to use `strdup` if you are working with `std::string`, which manages memory automatically. Instead, use `std::string`'s copy constructor or assignment operator, which is safer and more idiomatic.
387+
388+
C++ alternative using `std::string`:
389+
390+
```cpp
391+
#include <iostream>
392+
#include <string>
393+
394+
int main() {
395+
// Original string
396+
std::string original = "Hello, World!";
397+
398+
// Duplicate the string using std::string
399+
std::string duplicate = original;
400+
401+
// Print both strings
402+
std::cout << "Original: " << original << std::endl;
403+
std::cout << "Duplicate: " << duplicate << std::endl;
404+
405+
// No need to free memory, std::string handles it automatically
406+
return 0;
360407
}
361408
```
362409

363-
It allocates a copy of a `char*` on the heap.
410+
In modern C++ code, using `std::string` is preferable to avoid manual memory management.
411+
364412

365413

414+
## strstr
415+
416+
A standard C-style API for searching a substring within a string can be implemented using the `strstr` function, which is part of the C standard library (<string.h>). The `strstr` function searches for the first occurrence of a substring in a string and returns a pointer to the beginning of the substring if found. Otherwise, it returns `NULL`.
417+
418+
```cpp
419+
char haystack[] = "Hello, World!"; // Now this is modifiable
420+
const char *needle = "World";
421+
422+
// Use strstr to find the first occurrence of the needle in the haystack
423+
char *result = strstr(haystack, needle);
424+
425+
if (result) {
426+
printf("Found substring: %s\n", result);
427+
} else {
428+
printf("Substring not found.\n");
429+
}
430+
```
366431
367432
## String copying
368433
@@ -496,19 +561,72 @@ while ((pos = s.find(delimiter)) != std::string::npos)
496561
s.erase(0, pos + delimiter.length());
497562
}
498563
```
499-
## std::string to lower/ upper case
564+
## std::tolower, std::toupper
565+
566+
567+
`std::tolower()` returns an integer, not a `std::string`, and you cannot directly cast the result to a `std::string`. Instead, you should convert the result of `std::tolower()` to a `char`, and then construct a `std::string` from that character.
568+
```cpp
569+
unsigned char c = 'A';
570+
char lower_c = static_cast<char>(std::tolower(c));
571+
572+
std::string a(1, lower_c); // Create a string with one character
573+
```
574+
575+
576+
To correctly use `std::tolower` on a std::string, you need to iterate over each character of the string and apply `std::tolower` to it. Since `std::tolower` works on single characters (and returns an int), you should also cast the result back to char. Here's how you can do this:
577+
578+
579+
```cpp
580+
std::string input = "Hello, World!";
581+
std::string result;
582+
583+
// Use std::transform to apply std::tolower to each character
584+
std::transform(input.begin(), input.end(), std::back_inserter(result),
585+
[](unsigned char c){ return std::tolower(c); });
586+
587+
std::cout << "Original: " << input << std::endl;
588+
std::cout << "Lowercase: " << result << std::endl;
500589
```
501-
#include <algorithm>
502-
#include <cctype>
503-
#include <string>
504590

505-
std::string my_str = "Foo";
506-
std::transform(my_str.begin(), my_str.end(), my_str.begin(),
507-
[](unsigned char c){ return std::tolower(c); });
508-
```
509-
# string_view
591+
- `std::transform` is used to apply the transformation (lowercasing in this case) to each character.
592+
- `std::tolower` is applied to each character of the string. It takes an `unsigned char` as input, so we cast each character to `unsigned char` to avoid undefined behavior with non-ASCII characters.
593+
- The result is accumulated in the `result` string using `std::back_inserter`.
594+
595+
This will output:
596+
```
597+
Original: Hello, World!
598+
Lowercase: hello, world!
599+
```
600+
601+
602+
## std::isalnum
603+
604+
The function `std::isalnum` in C++ checks whether a given character is either an alphanumeric character, i.e., a letter (A-Z, a-z) or a digit (0-9).
605+
606+
- digits (0123456789)
607+
- uppercase letters (ABCDEFGHIJKLMNOPQRSTUVWXYZ)
608+
- lowercase letters (abcdefghijklmnopqrstuvwxyz)
609+
610+
611+
Return Value:
612+
- It returns a **non-zero value** (typically `true`) if the character is alphanumeric.
613+
- It returns **0** (typically `false`) if the character is not alphanumeric.
510614

511615

616+
```cpp
617+
char c = 'A';
618+
if (std::isalnum(c)) {
619+
std::cout << c << " is alphanumeric." << std::endl;
620+
} else {
621+
std::cout << c << " is not alphanumeric." << std::endl;
622+
}
623+
```
624+
625+
In this case, if `c` is 'A' (an alphanumeric character), `std::isalnum(c)` will return a non-zero value, and the output will be:
626+
627+
```
628+
A is alphanumeric.
629+
```
512630
513631
# Find String Case Insensitive
514632
```cpp

src/main.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,5 +329,13 @@ int main() {
329329
std::cout << user << std::endl;
330330

331331
// if (usernames.find("who") == usernames.end())
332+
333+
unsigned char c = 'A';
334+
char lower_c = static_cast<char>(std::tolower(c));
335+
336+
std::string a(1, lower_c); // Create a string with one character
337+
338+
std::cout << std::boolalpha << static_cast<bool>(std::isalnum(c)) << '\n';
339+
332340
return 0;
333341
}

src/string.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,47 @@ void WidestringStringConversion() {
348348
// std::wstring wide = converter.from_bytes(narrow_utf8_source_string);
349349
}
350350

351+
int isalnumExample() {
352+
char c = 'A';
353+
if (std::isalnum(c)) {
354+
std::cout << c << " is alphanumeric." << std::endl;
355+
} else {
356+
std::cout << c << " is not alphanumeric." << std::endl;
357+
}
358+
return 0;
359+
}
360+
#include <stdio.h>
361+
362+
void strstrExample() {
363+
char haystack[] = "Hello, World!"; // Now this is modifiable
364+
const char *needle = "World";
365+
366+
// Use strstr to find the first occurrence of the needle in the haystack
367+
char *result = strstr(haystack, needle);
368+
369+
if (result) {
370+
printf("Found substring: %s\n", result);
371+
} else {
372+
printf("Substring not found.\n");
373+
}
374+
}
375+
376+
#include <cstring> // for strdup and free
377+
378+
void strdupExample() {
379+
// Original string
380+
const char *original = "Hello, World!";
381+
382+
// Duplicate the string using strdup
383+
char *duplicate = strdup(original);
384+
385+
// Print both strings
386+
std::cout << "Original: " << original << std::endl;
387+
std::cout << "Duplicate: " << duplicate << std::endl;
388+
389+
// Free the memory allocated by strdup
390+
free(duplicate);
391+
}
351392
int main() {
352393

353394
// stringNumberConversion();

0 commit comments

Comments
 (0)