Работа со строками - фундаментальная задача в программировании. Рассмотрим ключевые алгоритмы и методы для эффективной обработки строк в C и C++.
В C:
size_t strlen(const char* str) {
const char* s = str;
while(*s) ++s;
return s - str;
}
В C++:
std::string s = "example";
size_t len = s.length(); // или s.size()
Безопасное копирование в C:
char* strcpy_safe(char* dest, const char* src, size_t dest_size) {
size_t i = 0;
while (i < dest_size - 1 && src[i]) {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return dest;
}
В C++:
std::string src = "source";
std::string dest = src; // автоматическое управление памятью
size_t naive_search(const std::string& text, const std::string& pattern) {
for(size_t i = 0; i <= text.size() - pattern.size(); ++i) {
bool found = true;
for(size_t j = 0; j < pattern.size(); ++j) {
if(text[i+j] != pattern[j]) {
found = false;
break;
}
}
if(found) return i;
}
return std::string::npos;
}
std::vector<int> computeLPS(const std::string& pattern) {
std::vector<int> lps(pattern.size());
int len = 0;
lps[0] = 0;
for(int i = 1; i < pattern.size(); ) {
if(pattern[i] == pattern[len]) {
lps[i++] = ++len;
} else {
if(len != 0) len = lps[len-1];
else lps[i++] = 0;
}
}
return lps;
}
size_t KMP_search(const std::string& text, const std::string& pattern) {
auto lps = computeLPS(pattern);
int i = 0, j = 0;
while(i < text.size()) {
if(text[i] == pattern[j]) {
i++; j++;
if(j == pattern.size()) return i - j;
} else {
if(j != 0) j = lps[j-1];
else i++;
}
}
return std::string::npos;
}
Лексикографическое сравнение:
int str_compare(const char* a, const char* b) {
while(*a && *b && *a == *b) { a++; b++; }
return *a - *b;
}
В C++:
std::string s1 = "apple", s2 = "banana";
if(s1 < s2) { /* ... */ } // перегруженные операторы
В C:
char* str_concat(char* dest, const char* src, size_t dest_size) {
size_t dest_len = strlen(dest);
size_t i = 0;
while(dest_len + i < dest_size - 1 && src[i]) {
dest[dest_len + i] = src[i];
i++;
}
dest[dest_len + i] = '\0';
return dest;
}
В C++:
std::string s1 = "Hello", s2 = "World";
std::string result = s1 + " " + s2;
В C (strtok):
char str[] = "one,two,three";
char* token = strtok(str, ",");
while(token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ",");
}
В C++ (stringstream):
std::string s = "one two three";
std::istringstream iss(s);
std::string token;
while(iss >> token) {
std::cout << token << std::endl;
}
void to_upper(std::string& s) {
for(auto& c : s) c = toupper(c);
}
std::string remove_whitespace(const std::string& s) {
std::string result;
std::copy_if(s.begin(), s.end(), std::back_inserter(result),
[](char c){ return !std::isspace(c); });
return result;
}
Полиномиальное хеширование:
size_t string_hash(const std::string& s, size_t p = 31, size_t m = 1e9+9) {
size_t hash = 0;
size_t p_pow = 1;
for(char c : s) {
hash = (hash + (c - 'a' + 1) * p_pow) % m;
p_pow = (p_pow * p) % m;
}
return hash;
}
#include <regex>
std::string s = "Email: test@example.com";
std::regex email_regex(R"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b)");
std::smatch matches;
if(std::regex_search(s, matches, email_regex)) {
std::cout << "Found email: " << matches[0] << std::endl;
}
Резюмируем: эффективная работа со строками требует понимания как базовых алгоритмов, так и современных методов. В C++ предпочтительно использовать std::string и алгоритмы STL, в C - аккуратно работать с ручным управлением памятью. Выбор алгоритма зависит от конкретной задачи и требований к производительности.