185 lines
5.1 KiB
C
185 lines
5.1 KiB
C
#include "types.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifndef TEST_BUILD
|
|
#define SIZE 15
|
|
int main(int argc, char *argv[]) { return 0; }
|
|
|
|
#endif
|
|
|
|
/**
|
|
* Zjistí délku řetězce.
|
|
* Všechny řetězce v C jsou ukončeny nulovým bytem.
|
|
*
|
|
* @param str vstupní řetězec
|
|
*
|
|
* @returns délku řetězce (počet znaků řetězce)
|
|
*/
|
|
size_t str_len(char *str) {
|
|
if (str == NULL) {
|
|
return 0;
|
|
}
|
|
int length = 0;
|
|
while (true) {
|
|
if (str[length] == '\0') {
|
|
break;
|
|
}
|
|
length++;
|
|
}
|
|
return length;
|
|
}
|
|
|
|
/**
|
|
* Kopíruje data po bytech v paměti o dane velikosti.
|
|
*
|
|
* Zdroj dat ke kopírování není změněn.
|
|
* Předpokládejte, že v cíli je k dispozici dostatek volné paměti.
|
|
*
|
|
* hint: (char *) k pretypovani z void*
|
|
*
|
|
* @param dest ukazatel na paměť do které se kopíruje
|
|
* @param src ukazatel na paměť ze které se kopíruje
|
|
* @param n velikost kopírované paměti v bytech
|
|
*/
|
|
void mem_cpy(void *dest, void *src, size_t n) {
|
|
if (dest == NULL || src == NULL) {
|
|
return;
|
|
}
|
|
|
|
char *d = (char *)dest;
|
|
char *s = (char *)src;
|
|
|
|
// Procházíme paměť a kopírujeme byte po bytu
|
|
for (size_t i = 0; i < n; i++) {
|
|
d[i] = s[i];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Najde první výskyt podřetězce v řetězci.
|
|
*
|
|
* Ani jeden z řetězců není změněn.
|
|
*
|
|
* hint: str_len
|
|
*
|
|
* @param str řetězec ve kterém se vyhledává
|
|
* @param substr vyhledávaný podřetězec
|
|
*
|
|
* @returns index na kterém v řetězci začíná podřetězec,
|
|
* nebo -1 pokud se podřetězec v řetězci nenachází.
|
|
*/
|
|
int find_substr(char *str, char *substr) {
|
|
if (str == NULL || substr == NULL || str_len(substr) > str_len(str)) {
|
|
return -1;
|
|
}
|
|
|
|
// Projdeme celý řetězec (zkrácený o délku podřetězce, protože tam už nikdy
|
|
// nepůjde najít)
|
|
for (size_t i = 0; i <= str_len(str) - str_len(substr); i++) {
|
|
size_t j;
|
|
// V druhé smyčce zkoušíme, jestli od `i` po `str_len(substr)` dojdeme bez
|
|
// přerušení
|
|
for (j = 0; j < str_len(substr); j++) {
|
|
if (str[i + j] != substr[j]) {
|
|
break;
|
|
}
|
|
}
|
|
// Pokud jsme prošli bez přerušení, našli jsme shodu
|
|
if (j == str_len(substr)) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
// Podřetězec nenalezen
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Nahradí podřetězec substr za nahrazující podřetězec v řetězci,
|
|
* kde oba podřetězce jsou o stejné délce.
|
|
*
|
|
* Podřetězce nejsou změněny.
|
|
* Pokud nejsou podřetězce stejně dlouhé, funkce substituci neprovede,
|
|
* stejně tak pokud podřetězec není v řetězci nalezen.
|
|
*
|
|
* hint: mem_cpy, find_substr, str_len
|
|
*
|
|
* @param str řetězec ve kterém se vyhledává
|
|
* @param substr vyhledávaný nahrazovaný podřetězec
|
|
* @param new_substr nahrazující podřetězec
|
|
*/
|
|
void replace_same_length(char *str, char *substr, char *new_substr) {
|
|
if (str == NULL || substr == NULL || new_substr == NULL ||
|
|
str_len(substr) != str_len(new_substr)) {
|
|
return;
|
|
}
|
|
int replaceIndex = find_substr(str, substr);
|
|
|
|
if (replaceIndex == -1) {
|
|
return;
|
|
}
|
|
|
|
// Přepíšeme v paměti na nový podřetězec
|
|
mem_cpy(str + replaceIndex, new_substr, str_len(new_substr));
|
|
}
|
|
|
|
/**
|
|
* Nahradí nahrazovaný podřetězec za nahrazující podřetězec v řetězci,
|
|
* kde každý podřetězec může mít jinou velikost.
|
|
* Původní řetězec je uvolněn.
|
|
*
|
|
* Podřetězce nejsou změněny.
|
|
* V případě chyby není původní řetězec uvolněn a zůstává nezměněn.
|
|
*
|
|
* hint: mem_cpy, find_substr, str_len, malloc, free
|
|
*
|
|
* @param str dynamicky řetězec ve kterém se vyhledává
|
|
* @param substr vyhledávaný nahrazovaný podřetězec
|
|
* @param new_substr nahrazující podřetězec
|
|
*
|
|
* @returns nový řetězec vytvořený v nově alokované paměti v případě úspěchu,
|
|
* pointer na původní řetězec v případě že podřetězec se v řetězci nenachází,
|
|
* NULL jinak.
|
|
*/
|
|
char *replace(char *str, char *substr, char *new_substr) {
|
|
if (str == NULL || substr == NULL || new_substr == NULL) {
|
|
return NULL;
|
|
}
|
|
int replaceIndex = find_substr(str, substr);
|
|
|
|
if (replaceIndex == -1) {
|
|
return str;
|
|
}
|
|
|
|
size_t newSize = str_len(str) - str_len(substr) + str_len(new_substr);
|
|
|
|
char *newStr = malloc(sizeof(char) * (newSize + 1));
|
|
if (newStr == NULL) {
|
|
// Chyba alokace
|
|
return NULL;
|
|
}
|
|
|
|
// Zkopírujeme část před nálezem
|
|
mem_cpy(newStr, str, replaceIndex);
|
|
|
|
// Zkopírujeme nový podřetězec
|
|
// Musíme se posunout na místo v paměti, kde je první znak nálezu
|
|
mem_cpy(newStr + replaceIndex, new_substr, str_len(new_substr));
|
|
|
|
// Zkopírujeme část za nálezem
|
|
// Posuneme se na místo za první znak nálezu + délka nového podřetězce
|
|
// Překopírujeme vše, co je v paměti na místě paměti původního řetězce + index
|
|
// prvního nálezu + délka hledaného podřetězce
|
|
mem_cpy(newStr + replaceIndex + str_len(new_substr),
|
|
str + replaceIndex + str_len(substr),
|
|
str_len(str) - replaceIndex - str_len(substr));
|
|
|
|
// Na konec dáme ukončovací znak
|
|
newStr[newSize] = '\0';
|
|
|
|
// Uvolníme původní řetězec a vrátíme novou adresu
|
|
free(str);
|
|
|
|
return newStr;
|
|
}
|