Ładowanie obiektu z pliku binarnego

Ładowanie obiektu z pliku binarnego
P3
  • Rejestracja:około 4 lata
  • Ostatnio:ponad rok
  • Postów:103
0

Witam
Mam taki problem że kiedy tworze plik binarny za pomocą klasy fstream i chciałbym zapisać w nim obiekt typu sf::RectangleShape z sfmla, a następnie odczytać i wyświetlić, visual studio nie sygnalizuję żadnego błędu. Jeśli próbuje wyświetlić w konsoli jakiś parametr obiektu wczytanego za pomocą fstream bez problemowo wszystko działa. Problem się pojawia kiedy próbuje wyświetlić ten obiekt. Próbowałem dynamicznie zaalokować obiekt a później skopiować ten odczytany ale to nie działa.

Kopiuj
#include <SFML/Graphics.hpp>
#include <iostream>
#include <fstream>

bool isCollision(sf::Vector2f A_pos, sf::Vector2f A_size, sf::Vector2f B_pos, sf::Vector2f B_size) {
	if (A_pos.x + A_size.x >= B_pos.x && A_pos.x <= B_pos.x + B_size.x && A_pos.y + A_size.y >= B_pos.y && A_pos.y <= B_pos.y + B_size.y) {
		return true;
	}

	return false;
}


int main() {

	sf::RenderWindow window(sf::VideoMode(300,300), "Snake", sf::Style::Default);
	window.setFramerateLimit(100);

	sf::RectangleShape rect;
	rect.setFillColor(sf::Color::Blue);
	rect.setPosition(sf::Vector2f(20,85));
	rect.setSize(sf::Vector2f(20,100));

	using namespace std;

    //Jesli stworze plik to juz tego kodu ponizej nie potrzebuje
	/*
	fstream saveFile("plik.bin", ios_base::binary | ios_base::out);
	saveFile.write((char*)&rect, sizeof(sf::RectangleShape));
	saveFile.close();
	*/



	sf::RectangleShape rec;

	fstream plik("plik.bin", ios_base::binary | ios_base::in);
	if (plik.good()) {
		cout << "Znalazlo plik" << endl;
		plik.read((char*)&rec, sizeof(sf::RectangleShape));
		plik.close();
	}



	while (window.isOpen()) {
		sf::Event event;

		while (window.pollEvent(event)) {
			if (event.type == sf::Event::Closed) {
				window.close();
			}
		}
		if (isCollision(sf::Vector2f(sf::Mouse::getPosition().x-window.getPosition().x, sf::Mouse::getPosition().y - window.getPosition().y), sf::Vector2f(1, 1), rect.getPosition(), rect.getSize())) {
			rect.setFillColor(sf::Color(rand()+ 255, rand() + 255,rand() + 255));
		}
		using namespace std;	


		window.clear();


        //Ta linijka ponizej generuje blad 
        window.draw(rec);
		window.display();

	}

	return 0;
}
edytowany 1x, ostatnio: Riddle
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
4

Prawdopodobnie obiekt ma część dynamiczną, czyli wskaźniki lub klasy zawierające część dynamiczną,
takie obiekty nie da się zapisać wprost.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:około 2 godziny
2

Od formalnej strony ten kod

Kopiuj
plik.read((char*)&rec, sizeof(sf::RectangleShape));

Zawiera undefined behavior.
Zwykle zadziała, ale mogą się podziać różne dziwne rzeczy.

Wiele ludzi tak robi z lenistwa (bo to jest szybki hack, który się wydaje działać zawsze).

Zalecałbym użyc jakiejś biblioteki i zapisać / odczytać dane ozywając jakiegoś standardowego formatu przyjaznego człowiekowi: JSon, xml, YAML?
Po pierwsze nauczysz się jakiś standardów zapisywania danych; po drugie: będziesz miał plik, który będzie łatwy w poprawianiu i czytaniu.

Równocześnie dziel kod na małe funkcje. Oddzielaj wczytywanie danych, od obłsugi UI, od logiki aplikacji, itp itd ... .
To ograniczy spaghetti code.

sf::RectangleShape ma dużo więcej niż tylko wymiary. Trzyma nawet teksturę.
Ergo używa wskaźników. Nigdy nie wolno zapisywać dosłownie wskaźników by potem je odczytać przy kolejnym uruchomieniu. A to włąśnie robisz.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 3x, ostatnio: MarekR22
P3
  • Rejestracja:około 4 lata
  • Ostatnio:ponad rok
  • Postów:103
0
MarekR22 napisał(a):

Od formalnej strony ten kod

Kopiuj
plik.read((char*)&rec, sizeof(sf::RectangleShape));

Zawiera undefined behavior.
Zwykle zadziała, ale mogą się podziać różne dziwne rzeczy.

Wiele ludzi tak robi z lenistwa (bo to jest szybki hack, który się wydaje działać zawsze).

Zalecałbym użyc jakiejś biblioteki i zapisać / odczytać dane ozywając jakiegoś standardowego formatu przyjaznego człowiekowi: JSon, xml, YAML?
Po pierwsze nauczysz się jakiś standardów zapisywania danych; po drugie: będziesz miał plik, który będzie łatwy w poprawianiu i czytaniu.

Równocześnie dziel kod na małe funkcje. Oddzielaj wczytywanie danych, od obłsugi UI, od logiki aplikacji, itp itd ... .
To ograniczy spaghetti code.

sf::RectangleShape ma dużo więcej niż tylko wymiary. Trzyma nawet teksturę.
Ergo używa wskaźników. Nigdy nie wolno zapisywać dosłownie wskaźników by potem je odczytać przy kolejnym uruchomieniu. A to włąśnie robisz.

to jak to rozwiązać ?

JB
A myślałeś żeby porównać bajt po bajcie to co zapisujesz i od razu to odczytać?
JB
  • Rejestracja:około 2 lata
  • Ostatnio:około 15 godzin
  • Lokalizacja:Holandia
  • Postów:843
0

@plugan300: jak Ty chcesz zapisać dosłownie wskaźnik? Piszesz o wartości na którą wskazuje? Nie wolno zapisać wartości na którą wskazuje wskaźnik?


MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:około 2 godziny
0
plugan300 napisał(a):

to jak to rozwiązać ?

MarekR22 napisał(a):

Zalecałbym użyc jakiejś biblioteki i zapisać / odczytać dane ozywając jakiegoś standardowego formatu przyjaznego człowiekowi: JSon, xml, YAML?
Po pierwsze nauczysz się jakiś standardów zapisywania danych; po drugie: będziesz miał plik, który będzie łatwy w poprawianiu i czytaniu.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
Marius.Maximus
  • Rejestracja:ponad 14 lat
  • Ostatnio:minuta
  • Postów:2079
0

--
Nie przyjmuję reklamacji za moje rady, używasz na własną odpowiedzialność.
Programowanie bez formatowania to jak chodzenie ze spodniami spuszczonymi na kostki. Owszem da się ale po pierwsze nie wygodne, po drugie nieprzyzwoicie wygląda.
Przed zaczęciem nowego wątku przeczytam problem XY
P3
  • Rejestracja:około 4 lata
  • Ostatnio:ponad rok
  • Postów:103
0
Adamek Adam napisał(a):

https://json.nlohmann.me/api/adl_serializer/to_json/#examples
https://json.nlohmann.me/api/adl_serializer/from_json/#examples

Chciałem kreator mapy do gry 2d gdzie używam własnych klas w których są obiekty z sfml i inne dane, myślałem że wrzuce wszystko do pliku binarnego i łatwo odczytam. A w jaki sposób powinno się zapisywać takie dane ?

Marius.Maximus
  • Rejestracja:ponad 14 lat
  • Ostatnio:minuta
  • Postów:2079
0
MarekR22 napisał(a):
plugan300 napisał(a):

to jak to rozwiązać ?

MarekR22 napisał(a):

Zalecałbym użyć jakiejś biblioteki i zapisać / odczytać dane ozywając jakiegoś standardowego formatu przyjaznego człowiekowi: JSon, xml, YAML?
Po pierwsze nauczysz się jakiś standardów zapisywania danych; po drugie: będziesz miał plik, który będzie łatwy w poprawianiu i czytaniu.

w linkach masz przykład z "user-defined type ns::person" w obie strony do json i z json. Dodajesz funkcje from_json , to_json i gotowe ;)
Oczywiście jak obiekt jest skompilowany to trzeba trochę więcej napisać niż w przykładach.


--
Nie przyjmuję reklamacji za moje rady, używasz na własną odpowiedzialność.
Programowanie bez formatowania to jak chodzenie ze spodniami spuszczonymi na kostki. Owszem da się ale po pierwsze nie wygodne, po drugie nieprzyzwoicie wygląda.
Przed zaczęciem nowego wątku przeczytam problem XY
mwl4
  • Rejestracja:około 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Wrocław
  • Postów:399
1

Jeśli używasz C++17 to da się uzyskać serializację/deserializację każdej struktury/klasy bez pisania dodatkowego kodu - tj. funkcji dla każdej klasy osobno.

https://github.com/CppCon/CppCon2022/blob/main/Presentations/Killing-C%2B%2B-Serialization-Overhead-%26-Complexity-EyalZedaka.pdf


Asm/C/C++
edytowany 1x, ostatnio: mwl4
JV
  • Rejestracja:ponad 6 lat
  • Ostatnio:2 miesiące
  • Postów:242
1

RectangleShape dziedziczy po Shape a tam takie coś:

Kopiuj
class SFML_GRAPHICS_API Shape : public Drawable, public Transformable
{
....
private:
....
    const Texture* m_texture{};                  //!< Texture of the shape
    IntRect        m_textureRect;                //!< Rectangle defining the area of the source texture to display
    Color          m_fillColor{Color::White};    //!< Fill color
    Color          m_outlineColor{Color::White}; //!< Outline color
    float          m_outlineThickness{};         //!< Thickness of the shape's outline
    VertexArray    m_vertices{PrimitiveType::TriangleFan};          //!< Vertex array containing the fill geometry
    VertexArray    m_outlineVertices{PrimitiveType::TriangleStrip}; //!< Vertex array containing the outline geometry
    FloatRect      m_insideBounds;                                  //!< Bounding rectangle of the inside (fill)
    FloatRect      m_bounds; //!< Bounding rectangle of the whole shape (outline + fill)
};

m_texture jest wskaźnikiem ale jak tekstur nie używasz to jest tam null_ptr i do pliku zapiszą się zera, więc to jeszcze przejdzie.

Problem jest pewnie z VertexArray który zawiera pole std::vector<Vertex> m_vertices;, a tam jak wiadomo również jest wskaźnik

Wywołaj po kolei getFillColor, getPosition, getSize dla obiektu rect i te wartości dopiero zapisz do pliku binarnego. To są proste typy i nie zawierają wskaźników więc zrzut pamięci nie przysporzy problemów.

kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:dzień
  • Lokalizacja:Łódź
  • Postów:1402
0

m_texture też nie przejdzie - bo zapis binarny nie analizuje pół, tylko zapisuje zrzut pamięci spod danego adresu. Tak jak pisali poprzednicy - takie zrzuty pamięci są 1) niebezpieczne (jeśli nie wiesz co robisz), 2 często nieprzenośne - wystarczy, że kompilacja będzie z innymi parametrami i może się okazać, że dane się rozjadą. Dlatego do takich celów używa się, tak jak pisali to wcześniej, albo czytelnych dla użyszkdnika formatów jak xml i pochodne, albo binarnych, ale w ustandaryzowany sposób, gdzie czytamy blokami (jak np stary format iff)


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
JB
  • Rejestracja:około 2 lata
  • Ostatnio:około 15 godzin
  • Lokalizacja:Holandia
  • Postów:843
0

/Napisz może to po ludzku.
Robisz wskaźnik na char, ustawiasz na pierwszym elemencie struktury, zapisujesz do pliku tyle bajtów jaki jest rozmiar(przesuwając wskaźnik, czyli w pętli). Potem następny element struktury i tak dalej.
Żeby odczytać tworzysz strukturę, tworzysz wskaźnik ustawiasz na początku pierwszego elementu i bajt bo bajcie odczytujesz z pliku tyle jaki jest jego rozmiar. To samo robisz z następnym.

Przykład:

Kopiuj
#include <stdio.h>
struct typek{
            int pierwszy;
            double drugi;
            };

int main(){
          FILE *plik;
          plik=fopen("aplik.txt","wb");
          struct typek nowy;
          nowy.pierwszy=555;
          nowy.drugi=33;
          char *tmp;


/*  zapisywanie */


/* ustawiasz na poczatku zmiennej */

          tmp=(char*)&nowy.pierwszy; 

 /* jedziesz wskaźnikiem po wartościach w zmiennej nowy.pierwszy */
 
for(int i=0;i<sizeof(nowy.pierwszy);i++){

          fprintf(plik,"%c",*tmp);tmp++;}

/*  powtarzasz operacje */

          tmp=(char*)&nowy.drugi;

/* jedziesz wskaźnikiem po wartościach w zmiennej nowy.drugi */
          
          for(int i=0;i<sizeof(nowy.drugi);i++){
              fprintf(plik,"%c",*tmp);tmp++;}

          fclose(plik);

/*         odczytywanie   */

          struct typek nowszy;

          plik=fopen("aplik.txt","rb");

          tmp=(char*)&nowszy.pierwszy; 

          for(int i=0;i<sizeof(nowszy.pierwszy);i++){
          fscanf(plik,"%c",tmp);tmp++;}	
	


          tmp=(char*)&nowszy.drugi; 

          for(int i=0;i<sizeof(nowszy.drugi);i++){
          fscanf(plik,"%c",tmp);tmp++;}	
	


          fclose(plik);

          printf("Wczytane zmienne:\n%d - %f",nowszy.pierwszy,nowszy.drugi);


return 0;
}

Odczytujesz podobnie.
Jak masz ileś takich samych struktur to robisz pętlę.
Tu się nie ma co nie udać, to są same podstawy.
Nie ma się nad czym modlić.
Wstaw sobie inne liczby niż 555 i 33 (albo zmodyfikuj typy w strukturze) i sam się przekonaj.
Nie wiem w sumie czy by nie dało rady z całą strukturą tak zrobić od razu(sizeof(typek)) i skrócić kod do 5% tego co jest.


edytowany 3x, ostatnio: johnny_Be_good
Marius.Maximus
fuj ! tak bez żadnego wcięcia to aż oczy bolą, a jest jedno, w strukturze ;)
JB
Przepraszam, to mój pierwszy kod, obiecuję, że to był przedostatni raz xD
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
0
johnny_Be_good napisał(a):

/Napisz może to po ludzku.

To co podałeś nie jest po ludzku! Sam oceń, to jest po ludzku:

Kopiuj
#include <stdio.h>

struct Data
{
    int iVale;
	double dValue;
};

int main()
{
    struct Data data={555,33};
	FILE *fwd=fopen("aplik.txt","wb");
    fwrite(&data,sizeof(data),1,fwd);
    fclose(fwd);
    printf("Zapisane dane: {%d, %f}\n",data.iVale,data.dValue);
    
    struct Data newdata={0,0};
	FILE *frd=fopen("aplik.txt","rb");
    fread(&newdata,sizeof(data),1,frd);
    fclose(frd);    
    printf("Wczytane dane: {%d, %f}\n",newdata.iVale,newdata.dValue);
    
	return 0;
}

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 2x, ostatnio: _13th_Dragon
Zobacz pozostałe 7 komentarzy
_13th_Dragon
Właśnie Hitler miał plany ale nie słuchał doradców i się pośpieszył w związku z czym spieprzył to i owo zaś w wyniku czego jego plany poszły się parzyć. Owszem ludzie uczą się na własnych błędach zaś mądrzy ludzi - na cudzych.
JB
Dla niego właśnie to co zrobił było bardzo ważne. Dla mnie moje plany są bardzo ważne. A co dla Ciebie jest bardzo ważne? Chcesz pouczać mnie, chcesz pouczać jego, a jakie sam masz plany? Napiszę to po angielsku "You're don't know, what You're dealing with".
ZD
@johnny_Be_good: jeszcze nie skojarzyłem, czyją jesteś reinkarnacją, ale jesteś
JB
@ZrobieDobrze: "I am Your father, Luke" xD
_13th_Dragon
Moi znajomi pracują w pewnym zakładzie, kiedyś mówili że mają tam dwóch ojców Luka.
JV
  • Rejestracja:ponad 6 lat
  • Ostatnio:2 miesiące
  • Postów:242
0
kaczus napisał(a):

m_texture też nie przejdzie - bo zapis binarny nie analizuje pół, tylko zapisuje zrzut pamięci spod danego adresu. Tak jak pisali poprzednicy - takie zrzuty pamięci są 1) niebezpieczne (jeśli nie wiesz co robisz), 2 często nieprzenośne - wystarczy, że kompilacja będzie z innymi parametrami i może się okazać, że dane się rozjadą. Dlatego do takich celów używa się, tak jak pisali to wcześniej, albo czytelnych dla użyszkdnika formatów jak xml i pochodne, albo binarnych, ale w ustandaryzowany sposób, gdzie czytamy blokami (jak np stary format iff)

Może źle się wyraziłem, m_texture przejdzie tylko w przypadku gdy nie używamy tekstur, wtedy to pole zawiera null_ptr i zapis zera do pliku nie powinien przysporzyć większych problemów. Oczywiście jest to niebezpieczne i tak się nie powinno zapisywać danych ale program przez 99% czasu może chodzić i wykrzaczyć się w najbardziej niekorzystnym momencie. Natomiast zrzut pola m_vertices, który jest typem std::vector<?> gwarantuje że za każdym razem ten program się wysypie, co nawet jest korzystne bo od razu pojawia się błąd, który trzeba poprawić żeby ruszyć dalej z projektem.

Poniżej kod po poprawce. Do pliku trzeba zrzucić potrzebne dane, które pozwalają odtworzyć obiekt:

Kopiuj
#include <SFML/Graphics.hpp>
#include <fstream>
#include <iostream>

bool isCollision(sf::Vector2f A_pos, sf::Vector2f A_size, sf::Vector2f B_pos,
                 sf::Vector2f B_size) {
    if (A_pos.x + A_size.x >= B_pos.x && A_pos.x <= B_pos.x + B_size.x &&
        A_pos.y + A_size.y >= B_pos.y && A_pos.y <= B_pos.y + B_size.y) {
        return true;
    }

    return false;
}

int main() {
    sf::RenderWindow window(sf::VideoMode(300, 300), "Snake", sf::Style::Default);
    window.setFramerateLimit(100);

    sf::RectangleShape rect;
    rect.setFillColor(sf::Color::Blue);
    rect.setPosition(sf::Vector2f(20, 85));
    rect.setSize(sf::Vector2f(20, 100));

    using namespace std;

    // Jesli stworze plik to juz tego kodu ponizej nie potrzebuje
    /* fstream saveFile("plik.bin", ios_base::binary | ios_base::out); */
    /* auto fcolor = rect.getFillColor(); */
    /* saveFile.write((char*)&fcolor, sizeof(fcolor)); */
    /* auto pos = rect.getPosition(); */
    /* saveFile.write((char*)&pos, sizeof(pos)); */
    /* auto size = rect.getSize(); */
    /* saveFile.write((char*)&size, sizeof(size)); */
    /* saveFile.close(); */

    sf::RectangleShape rec;

    fstream plik("plik.bin", ios_base::binary | ios_base::in);
    if (plik.good()) {
        cout << "Znalazlo plik" << endl;
        sf::Color fcolor;
        plik.read((char*)&fcolor, sizeof(fcolor));
        sf::Vector2f pos;
        plik.read((char*)&pos, sizeof(pos));
        sf::Vector2f size;
        plik.read((char*)&size, sizeof(size));
        plik.close();

        rec.setFillColor(fcolor);
        rec.setPosition(pos);
        rec.setSize(size);
    }

    while (window.isOpen()) {
        sf::Event event;

        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }
        if (isCollision(
                sf::Vector2f(
                    sf::Mouse::getPosition().x - window.getPosition().x,
                    sf::Mouse::getPosition().y - window.getPosition().y),
                sf::Vector2f(1, 1), rect.getPosition(), rect.getSize())) {
            rect.setFillColor(
                sf::Color(rand() + 255, rand() + 255, rand() + 255));
        }
        using namespace std;

        window.clear();

        // Ta linijka ponizej generuje blad
        window.draw(rec);
        window.display();
    }

    return 0;
}
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)