Transponowanie macierzy

Transponowanie macierzy
D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

Cześć, piszę sobie klasę do obsługi działań na macierzach:

Kopiuj
class Macierz
{
public:
	Macierz(int a, int b);
	Macierz(int a, int b, int c);
	~Macierz();
	void wypisz(void) const;
	void transponuj(void);

private:
	int **tab;
	int x;
	int y;
}; 

I chcę napisać metodę 'transponuj' która zrobi transponowanie macierzy (wiersz to kolumna, a kolumn to wiersz).

Kopiuj
void Macierz::transponuj(void)
{
	int **tab_trans = new int *[y];
	for (int k = 0; k < y; ++k)
	{
		tab[k] = new int[x];
	}
	for (int i = 0; i < y; i++)
	{
		for (int j = 0; j < x; j++)
			tab_trans[i][j] = tab[j][i]; //tu wywala!
	}
	tab = tab_trans;
	swap(x, y);
	//tu jeszcze zwolnienie pamięci dla tab_trans
} 

W komentarzu zaznaczyłem miejsce w którym program sie wysypuje, mógłby ktoś spojrzeć i dać wskazówkę co jest nie tak?

spartanPAGE
Piszesz w C++. Nie potrzebujesz voida w nawiasach, gdy nie pobierasz argumentów.
D1
Ok, zapamiętam, mimo to nie rozwiązuje to mojego problemu.
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
1
Kopiuj
    int **tab_trans = new int *[x];
    for (int k = 0; k < x; ++k)
    {
        tab[k] = new int[y];
    }

Oraz zapomniałeś zwolnić tab wraz z wierszami.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

No tak, ale wydaje mi się że problem nie leży w samym utworzeniu tab_trans (tablica ta ma mieć rozmiar odwrotny do tab), tylko w przypisaniu do tab_trans, odpowiedniej wartości tab.

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Tak jak pisze @_13th_Dragon masz memleak, bo nie zwalniasz tablicy (http://en.wikipedia.org/wiki/Memory_leak).
To nie bezpośrednio powód tego że Ci nie działa, to kolejny błąd. Powinieneś zwalniać tab zanim zmienisz jego wartość.

Jak o zwalnianiu mowa:

Kopiuj
//tu jeszcze zwolnienie pamięci dla tab_trans

Jeśli fatycznie zwalniasz pamięć dla tab_trans, to zwalniasz całą tablicę (w tym momencie tab_trans pokazuje na to samo na co tab) - nic dziwnego że nie działa.

Jeszcze możesz się przyjrzeć czy x i y są poprawnie inicjalizowane.

edytowany 2x, ostatnio: msm
D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

Mój pomysł przedstawiał się następująco:

  • mam tablicę którą chcę transponować, powiedzmy tab[x][y]
  • rezerwuję sobie miejsce na nową tablicę, tylko z odwróconymi rozmiarami tab_trans [y][x]
  • przepisuje wartości tab do tab_trans
  • zwalniam pamięć dla starej tab
  • niech tab pokazuje na to samo co tab_trans (tab = tab_trans)
  • zwalniam pamięć dla tab_trans

Nie ma tutaj chyba mowy o wyciekach pamięci?

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
1
  • zwalniam pamięć dla starej tab

W kodzie który podałeś tego nie ma, dlatego zauważamy. Tak, z tym nie byłoby wycieku pamięci.

  • zwalniam pamięć dla tab_trans

Ale w ten sposób zwalniasz pamięć dla tego co jest aktualnie.

Prościej będzie opisać strzałkami. Przy wskaźnikach zawsze sprawdzają się strzałki ;)

początkowy stan:

Kopiuj
tab -----------> początkowa tablica

alokowanie pamięci:

Kopiuj
tab -----------> początkowa tablica
tab_trans  ----> nowa tablica

po pętli for robiąca transponowanie:

Kopiuj
tab -----------> początkowa tablica
tab_trans  ----> tablica po transponowaniu (wynik)

po zwolnieniu pamięci dla tab:

Kopiuj
tab -----------> [zwolniona pamięć, śmieci]
tab_trans  ----> tablica po transponowaniu (wynik)

tab = tab_trans:

Kopiuj
tab ---------\
              -----> tablica po transponowaniu (wynik)
tab_trans  --/

I to wszystko czego potrzeba - tab wskazuje już na wynik końcowy, a tab_trans (tzn. sam wskaźnik, cztery/osiem bajtów) zniknie za chwilę bo jest zmienną lokalną.

Ale jeśli teraz zwolnisz tab_trans (czyli pamięć na którą wskazuje), to skończysz z (katastrofa):

Kopiuj
tab ---------\
              -----> [zwolniona pamięć, śmieci]
tab_trans  --/
edytowany 2x, ostatnio: msm
D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

Okej, jeżeli chodzi o alokację pamięci wszystko już rozumiem, dzięki.

Jednak problemem jest teraz przepisanie wartości ze starej tablicy do nowej, gdyż np. linijka tab_trans[i][j] = tab[j][i] nie działa, czyli trzeba tu wymyślić chyba jakiś sprytniejszy sposób, niż ten znany ze statycznych tablic.

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Mógłbyś dać cały kod macierzy? Bo w tym co podałeś nie ma (albo nie widzę na pierwszy rzut oka) błędu, może coś wcześniej idzie źle.

D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0
Kopiuj
 class Macierz
{
public:
	Macierz(int a, int b);
	Macierz(int a, int b, int c);
	~Macierz();
	void wypisz() const;
	void transponuj();
	//void wyznacznik();

private:
	int **tab;
	int x;
	int y;
};
Kopiuj
#include "Macierz.h"
#include <iostream>

using namespace std;

Macierz::Macierz(int a, int b)
{
	x = a;
	y = b;
	tab = new int *[a];
	for (int i = 0; i < a; ++i)
	{
		tab[i] = new int[b];
	}
}

Macierz::Macierz(int a, int b, int c)
{
	x = a;
	y = b;
	tab = new int *[a];
	for (int i = 0; i < a; ++i)
	{
		tab[i] = new int[b];
	}
	//wypełnienie tablicy argumentem c
	for (int i = 0; i < a; i++)
	{
		for (int j = 0; j < b; j++)
			tab[i][j] = c;
	}
}


Macierz::~Macierz()
{
	for (int i = 0; i < x; ++i)
	{
		delete tab[i];
	}
	delete tab;
}

void Macierz::wypisz(void) const
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			cout << tab[i][j] << " ";
		}
		cout << endl;
	}
}

void Macierz::transponuj()
{
	int **tab_trans = new int *[y];
	for (int k = 0; k < x; ++k)
	{
		tab[k] = new int[x];
	}
	for (int i = 0; i < y; i++)
	{
		for (int j = 0; j < x; j++)
		{
			tab_trans[i][j] = tab[j][i]; //tu wywala!
		}
	}
	tab = tab_trans;
	swap(x, y);
} 

Jeszcze nie wcieliłem w życie (w kod), w metodzie transponuj zwalniania pamięci, o którym rozmawialiśmy, ale to chyba nie jest powód tego że program się wysypuje?

Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
0
Kopiuj
    int **tab_trans = new int *[y];
    for (int k = 0; k < x; ++k)

Hint: warunek pętli.

PS nazywaj sensowniej parametry;
PPS //wypełnienie tablicy argumentem c - c jest parametrem, nie argumentem;
PPPS raczej rozmiar macierzy nie może być ujemny, więc int jest nie na miejscu. unsigned int/size_t/(...) byłoby lepszym wyborem.


edytowany 3x, ostatnio: Patryk27
D1
PS sensowniej, tzn?
Patryk27
Widzisz nagłówek metody: Macierz::Macierz(int a, int b, int c). Jak bez patrzenia w jej ciało masz się domyślić, czym są a, b oraz c?
D1
Czyli na ten przykład, zamiast a, będzie wiersz, zamiast b, kolumna itp. Poza tym, lepiej chyba pisać programy po angielsku?
Patryk27
zamiast a, będzie wiersz, zamiast b, kolumna ale to wiesz, ponieważ zajrzałeś do ciała metody. Nie uważasz, że sensowniej byłoby: Macierz::Macierz(unsigned int width, unsigned int height, int defaultValue)?
D1
Tak, masz rację, lepiej nauczyć się zasad pisania, dobrego czytelnego kodu, dzięki za wskazówki!
D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

Tak tak, powinno być:

Kopiuj
 
int **tab_trans = new int *[y];
	for (int k = 0; k < y; ++k)

Ale mimo to dalej wysypuje się w linijce przepisanie wartości: "Instrukcja spod <adres> odwołuje się do pamięci pod adresem <adres>. Pamięć nie może być written".

Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
1

Zauważ jeszcze, do czego przypisujesz:
tab[k] = new int[x];


edytowany 1x, ostatnio: Patryk27
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
1

Faktycznie, nie zauważyłem tego (i nikt inny wcześniej) (chciaż problem jest trochę niżej):

Kopiuj
int **tab_trans = new int *[y];
for (int k = 0; k < y; ++k)
{
    tab[k] = new int[x]; // chcesz stworzyć tablicę 2d z /tab_trans/. W ten sposób tylko "zapominasz" wszystkie dane z tab
    // czyli tab_trans[k] = new int[x];
}

for (int i = 0; i < y; i++)
{
    for (int j = 0; j < x; j++)
        tab_trans[i][j] = tab[j][i]; //tu wywala - bo tab_trans[i] nigdy nie miało przypisanej wartości (i są tam jakieś śmieci).
}

?

D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

Bingo, głupia literówka, zamiast tab_trans miałem w kodzie tab, a tyle kombinowania. Mimo wszystko, dobrze, że zwróciłem się z pomocą, gdyż zwróciliście mi uwagę na te wycieki pamięci. Serdeczne dzięki!

D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

Nie ma sensu zakładać nowego tematu, a jedna rzecz mnie jeszcze interesuje przy okazji rozwijania mojej klasy.
Otóż chcę zrobić funkcjonalność dodawania macierzy, za pomocą przeciążenia operatora +, np:

Kopiuj
macierz A, B, C;
C = A + B 

Dodawać macierze można tylko gdy mają ten sam rozmiar. Ciekawi mnie, czy w przypadku gdy macierze będą miały różne wymiary, to zamiast w metodzie dać ifa sprawdzającego czy mają taki sam rozmiar i wypisującego np. tylko że nie ma możliwości dodania tych macierzy, można zrobić taki mechanizm, że program się w ogóle nie skompiluje, kompilator wyrzuci błąd, iż nie można dodawać macierzy o różnych wymiarach. Analogicznie kompilator protestuje, gdy będziemy chcieli dodać do siebie intigera i np. double'a. Da się coś takiego zrobić w C++?

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
0

Potrzebujesz następujących rzeczy:

Kopiuj
Macierz operator+(const Macierz &m)const { ... }
Macierz &operator=(const Macierz &m) { ... }
Macierz(const Macierz &m) { ... }

oraz jeżeli to C++11 zastanów się nad:

Kopiuj
Macierz &operator=(Macierz &&m) { ... }
Macierz(Macierz &&m) { ... }

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Ciekawi mnie, czy w przypadku gdy macierze będą miały różne wymiary, to zamiast w metodzie dać ifa sprawdzającego czy mają taki sam rozmiar i wypisującego np. tylko że nie ma możliwości dodania tych macierzy, można zrobić taki mechanizm, że program się w ogóle nie skompiluje, kompilator wyrzuci błąd, iż nie można dodawać macierzy o różnych wymiarach

Można, tylko musiałbyś poczytać trochę o szablonach w C++ (http://en.wikipedia.org/wiki/Template_%28C%2B%2B%29)
Wtedy wyglądałoby to tak że można dodać Macierz<A, B> tylko do Macierz<A, B> (gdzie A, B to parametry określające wysokośc i szerokość). Ogólnie ciekawa rzecz do napisania, polecam.

edytowany 1x, ostatnio: msm
D1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 5 lat
  • Lokalizacja:Sosnowiec
  • Postów:21
0

A jakieś informację gdzie można o tym znaleźć? Ew. jak fachowo nazywa się taki zabieg?

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Szablony, po prostu szablony.

Pierwszy (jeden z pierwszych) kurs z brzegu - http://www.tutorialspoint.com/cplusplus/cpp_templates.htm. To dość podstawy, ale wystarczyłoby.

Ale jeśli chcesz zepsuć sobie zabawę, sample (bardzo niekompletny ofc, i pamięć dla tab nie jest nigdy zwalniana ;) ):

Kopiuj
template <int X, int Y>
struct Matrix {
    int **tab;

    Matrix<X, Y>() {
        tab = new int*[X];
        for (int i = 0; i < X; i++) {
            tab[i] = new int[Y];
        }
    }

    Matrix<X, Y> operator +=(Matrix<X, Y> other) {
        // add
    }
};

int main() {
    Matrix<2, 3> m;
    Matrix<2, 3> n;
    Matrix<5, 5> o;

    m += n;
    n += m;
    // n += o; - kompilator głośno krzyczy
}

Przy czym ważne jest zrozumieć że w tym przypadku jest problem z wczytywaniem macierzy o nieznanych rozmiarach (bo kompilator musi znać rozmiar każdej macierzy na etapie kompilacji żeby móc ja zweryfikować).

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:3 miesiące
0

@msm, przekombinowałeś, jeżeli już masz rozmiary ustawione w parametrach to:

Kopiuj
template<size_t X,size_t Y> struct Matrix
  {
   double tab[Y][X];
   Matrix() { memset(&tab[0][0],0,sizeof(tab)); }
   Matrix &operator+=(const Matrix &other)
     {
       // add
     }
  };

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
Endrju
Ten memset to undefined behavior.
_13th_Dragon
tak, tak już wyjaśnialiśmy, jakiś zapis w standardzie zrozumiałeś jako: sizeof(tab)!=X*Y*sizeof(double)
Endrju
Nie wiem o czym Ty mówisz, ale nie można wskaźnikiem pokazującym na tab[0][0] wyjść poza tab[0][X-1].
_13th_Dragon
Ok, czyli twierdzisz że tab nie jest pamięcią ciągłą?
Endrju
Oczywiście, że jest. I to nie zmienia tego, że to UB. Poza tym wpisywanie binarnych zer w double jest niemądre - nie wiadomo co będzie oznaczać takie coś.
_13th_Dragon
Jeżeli to jest jeden obszar oraz sizeof(tab)==X*Y*sizeof(double) to nie ma mowy aby to było UB - już wyjaśnialiśmy coś ci się źle zrozumiało albo tak bez sensu napisane. Jeżeli tak sobie życzysz to za każdym razem będziemy to tak krok po kroku przechodzić. Przypominam że powtarzamy to po raz trzeci na tym forum a nadal nie wiesz o czym mówię. Poza tym czyżby IEEE 754 oraz innych nie uznajesz?
Endrju
To jest undefined behavior. @kq przyzywam Cię.
_13th_Dragon
No oczywiście bo pamięć komputera może mieć 4-ty wymiar i mimo że tab zajmuje ciągły obszar oraz ten rozmiar spełnia sizeof(tab)==X*Y*sizeof(double) to są w nim jakieś dziury i wstawki z innego obszaru. Chrzanić logikę - coś zrozumiałeś że jest UB - to już nie ważne dobrze czy źle zrozumiałeś jest UB i już.
Endrju
Nic nie poradzę na to, że tak zostało to zdefiniowane w standardzie. Nie można wyjść wskaźnikiem poza tablicę z której on pochodzi i koniec kropka. This is the law. (5.7.5)
_13th_Dragon
Problem w tym że nie rozumiesz że to ta sama tablica.
Endrju
No niestety to nie jest ta sama tablica. Musisz zrozumieć jak są zdefiniowane takie tablice w C/C++. Takie coś: T t[N][M] to są dwie różne tablice: jedna to tablica N-elementów typu T[M] a druga to tablica M-elementów typu T. Dokładnie jest to opisane w 8.3.4.
_13th_Dragon
Rozumiem - chrzanimy logikę.
Ranides
nie mam pojęcia, który ma rację, więc może by tak... Matrix() : tab{{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)