IZP/Cviko8_2/main.c
2024-11-21 17:14:54 +01:00

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;
}