forked from 131/lab0.1_letscontinue
add new functions & tests
This commit is contained in:
@@ -36,4 +36,6 @@ $ ./wcl ./test/wiki_ci ./test/nullfile
|
|||||||
* realloc(3) -- функции для работы с динамической памятью
|
* realloc(3) -- функции для работы с динамической памятью
|
||||||
* memset(3) -- функция, заполняющая буфер константным значением
|
* memset(3) -- функция, заполняющая буфер константным значением
|
||||||
* memcpy(3) -- функция, копирующая данные между двумя массивами
|
* memcpy(3) -- функция, копирующая данные между двумя массивами
|
||||||
* strlen(3) -- функция, вычисляющая длинну строки
|
* memmove(3) -- функция, копирующая данные между массивами (входящий и исходящий массивы могут пересекаться)
|
||||||
|
* strlen(3) -- функция, вычисляющая длину строки
|
||||||
|
* strcpy(3) -- функция, копирующая строку в буфер
|
||||||
|
|||||||
3
build.sh
Executable file
3
build.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
gcc -Wall -g -o str_test str.c str_test.c util.c
|
||||||
79
str.c
79
str.c
@@ -6,6 +6,24 @@
|
|||||||
|
|
||||||
#define INIT_SZ 20
|
#define INIT_SZ 20
|
||||||
|
|
||||||
|
//Внутренняя функция,
|
||||||
|
//позволяет убедиться что строка может вместить как минимум newsz символов
|
||||||
|
void
|
||||||
|
_str_ensure(str *s, int newsz)
|
||||||
|
{
|
||||||
|
int tmp;
|
||||||
|
newsz += 1; // добавляем единичку чтобы влез нулевой байт
|
||||||
|
if (newsz < s->capacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tmp = s->capacity * 2;
|
||||||
|
if (tmp > newsz) {
|
||||||
|
newsz = tmp;
|
||||||
|
}
|
||||||
|
s->ptr = xrealloc(s->ptr, newsz);
|
||||||
|
s->capacity = newsz;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
str_init(str *s)
|
str_init(str *s)
|
||||||
{
|
{
|
||||||
@@ -36,6 +54,13 @@ str_data(str *s)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
str_set(str *s, char *cstr)
|
||||||
|
{
|
||||||
|
assert(s && cstr);
|
||||||
|
// <YOURCODE>
|
||||||
|
}
|
||||||
|
|
||||||
str
|
str
|
||||||
str_copy(str *s)
|
str_copy(str *s)
|
||||||
{
|
{
|
||||||
@@ -43,15 +68,61 @@ str_copy(str *s)
|
|||||||
// <YOURCODE>
|
// <YOURCODE>
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
str_append(str *s, char *p)
|
str_count(str *s, char ch)
|
||||||
{
|
{
|
||||||
|
assert(s);
|
||||||
|
// <YOURCODE>
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
str_append(str *s, char *cstr)
|
||||||
|
{
|
||||||
|
assert(s && cstr);
|
||||||
// <YOURCODE>
|
// <YOURCODE>
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
str_shrink(str *s, int sz)
|
str_append_n(str *s, char *cstr, int len)
|
||||||
{
|
{
|
||||||
assert(s && sz >= 0);
|
assert(s && cstr);
|
||||||
// <YOURCODE>
|
// <YOURCODE>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
str_shrink(str *s, int len)
|
||||||
|
{
|
||||||
|
assert(s && len >= 0);
|
||||||
|
// <YOURCODE>
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
str
|
||||||
|
str_sub(str *s, int start_idx, int length)
|
||||||
|
{
|
||||||
|
assert(s && start_idx >= 0 && length >= 0);
|
||||||
|
|
||||||
|
str s2;
|
||||||
|
str_init(&s2);
|
||||||
|
// <YOURCODE>
|
||||||
|
return s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hint: you can create temporary string object!
|
||||||
|
int
|
||||||
|
str_replace(str *s, char *substr, char *replacement)
|
||||||
|
{
|
||||||
|
assert(s && substr && replacement);
|
||||||
|
// <YOURCODE>
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
41
str.h
41
str.h
@@ -2,12 +2,11 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
// Str это структура, которая хранит в памяти строки произвольной длинны
|
// Str это структура, которая хранит в памяти строки произвольной длинны
|
||||||
// sz -- содержит текущий размер строки (0 если строка не инициализирована или нулевого размера)
|
// len -- содержит текущую длину строки (0 если строка не инициализирована или нулевого размера)
|
||||||
// Размер строки -- количество байт, занятое под символы (за исключением последнего нулевого байта)
|
|
||||||
// capacity содержит размер динамически инициализированного массива ptr
|
// capacity содержит размер динамически инициализированного массива ptr
|
||||||
|
|
||||||
struct Str {
|
struct Str {
|
||||||
int sz;
|
int len;
|
||||||
int capacity;
|
int capacity;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
};
|
};
|
||||||
@@ -25,11 +24,39 @@ void str_deinit(str *s);
|
|||||||
// Функция должна вернуть указатель на ptr
|
// Функция должна вернуть указатель на ptr
|
||||||
char *str_data(str *s);
|
char *str_data(str *s);
|
||||||
|
|
||||||
|
//Функция копирует в строку содержимое cstr.
|
||||||
|
void str_set(str *s, char *cstr);
|
||||||
|
|
||||||
//Функция создаёт и возвращает новую строку, копию s
|
//Функция создаёт и возвращает новую строку, копию s
|
||||||
str str_copy(str *s);
|
str str_copy(str *s);
|
||||||
|
|
||||||
//добавляет к строке строку suffix
|
// Функция возвращает количество символов ch в строке str
|
||||||
void str_append(str *s, char *suffix);
|
int str_count(str *s, char ch);
|
||||||
|
|
||||||
//уменьшает размер строки до sz байт
|
//добавляет к строке строку cstr
|
||||||
void str_shrink(str *s, int sz);
|
void str_append(str *s, char *cstr);
|
||||||
|
|
||||||
|
//добавляет к строке строку cstr
|
||||||
|
void str_append_n(str *s, char *cstr, int len);
|
||||||
|
|
||||||
|
//Если строка s содержит больше len байт, то уменьшает размер строки до len байт
|
||||||
|
void str_shrink(str *s, int len);
|
||||||
|
|
||||||
|
//Искать подстроку subsr в строке s. Вернуть индекс в строке или -1
|
||||||
|
int str_find(str *s, char *substr);
|
||||||
|
|
||||||
|
//Функция создаёт новую строку, которая должна содержать подстроку s, начиная с символа по индексу start_idx, и быть длины length символов (или меньше, если в строке s не хватает символов).
|
||||||
|
//Пример использования:
|
||||||
|
// str_init(&s, "hello world");
|
||||||
|
// str s2 = str_sub(&s, 6, 5);
|
||||||
|
// В s2 должна оказаться подстрока "world"
|
||||||
|
str str_sub(str *s, int start_idx, int length);
|
||||||
|
|
||||||
|
//Функция ищет в исходной строке s подстроки substr и заменяет их на replacement
|
||||||
|
//Возвращает число заменённых подстрок.
|
||||||
|
//Пример использования:
|
||||||
|
// str_init(&s, "foo bar baz foo");
|
||||||
|
// str_replace(&s, "foo", "test");
|
||||||
|
//В результате в строке &s должна получиться строка "test bar baz test",
|
||||||
|
//функция должна вернуть 2
|
||||||
|
int str_replace(str *s, char *substr, char *replacement);
|
||||||
|
|||||||
86
str_test.c
86
str_test.c
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
|
|
||||||
#define my_assert(cond, reason, ...) do { \
|
#define my_assert(cond, reason, ...) do { \
|
||||||
if (!(cond)) { \
|
if (!(cond)) { \
|
||||||
printf("[-] ERROR " reason "\n", ##__VA_ARGS__); \
|
printf("[-] ERROR " reason "\n", ##__VA_ARGS__); \
|
||||||
printf("\t%s:%d " #cond "\n", __FILE_NAME__, __LINE__); \
|
printf("\t%s:%d " #cond "\n", __FILE_NAME__, __LINE__); \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
@@ -22,35 +22,89 @@ test_it()
|
|||||||
//TEST str_init
|
//TEST str_init
|
||||||
str_init(&s);
|
str_init(&s);
|
||||||
|
|
||||||
my_assert(s.sz == 0, "initial size should be 0");
|
my_assert(s.len == 0,
|
||||||
my_assert(s.ptr == str_data(&s), "str_data должна вернуть то же самое что хранится в ptr поле");
|
"initial size should be 0");
|
||||||
|
my_assert(s.ptr == str_data(&s),
|
||||||
|
"str_data, должна вернуть то же самое что хранится в ptr поле");
|
||||||
str_deinit(&s);
|
str_deinit(&s);
|
||||||
|
|
||||||
// TEST str_init_data
|
// TEST str_init_data
|
||||||
str_init_data(&s, "hello");
|
str_init_data(&s, "hello");
|
||||||
my_assert(s.sz == strlen("hello"), "str_init_data, неправильный размер строки");
|
my_assert(s.len == strlen("hello"),
|
||||||
my_assert(strcmp(str_data(&s), "hello") == 0, "не правильная строка '%s' != 'hello'", str_data(&s));
|
"str_init_data, неправильный размер строки");
|
||||||
|
my_assert(strcmp(str_data(&s), "hello") == 0,
|
||||||
|
"str_init_data, не правильная строка '%s' != 'hello'", str_data(&s));
|
||||||
|
|
||||||
|
// TEST str_set
|
||||||
|
str_set(&s, "");
|
||||||
|
my_assert(s.len == 0,
|
||||||
|
"str_set, нулевая строка, неверный размер");
|
||||||
|
my_assert(strcmp(str_data(&s), "") == 0,
|
||||||
|
"str_set, нулевая строка, не верное содержимое %s", str_data(&s));
|
||||||
|
|
||||||
|
char *lazyfox = "The quick brown fox jumps over the lazy dog";
|
||||||
|
str_set(&s, lazyfox);
|
||||||
|
my_assert(s.len == strlen(lazyfox),
|
||||||
|
"str_set, lazyfox s.len error");
|
||||||
|
my_assert(strcmp(str_data(&s), lazyfox) == 0,
|
||||||
|
"str_set, нулевая строка, не верное содержимое %s", str_data(&s));
|
||||||
|
|
||||||
// TEST str_copy
|
// TEST str_copy
|
||||||
str s2;
|
str s2;
|
||||||
s2 = str_copy(&s);
|
s2 = str_copy(&s);
|
||||||
my_assert(s2.sz == s.sz,
|
my_assert(s2.len == s.len,
|
||||||
"str_copy. размеры строк разные!");
|
"str_copy, размеры строк разные!");
|
||||||
my_assert(strcmp(str_data(&s), str_data(&s2)) == 0,
|
my_assert(strcmp(str_data(&s), str_data(&s2)) == 0,
|
||||||
"str_copy получились разные строки '%s' != '%s'", str_data(&s), str_data(&s2));
|
"str_copy, получились разные строки '%s' != '%s'", str_data(&s), str_data(&s2));
|
||||||
my_assert(s.ptr != s2.ptr, "str_copy s.ptr и s2.ptr не должны указывать на одну строку. Указатели строк должны быть разными");
|
my_assert(s.ptr != s2.ptr,
|
||||||
|
"str_copy, s.ptr и s2.ptr не должны указывать на одну строку. Указатели строк должны быть разными");
|
||||||
|
str_deinit(&s2);
|
||||||
|
|
||||||
// TEST str_append
|
// TEST str_append
|
||||||
|
str_set(&s, "hello");
|
||||||
str_append(&s, " world");
|
str_append(&s, " world");
|
||||||
my_assert(strcmp(s.ptr, "hello world") == 0, "str_append, неправильная строка %s", s.ptr);
|
my_assert(strcmp(s.ptr, "hello world") == 0,
|
||||||
|
"str_append, неправильная строка %s", s.ptr);
|
||||||
str_append(&s, "loooooooooooooooooooooooooooooooooooooooooooooooong str");
|
str_append(&s, "loooooooooooooooooooooooooooooooooooooooooooooooong str");
|
||||||
my_assert(strcmp(s.ptr, "hello worldloooooooooooooooooooooooooooooooooooooooooooooooong str") == 0, "str_append вторая проверка, неправильная строка");
|
my_assert(strcmp(s.ptr, "hello worldloooooooooooooooooooooooooooooooooooooooooooooooong str") == 0,
|
||||||
|
"str_append, вторая проверка, неправильная строка");
|
||||||
|
|
||||||
|
// TEST str_append_n
|
||||||
|
str_set(&s, "hello ");
|
||||||
|
str_append_n(&s, lazyfox, 9);
|
||||||
|
my_assert(strcmp(str_data(&s), "hello The quick") == 0,
|
||||||
|
"str_append_n, неверная строка %s", str_data(&s));
|
||||||
|
|
||||||
// TEST str_shrink
|
// TEST str_shrink
|
||||||
str_shrink(&s, 5);
|
str_shrink(&s, 5);
|
||||||
my_assert(s.sz == 5, "str_shrink неправильный размер строки");
|
my_assert(s.len == 5,
|
||||||
my_assert(strcmp(str_data(&s), "hello") == 0, "str_shrink не правильная строка");
|
"str_shrink, неправильный размер строки");
|
||||||
|
my_assert(strcmp(str_data(&s), "hello") == 0,
|
||||||
|
"str_shrink, не правильная строка");
|
||||||
|
str_deinit(&s);
|
||||||
|
|
||||||
|
// TEST str_find
|
||||||
|
str_init_data(&s, "hello");
|
||||||
|
my_assert(str_find(&s, "hello") == 0,
|
||||||
|
"str_find, не могу найти `hello` в строке `hello`");
|
||||||
|
my_assert(str_find(&s, "llo") == 2,
|
||||||
|
"str_find, не могу найти `llo` в строке `hello`");
|
||||||
|
my_assert(str_find(&s, "world") == -1,
|
||||||
|
"str_find, могу найти `world` в строке `hello`");
|
||||||
|
|
||||||
|
//TEST str_sub
|
||||||
|
str_set(&s, lazyfox);
|
||||||
|
s2 = str_sub(&s, 4, 5);
|
||||||
|
my_assert(strcmp(str_data(&s2), "quick") == 0,
|
||||||
|
"str_sub, не правильная строка %s", str_data(&s2));
|
||||||
|
str_deinit(&s2);
|
||||||
|
|
||||||
|
//TEST str_replace
|
||||||
|
str_set(&s, "foo bar baz foo");
|
||||||
|
str_replace(&s, "foo", "test");
|
||||||
|
my_assert(strcmp(s.ptr, "test bar baz test") == 0,
|
||||||
|
"str_replace, не верное значение %s", s.ptr);
|
||||||
|
str_deinit(&s);
|
||||||
|
|
||||||
printf("[+] ALL_TESTS_PASSED\n");
|
printf("[+] ALL_TESTS_PASSED\n");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user