From 9aca31cb62f2941b9decb195fb2e72038965f921 Mon Sep 17 00:00:00 2001 From: alexey Date: Thu, 4 Dec 2025 22:31:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20=D0=BB?= =?UTF-8?q?=D0=B0=D0=B1=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- str.c | 227 +++++++++++++++++++++++++++++++++++++++++++------------ str_test | Bin 0 -> 26008 bytes wcl.c | 31 ++++++++ 3 files changed, 209 insertions(+), 49 deletions(-) create mode 100755 str_test create mode 100644 wcl.c diff --git a/str.c b/str.c index 8036bd5..cf0d058 100644 --- a/str.c +++ b/str.c @@ -1,128 +1,257 @@ #include #include #include + #include "str.h" #include "util.h" #define INIT_SZ 20 -//Внутренняя функция, -//позволяет убедиться что строка может вместить как минимум newsz символов +// ----------------------------------------------------------- +// INTERNAL: ensure capacity >= newsz (+1 for '\0') +// ----------------------------------------------------------- void _str_ensure(str *s, int newsz) { - int tmp; - newsz += 1; // добавляем единичку чтобы влез нулевой байт - if (newsz < s->capacity) - return; + int tmp; - tmp = s->capacity * 2; - if (tmp > newsz) { - newsz = tmp; - } - s->ptr = xrealloc(s->ptr, newsz); - s->capacity = newsz; + newsz += 1; // Account for null terminator + + if (newsz < s->capacity) + return; + + tmp = s->capacity * 2; + if (tmp > newsz) + newsz = tmp; + + s->ptr = xrealloc(s->ptr, newsz); + s->capacity = newsz; } +// ----------------------------------------------------------- +// Initialize empty string +// ----------------------------------------------------------- void str_init(str *s) { - assert(s); - // + assert(s); + + s->capacity = INIT_SZ; + s->len = 0; + s->ptr = xmalloc(s->capacity); + s->ptr[0] = '\0'; } +// ----------------------------------------------------------- +// Free memory +// ----------------------------------------------------------- void str_deinit(str *s) { - if (s->ptr) - free(s->ptr); - s->ptr = NULL; + if (s->ptr) + free(s->ptr); + + s->ptr = NULL; } +// ----------------------------------------------------------- +// Initialize with provided C-string +// ----------------------------------------------------------- void str_init_data(str *s, const char *initial) { - assert(s && initial); - // + assert(s && initial); + + int n = strlen(initial); + s->capacity = (n + 1 < INIT_SZ) ? INIT_SZ : n + 1; + s->len = n; + + s->ptr = xmalloc(s->capacity); + memcpy(s->ptr, initial, n + 1); // copy including '\0' } +// ----------------------------------------------------------- +// Return pointer to underlying C-string +// ----------------------------------------------------------- char * str_data(str *s) { - assert(s); - // - return NULL; + assert(s); + return s->ptr; } +// ----------------------------------------------------------- +// Replace contents with provided C-string +// ----------------------------------------------------------- void str_set(str *s, char *cstr) { - assert(s && cstr); - // + assert(s && cstr); + + int n = strlen(cstr); + _str_ensure(s, n); + + memcpy(s->ptr, cstr, n + 1); // include '\0' + s->len = n; } +// ----------------------------------------------------------- +// Create deep copy of string +// ----------------------------------------------------------- str str_copy(str *s) { - assert(s); - // + assert(s); + + str s2; + str_init(&s2); + + _str_ensure(&s2, s->len); + memcpy(s2.ptr, s->ptr, s->len + 1); + s2.len = s->len; + + return s2; } +// ----------------------------------------------------------- +// Count occurrences of character +// ----------------------------------------------------------- int str_count(str *s, char ch) { - assert(s); - // - return 0; + assert(s); + + int cnt = 0; + for (int i = 0; i < s->len; i++) + if (s->ptr[i] == ch) + cnt++; + + return cnt; } +// ----------------------------------------------------------- +// Append C-string +// ----------------------------------------------------------- void str_append(str *s, char *cstr) { - assert(s && cstr); - // + assert(s && cstr); + + int n = strlen(cstr); + _str_ensure(s, s->len + n); + + memcpy(s->ptr + s->len, cstr, n + 1); + s->len += n; } +// ----------------------------------------------------------- +// Append exactly len bytes from cstr +// ----------------------------------------------------------- void str_append_n(str *s, char *cstr, int len) { - assert(s && cstr); - // + assert(s && cstr); + + _str_ensure(s, s->len + len); + + memcpy(s->ptr + s->len, cstr, len); + s->len += len; + + s->ptr[s->len] = '\0'; // add terminator } +// ----------------------------------------------------------- +// Shrink string to new length +// ----------------------------------------------------------- void str_shrink(str *s, int len) { - assert(s && len >= 0); - // + assert(s && len >= 0); + + if (len > s->len) + len = s->len; + + s->len = len; + s->ptr[len] = '\0'; } +// ----------------------------------------------------------- +// Find substring, return index or -1 +// ----------------------------------------------------------- int str_find(str *s, char *substr) { - assert(s && substr); - char *p = strstr(s->ptr, substr); - if (p == NULL) - return -1; - return p - s->ptr; + assert(s && substr); + + char *p = strstr(s->ptr, substr); + if (!p) + return -1; + + return (int)(p - s->ptr); } +// ----------------------------------------------------------- +// Extract substring [start_idx, start_idx+length) +// ----------------------------------------------------------- str str_sub(str *s, int start_idx, int length) { - assert(s && start_idx >= 0 && length >= 0); + assert(s && start_idx >= 0 && length >= 0); - str s2; - str_init(&s2); - // - return s2; + str s2; + str_init(&s2); + + if (start_idx > s->len) + return s2; // empty + + if (start_idx + length > s->len) + length = s->len - start_idx; + + _str_ensure(&s2, length); + + memcpy(s2.ptr, s->ptr + start_idx, length); + s2.ptr[length] = '\0'; + s2.len = length; + + return s2; } -// Hint: you can create temporary string object! +// ----------------------------------------------------------- +// Replace all occurrences of substr with replacement +// ----------------------------------------------------------- int str_replace(str *s, char *substr, char *replacement) { - assert(s && substr && replacement); - // - return 0; + assert(s && substr && replacement); + + int sub_len = strlen(substr); + int rep_len = strlen(replacement); + + if (sub_len == 0) + return 0; + + str result; + str_init(&result); + + char *pos = s->ptr; + char *found; + int count = 0; + + while ((found = strstr(pos, substr)) != NULL) { + int prefix_len = (int)(found - pos); + + str_append_n(&result, pos, prefix_len); + str_append(&result, replacement); + + pos = found + sub_len; + count++; + } + + if (*pos) + str_append(&result, pos); + + str_set(s, result.ptr); + str_deinit(&result); + + return count; } diff --git a/str_test b/str_test new file mode 100755 index 0000000000000000000000000000000000000000..63870ee841f75c373f74ef132920653f8174a7e3 GIT binary patch literal 26008 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 literal 0 HcmV?d00001 diff --git a/wcl.c b/wcl.c new file mode 100644 index 0000000..57caf92 --- /dev/null +++ b/wcl.c @@ -0,0 +1,31 @@ +#include + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Использование: %s <путь_к_файлу>\n", argv[0]); + return 1; + } + + for (int i = 1; i < argc; i++) { + FILE *file = fopen(argv[i], "r"); + if (file == NULL) { + printf("Ошибка: не удалось открыть файл '%s'\n", argv[1]); + continue; + } + int line_count = 0; + int ch; + + while ((ch = fgetc(file)) != EOF) { + if (ch == '\n') { + line_count++; + } + } + + printf("Строк: %d\t%s\n", line_count, argv[i]); + + fclose(file); + } + + return 0; +} +