První bonusový úkol
Odevzdání
Úkol odevzdejte mailem (adresu najdete na webu katedry), s předmětem
ZP2 - Bonusový úkol 1, jako přílohu soubor se zdrojovým kódem (a nic
dalšího). Odevzdávejte nejpozději 2. 3. ve 23:59.
Body
Za úkol lze získat 4 body.
Zadání
Uvažujme následující strukturu pro řetězec.
Položka data není zakončená 0, místo toho si pamatuje svoji délku v položce len.
typedef struct
{
char* data;
size_t len;
} String;
Prázdný řetězec má obě položky nastaveny na 0.
Řětězce budeme vytvářet pomocí funkce (není nutno se zabývat jejím tělem, funkci stačí skopírovat do zdrojáku).
String clone_from_cstring(char *cstring)
{
String ret = {0};
ret.len = strlen(cstring);
if (ret.len == 0)
{
ret.data = 0;
}
else
{
ret.data = malloc(ret.len);
assert(ret.data);
memcpy(ret.data, cstring, ret.len);
}
return ret;
}
Naprogramujte následující funkce
void print_string(String str);
Funkce vytiskne řetězec str.
String get_prefix(String str, char delimiter, String* remainder);
Funkce vrátí prefix řetězce str až do prvního výskytu znaku delimiter. Ten
ovšem do výsledku nepatří. Do argumentu remainder zapíše zbytek řetězce,
s tím že delimiter na začátku vynechá.
//
// Příklad použítí funkce get_prefix
//
String a = clone_from_cstring("xx-yy");
String b = clone_from_cstring("xx--zz");
String c = clone_from_cstring("-xxxx");
String d = clone_from_cstring("xxx");
String e = clone_from_cstring("");
String rem;
String res;
//
// následující vytiskne "xx" a "yy"
//
res = get_prefix(a, '-', &rem);
print_string(res);
print_string(rem);
//
// následující vytiskne "xx" a "-zz"
//
res = get_prefix(b, '-', &rem);
print_string(res);
print_string(rem);
//
// následující vytiskne "" a "xxxx"
//
res = get_prefix(c, '-', &rem);
print_string(res);
print_string(rem);
//
// následující vytiskne "xxx" a ""
//
res = get_prefix(d, '-', &rem);
print_string(res);
print_string(rem);
//
// následující vytiskne "" a ""
//
res = get_prefix(e, '-', &rem);
print_string(res);
print_string(rem);
int string_to_long(String s, long* result);
Funkce převede číslo zapsané jako řetězec na long.
Číslo může být záporné.
Pokud je s prázdný, je výsledkem převodu 0.
Výsledné číslo je zapsáno do argumentu result. Funkce vrací 1, pokud se
povedlo číslo z řetězce převést, jinak vrací 0.
int compute_the_thing(String s, long* result);
s je text, který obsahuje na každém řádku mezerami oddělená celá
čísla. Funkce vrací číslo, které dostane následovně: čísla v každém
řádku sečte; výsledek dostane tak, že sečte součty sudých řádků a od
toho odečte součty lichých řádků. Výsledek zapíše do
result. Pokud se část řetězce nepovede převést na číslo, vrátí
funkce 0, jinak vrací 1. Například, pokud je s
2 2
2 2 2
-2 3
jsou součty řádků postupně 4, 6, 1 a výsledek je -4 + 6 -1 = 1
a funkce vrátí 1.
int res = 0;
int ok = 0;
//
// Následující vytiskne 1, 1
//
String s = clone_from_cstring("2 2\n2 2 2\n-2 3");
ok = compute_the_thing(s, &res);
printf("%i %i\n", res, ok);
//
// Následující vytiskne -3, 0
//
res = -3;
String t = clone_from_cstring("2 2\nx y\n");
ok = compute_the_thing(t, &res);
printf("%i %i\n", res, ok);
Omezení
Je zakázáno používat funkce pro manipulaci s řetězci, které jsou
ve standardní knihovně. Tj. úkol nelze řešit způsobem: nejdříve převedu String
na řetězec v C, potom zavolám knihovní funkci, a nakonec výsledek převedu zpátky na
String.