Implementacji listy łączonej i testów

Implementacji listy łączonej i testów

Wątek przeniesiony 2023-02-21 13:10 z C/C++ przez Riddle.

lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
1

Hej wam, napisałem wreszcie działającą listę łączoną, program działa, wyniki są sprawdzone w mainie. Mam w planach ogarnąć cmocka do unit testów. Co sądzicie o tym, żeby sprawdzać w funkcjach pop_front i pop_back czy lista jest pusta? Jaką wartość powinna w tym przypadku otrzymać zmienna data?

Kodzik:

main.c

Kopiuj
#include <stdio.h>
#include "linked_list.h"

int main(void) {
    printf("initializing list");
    struct linked_list *list = ll_new();
    ll_push_back(&list, 2);
    ll_push_back(&list, 3);
    printf("data after ll_push_bash:\n");
    ll_print(list);

    int data;
    ll_pop_back(&list, &data);
    ll_pop_back(&list, &data);
    printf("data after 2x ll_pop_back: data=%d\n", data);
    ll_print(list);

    ll_push_front(&list, 3);
    ll_push_front(&list, 4);
    printf("data after ll_push_front:\n");
    ll_print(list);

    ll_pop_front(&list, &data);
    ll_pop_front(&list, &data);
    ll_print(list);
    printf("data after 2x ll_pop_front: %d\n", data);

    printf("inserting data into list:\n");
    ll_push_front(&list, 1);
    ll_push_front(&list, 2);
    ll_push_back(&list, 3);
    ll_print(list);
    if (ll_contains(list, 3) > -1) {
        printf("list contains element 3\n");
    }
    int idx = ll_find(list, 1);
    if (idx > -1) {
        printf("list contains element 1 at position %d\n", idx);
    }
    ll_destroy(list);
    return 0;
}

linked_list.h

Kopiuj
#ifndef LINKED_LIST_H
#define LINKED_LIST_H

#include <stdlib.h>

struct ll_node {
    int data;
    struct ll_node *prev;
    struct ll_node *next;
};

struct linked_list {
    struct ll_node *head;
    struct ll_node *tail;
    size_t size;
};

struct linked_list *ll_new(void);
int ll_destroy(struct linked_list *list);

int ll_push_back(struct linked_list **list, int data);
int ll_pop_back(struct linked_list **list, int *data);
int ll_push_front(struct linked_list **list, int data);
int ll_pop_front(struct linked_list **list, int *data);

int ll_find(struct linked_list *list, int data);
int ll_contains(struct linked_list *list, int data);

int ll_print(struct linked_list *list);

#endif //LINKED_LIST_H

linked_list.c

Kopiuj
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"

struct linked_list *ll_new(void) {
    struct linked_list *list = malloc(sizeof(struct linked_list));
    if (list == NULL) {
        return NULL;
    }
    list->head = NULL;
    list->tail = NULL;
    list->size = 0;
    return list;
}

int ll_destroy(struct linked_list *list) {
    if (list == NULL) {
        return -1;
    }
    if (list->head != NULL) {
        struct ll_node *node = list->head;
        while (node->next != NULL) {
            node = node->next;
            free(node->prev);
        }
        free(node);
    }
    free(list);
    return 0;
}

int ll_push_back(struct linked_list **list, int data) {
    if (list == NULL || *list == NULL) {
        return -1;
    }
    struct ll_node *node = malloc(sizeof(struct ll_node));
    if (node == NULL) {
        return -1;
    }
    node->prev = (*list)->tail;
    node->next = NULL;
    node->data = data;
    if ((*list)->size == 0) {
        (*list)->head = node;
        (*list)->tail = node;
    } else {
        (*list)->tail->next = node;
        (*list)->tail = (*list)->tail->next;
    }
    ++((*list)->size);
    return 0;
}

int ll_pop_back(struct linked_list **list, int *data) {
    if (list == NULL || *list == NULL) {
        return -1;
    }
    if (data != NULL) {
        *data = (*list)->tail->data;
    }
    if ((*list)->size > 1) {
        struct ll_node *prev = (*list)->tail->prev;
        free((*list)->tail);
        (*list)->tail = prev;
        (*list)->tail->next = NULL;
    } else {
        free((*list)->tail);
        (*list)->tail = NULL;
        (*list)->head = NULL;
    }
    --((*list)->size);
    return 0;
}

int ll_push_front(struct linked_list **list, int data) {
    if (list == NULL || *list == NULL) {
        return -1;
    }
    struct ll_node *node = malloc(sizeof(struct ll_node));
    node->data = data;
    node->prev = NULL;
    if ((*list)->size == 0) {
        node->next = NULL;
        (*list)->tail = node;
    } else {
        node->next = (*list)->head;
    }
    (*list)->head = node;
    ++((*list)->size);
    return 0;
}

int ll_pop_front(struct linked_list **list, int *data) {
    if (list == NULL || *list == NULL) {
        return -1;
    }
    if (data != NULL) {
        *data = (*list)->head->data;
    }
    if ((*list)->size > 1) {
        struct ll_node *next = (*list)->head->next;
        (*list)->head = next;
        free((*list)->head->prev);
        (*list)->head->prev = NULL;
    } else {
        free((*list)->head);
        (*list)->head = NULL;
        (*list)->tail = NULL;
    }
    --((*list)->size);
    return 0;
}

int ll_find(struct linked_list *list, int data) {
    int offset = 0;
    struct ll_node *node = list->head;
    while (node->next != NULL) {
        if (node->data == data) {
            return offset;
        }
        ++offset;
        node = node->next;
    }
    return -1;
}

int ll_contains(struct linked_list *list, int data) {
    return ll_find(list, data) >= 0;
}

int ll_print(struct linked_list *list) {
    if (list == NULL) {
        return -1;
    }
    if (list->head == NULL) {
        printf("list is empty\n");
        return 0;
    }
    int n = 0;
    struct ll_node *node = list->head;
    while (node != NULL) {
        printf("linked list node %d: %d\n", n, node->data);
        node = node->next;
        ++n;
    }
    return 0;
}
edytowany 3x, ostatnio: Riddle
RE
jest dział ocenu i recenzje. Może wrzuć to na jakiś github i tam podeślij link?
lester29
To proszę o przeniesienie moda do tego działu
kq
Zostawiłem tutaj bo imo za mały kod na oceny i recenzje, ale jeśli jest takie życzenie mogę przenieść
several
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 6 godzin
1

Jeżeli Twój węzeł zawiera głowę i ogon a więc nie modyfikujesz wskaźnika przekazanego do funkcji tylko elementy otrzymane w skutek dereferencji to nie potrzebujesz używać "referencji" do wskaźnika, tak więc wygląda na to, że wszędzie gdzie używasz struct linked_list **list jako argumentu powinno wystarczyć struct linked_list *list. Za to w ll_destroy(struct linked_list *list) powinieneś przekazać "referencję" do wskaźnika.

Zeruj wskaźniki gdy zwolniasz "pokazywaną" przez nie pamięć. Co się stanie jeśli zawołasz Twoje obecne ll_destroy dwa razy pod rząd na tej samej liście?.
Zmniejsz i zeruj rozmiar gdy redukujesz bądź usuwasz listę.

Twój size to tak na prawdę count.


edytowany 1x, ostatnio: several
lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0

Teraz lepiej?

Kopiuj
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"

struct linked_list *ll_new(void) {
    struct linked_list *list = malloc(sizeof(struct linked_list));
    if (list == NULL) {
        return NULL;
    }
    list->head = NULL;
    list->tail = NULL;
    list->size = 0;
    return list;
}

int ll_destroy(struct linked_list **list) {
    if (list == NULL || *list == NULL) {
        return -1;
    }
    if ((*list)->head != NULL) {
        struct ll_node *node = (*list)->head;
        while (node->next != NULL) {
            node = node->next;
            free(node->prev);
            node->prev = NULL;
        }
        free(node);
    }
    free(*list);
    return 0;
}

int ll_push_back(struct linked_list *list, int data) {
    if (list == NULL) {
        return -1;
    }
    struct ll_node *node = malloc(sizeof(struct ll_node));
    if (node == NULL) {
        return -1;
    }
    node->prev = list->tail;
    node->next = NULL;
    node->data = data;
    if (list->size == 0) {
        list->head = node;
        list->tail = node;
    } else {
        list->tail->next = node;
        list->tail = list->tail->next;
    }
    ++(list->size);
    return 0;
}

int ll_pop_back(struct linked_list *list, int *data) {
    if (list == NULL) {
        return -1;
    }
    if (data != NULL) {
        *data = list->tail->data;
    }
    if (list->size > 1) {
        struct ll_node *prev = list->tail->prev;
        free(list->tail);
        list->tail = prev;
        list->tail->next = NULL;
    } else {
        free(list->tail);
        list->tail = NULL;
        list->head = NULL;
    }
    --(list->size);
    return 0;
}

int ll_push_front(struct linked_list *list, int data) {
    if (list == NULL) {
        return -1;
    }
    struct ll_node *node = malloc(sizeof(struct ll_node));
    node->data = data;
    node->prev = NULL;
    if (list->size == 0) {
        node->next = NULL;
        list->tail = node;
    } else {
        node->next = list->head;
    }
    list->head = node;
    ++(list->size);
    return 0;
}

int ll_pop_front(struct linked_list *list, int *data) {
    if (list == NULL) {
        return -1;
    }
    if (data != NULL) {
        *data = list->head->data;
    }
    if (list->size > 1) {
        struct ll_node *next = list->head->next;
        list->head = next;
        free(list->head->prev);
        list->head->prev = NULL;
    } else {
        free(list->head);
        list->head = NULL;
        list->tail = NULL;
    }
    --(list->size);
    return 0;
}

int ll_find(struct linked_list *list, int data) {
    int offset = 0;
    struct ll_node *node = list->head;
    while (node->next != NULL) {
        if (node->data == data) {
            return offset;
        }
        ++offset;
        node = node->next;
    }
    return -1;
}

int ll_contains(struct linked_list *list, int data) {
    return ll_find(list, data) >= 0;
}

int ll_print(struct linked_list *list) {
    if (list == NULL) {
        return -1;
    }
    if (list->head == NULL) {
        printf("list is empty\n");
        return 0;
    }
    int n = 0;
    struct ll_node *node = list->head;
    while (node != NULL) {
        printf("linked list node %d: %d\n", n, node->data);
        node = node->next;
        ++n;
    }
    return 0;
}
kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
0

Wg mnie brakuje insert_after/insert_before. To kluczowe api dla listy, inaczej masz deque.


lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0

Jakie argumenty miałyby mieć insert_after/insert_before? Nie bardzo rozumiem co miałyby przyjmować, ll_node czy pierwszego znalezionego inta przed/po którym miałyby wstawiać wartość?

Dodałem takie coś:

Kopiuj
int ll_is_index_valid(struct linked_list *list, int index) {
    return index >= 0 && index < list->count ? 0 : -1;
}

int ll_get(struct linked_list *list, int index, int *data) {
    if (list == NULL || ll_is_index_valid(list, index) < 0) {
        return -1;
    }
    int result;
    if (index <= list->count / 2 - 1) {
        struct ll_node *node = list->head;
        for (int i = 0; i <= index && node != NULL; ++i) {
            result = node->data;
            node = node->next;
        }
    } else {
        struct ll_node *node = list->tail;
        for (int i = 0; i < list->count - index && node != NULL; ++i) {
            result = node->data;
            node = node->prev;
        }
    }
    *data = result;
    return 0;
}

int ll_set(struct linked_list *list, int index, int data) {
    if (list == NULL || ll_is_index_valid(list, index) < 0) {
        return -1;
    }
    if (index <= list->count / 2 - 1) {
        struct ll_node *node = list->head;
        for (int i = 0; i <= index && node->next != NULL; ++i) {
            node = node->next;
        }
        node->prev->data = data;
    } else {
        struct ll_node *node = list->tail;
        for (int i = 0; i < list->count - index - 1 && node->prev != NULL; ++i) {
            node = node->prev;
        }
        node->data = data;
    }
    return 0;
}
edytowany 1x, ostatnio: lester29
kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
0

Linked listy się nie indeksuje, api opartego o indeksy w ogóle nie powinno w niej być - jest kosztowne i jest zaprzeczeniem idei używania listy.

Insert before/after powinny przyjmować wskaźnik na node przed/za którym ma zostać dodany nowy element oraz wartość tego elementu. Nic więcej.

Możesz też dodać funkcję swap, która zamieni dwa elementy w liście miejscami, tutaj musisz uważać na przypadki krańcowe (lub zamienić wartości, ale to pierwsze w ramach ćwiczen warto zrobić)


lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0
kq napisał(a):

Insert before/after powinny przyjmować wskaźnik na node przed/za którym ma zostać dodany nowy element oraz wartość tego elementu. Nic więcej.

Takie coś masz na myśli?

Kopiuj
int ll_insert_before(struct ll_node *node, int data);
int ll_insert_after(struct ll_node *node, int data);
kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
0

Tak, dokładnie, chociaż nie wiem co ma oznaczać ten zwracany int


edytowany 1x, ostatnio: kq
lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0

Zwracany int ma sygnalizować czy operacja się powiodła

JB
  • Rejestracja:około 2 lata
  • Ostatnio:3 dni
  • Lokalizacja:Holandia
  • Postów:843
0

Tak.... może to sygnalizować ewentualny błąd , nie lepiej bool? Właśnie się zastanawiam ile rzeczy można zwrócić w 4 bajtach. Ale jestem absolutnie w stanie zaakceptować Twój wybór.


kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
1

Podejście mocno z 1975. Zwracałbym bool albo odpowiedniego enuma. Ale int też będzie ok, tylko tutaj z reguły jest odwrotna metodyka i zwracasz kod błędu (0 jeśli operacja się powiodła).


Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:13 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10035
0

Nie dodawaj mocków do tych testów - nie są Ci do niczego potrzebne, a tylko zaciemnisz test.

lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0
Riddle napisał(a):

Nie dodawaj mocków do tych testów - nie są Ci do niczego potrzebne, a tylko zaciemnisz test.

Czyli w ogóle nie robić testów jednostkowych? Jak polecasz przetestować kod?

kq napisał(a):

Podejście mocno z 1975. Zwracałbym bool albo odpowiedniego enuma. Ale int też będzie ok, tylko tutaj z reguły jest odwrotna metodyka i zwracasz kod błędu (0 jeśli operacja się powiodła).

Zwracam inta bo funkcje ze standardowej biblioteki zwracają inty. Czy używanie boola będzie ok jeśli w swoim kodzie będę się trzymał booli? Co z funkcjami ze standardowej biblioteki?

edytowany 2x, ostatnio: lester29
JB
  • Rejestracja:około 2 lata
  • Ostatnio:3 dni
  • Lokalizacja:Holandia
  • Postów:843
0

@lester29: standardowe biblioteki... niedawno był ktoś tutaj kto chciał pisać własny język, trochę spore wyzwanie, ale zapytam, widzisz różnicę między narzędziem które sam zrobisz a które dostajesz w markecie? Nie pytasz co z funkcjami których sam nie napiszesz?


lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0
johnny_Be_good napisał(a):

@lester29: standardowe biblioteki... niedawno był ktoś tutaj kto chciał pisać własny język, trochę spore wyzwanie, ale zapytam, widzisz różnicę między narzędziem które sam zrobisz a które dostajesz w markecie? Nie pytasz co z funkcjami których sam nie napiszesz?

Co masz na myśli? Lepiej samodzielnie ogarnąć narzędzia do testów niż korzystać z gotowych rozwiązań?

edytowany 1x, ostatnio: lester29
Zobacz pozostałe 3 komentarze
lester29
No moje potrzeby to unit testy do każdej z funkcjonalności biblioteki. Fajnie byłoby gdyby można było określić takie rzeczy jak setup czy tear down.
JB
"Fajnie byłoby" a nie "Fajnie byłoby umieć" ?
JB
A co Ty tam tak testujesz? masz realną kontrolę to ma się dziać to co ma się dziać.
lester29
No chcę sprawdzić czy dane funkcje robią to co trzeba zgodnie z założeniami
JB
A jak tak to będziesz pilnował czy się nie zmieniły rozumiem. I tu się rozumiemy. To jest pełna kontrola.
kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
0

Biblioteka standardowa C ma już ok 50 lat. W tym czasie wiele się zmieniło, zarówno w języku jak i w ogólnym podejściu do pisania programów i tworzenia API. Wg mnie bool lub enum będzie lepszym rozwiązaniem, chociaż int nie jest tragicznym, ponieważ jest zgodny istniejącym już gdzieś kanonem.


lester29
Wolę bool bo bardziej czytelny
Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:13 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10035
0
lester29 napisał(a):
Riddle napisał(a):

Nie dodawaj mocków do tych testów - nie są Ci do niczego potrzebne, a tylko zaciemnisz test.

Czyli w ogóle nie robić testów jednostkowych? Jak polecasz przetestować kod?

Nie kieruj się takimi określeniami jak jednostkowy/integracyjny. Te określenia już dawno straciły swoje ścisłe znaczenie.

Napisz testy które po prostu korzystają z listy którą napisałeś.

lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0
Riddle napisał(a):

Napisz testy które po prostu korzystają z listy którą napisałeś.

Mam użyć zewnętrznej libki jak CMocka czy zrobić własną libkę od podstaw?

Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:13 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10035
1
lester29 napisał(a):
Riddle napisał(a):

Napisz testy które po prostu korzystają z listy którą napisałeś.

Mam użyć zewnętrznej libki jak CMocka czy zrobić własną libkę od podstaw?

Ale po co chcesz używać czegoś takiego? Nie potrzebujesz mocków do przetestowania swojej listy. Wystarczy Ci runner testów, np CppUnitTestFramework.

Jeśli dodasz mocki z użyciem CMock to po pierwsze niepotrzebnie skomplikujesz testy, a po drugie osłabisz ich zdolność do wykrywania bugów i odporność na refaktor kodu.

lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0
Riddle napisał(a):
lester29 napisał(a):
Riddle napisał(a):

Napisz testy które po prostu korzystają z listy którą napisałeś.

Mam użyć zewnętrznej libki jak CMocka czy zrobić własną libkę od podstaw?

Ale po co chcesz używać czegoś takiego? Nie potrzebujesz mocków do przetestowania swojej listy. Wystarczy Ci runner testów, np CppUnitTestFramework.

Jeśli dodasz mocki z użyciem CMock to po pierwsze niepotrzebnie skomplikujesz testy, a po drugie osłabisz ich zdolność do wykrywania bugów i odporność na refaktor kodu.

To jakie narzędzia polecisz do testów? Używam linuxa, nie windowsa z visual studio

Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:13 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10035
1

screenshot-20230221230723.png

lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0

https://nemequ.github.io/munit/
Takie coś będzie ok?

Riddle
Administrator
  • Rejestracja:ponad 14 lat
  • Ostatnio:13 minut
  • Lokalizacja:Laska, z Polski
  • Postów:10035
0
lester29 napisał(a):

https://nemequ.github.io/munit/
Takie coś będzie ok?

Tak, wydaje się spoko.

lester29
  • Rejestracja:ponad 2 lata
  • Ostatnio:około rok
  • Postów:114
0

Ma ktoś pomysł jak uogólnić listę na dane dowolnego typu? Czy zmiana typu data z inta na void* będzie dobrym pomysłem?

Althorion
Moderator C/C++
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 17 godzin
  • Postów:1601
1
  1. Jak chcesz testować listę, to testuj listę, a nie jej mocka. Mock zapewne działa poprawnie, to lista może być popsuta…
  2. W C niestety trudno o lepsze rozwiązanie niż void * w takich sytuacjach… Inne podejścia byłyby karkołomne. Byłby sens je rozważać, gdybyś chciał jednak ograniczyć zakres typów, które lista może przechowywać; ale jak faktycznie chcesz ogólną listę (a raczej chcesz), to byłoby to raczej bezcelowe.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)