Metody (template) dla array helper'a

Metody (template) dla array helper'a
CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0

Panowie,

Zaczynam sobie przygotowywac custom helper'a dla wielowymiarowych tablic. Zaczalem od dwoch metod template:

  1. inicjalizacja tablicy:
Kopiuj
		template <typename T>
		T** initArr2DT(T** arr2DPtr, int iLength, int jLength)
		{
			arr2DPtr = new T*[iLength];

			for (int i = 0; i < iLength; i++)
			{
				arr2DPtr[i] = new T[jLength];

				memset(arr2DPtr[i], '\0', sizeof(arr2DPtr[i]));
			}

			return arr2DPtr;
		}
  1. kopiowanie tablicy:
Kopiuj
		template <typename T>
		T** copyArr2DT(T** arr2DPtr, T** arr2DCopyPtr, int iLength, int jLength)
		{
			arr2DCopyPtr = new T*[iLength];

			for (int i = 0; i < iLength; i++)
			{
				arr2DCopyPtr[i] = new T[jLength];

				for (int j = 0; j < jLength; j++)
				{
					arr2DCopyPtr[i][j] = arr2DPtr[i][j];
				}
			}

			return arr2DCopyPtr;
		}

Prosze o ich ocene i ewentualne wskazowki co do ulepszenia kodu.
Z gory dziekuje :)

tajny_agent
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad rok
  • Postów:1340
5

Obie funkcje różnią się tylko jedną linijką. (DRY)

Nie chcę być złośliwy, ale w C++ kopiowanie wielowymiarowej tablicy(std::vector czy std::array) wygląda tak:

Kopiuj
secondArray = firstArray;

"I love C++. It's the best language in the world right now for me to write the code that i need and want to write"
~ Herb Sutter
CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0
tajny_agent napisał(a):

Obie funkcje różnią się tylko jedną linijką. (DRY)

  1. W pierwszym przypadku potrzebuje jedynie pustej zainicjowanej tablicy do ktorej moge wpisac w petli wartosci odczytywane z pliku
tajny_agent napisał(a):

Nie chcę być złośliwy, ale w C++ kopiowanie wielowymiarowej tablicy(std::vector czy std::array) wygląda tak:

Kopiuj
secondArray = firstArray;
  1. Alez bron Cie Panie Boze :). W drugim przypadku chodzi o to ze kopiowana tablica (arr2DPtr) w zalozeniu jest lokalna w ciele pewnej metody klasy, natomiast kopiujaca (arr2DCopyPtr) jest tej samej klasy atrybutem. I tutaj jest problem bo w przypadku kopiowania o ktorym mowisz oba wskazniki sa identyczne. Kiedy metoda konczy swoje dzialanie szlak trafia tablice arr2DPtr co (o ile dobrze rozumiem zawilosci w kwestii wskaznikow w C++) ma fatalne konsekwencje dla arr2DCopyPtr. Zatem w skrocie chodzilo mi o skopiowanie wartosci z jednej tablicy do drugiej a nie jej klonowanie w przypadku kiedy obie maja rozny zasieg.
    Oczywiscie jest wysoce prawdopodobne, ze moge nie brac pewnych istotnych rzeczy pod uwage (c++ to nie moja bajka, jestem php-owcem), ale wg mojego aktualnego (niewielkiego zreszta) stanu wiedzy wlasnie w taki sposob moge sobie poradzic.

Jesli masz jakies sugestie mogac mi pomoc rozwiazac te zagwozdke - bede szczerze wdzieczny.

edytowany 1x, ostatnio: Constantic
YooSy
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 5 lat
  • Postów:472
3
Kopiuj
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using Vec2Int = std::vector<std::vector<int>>;

template <typename C>
void Copy(const C& src, C& dest) {
   dest = src;
}

template <typename C>
void LocalCopy(C& coll) {
   C loclaColl{ {11, 22, 33}, {44, 55, 66} };
   Copy(loclaColl, coll);
}

template <typename C>
void Mult(C& coll, int n) {
   for (auto& dimension : coll) {
      std::transform(
         dimension.cbegin(), dimension.cend(), 
         dimension.begin(), 
         [=](auto& el) { return el * n; });
   }
}

template <typename C>
void Print(const C& coll, const std::string& opt = "") {
   if (!opt.empty()) { std::cout << opt << &coll << '\n'; }
   for (auto const& firstDimension : coll) {
      for (auto const& secondDimensionElement : firstDimension) {
         std::cout << secondDimensionElement << ' ';
      }
      std::cout << '\n';
   }
   std::cout << std::endl;
}

int main() {
   Vec2Int arr1{ { 1, 2, 3 }, {4, 5, 6 } };
   Vec2Int arr2;
   Vec2Int arr3;
   Copy(arr1, arr2);
   Print(arr1, "arr1");
   Mult(arr2, 3);
   Print(arr2, "arr2");
   LocalCopy(arr3);
   Mult(arr3, 2);
   Print(arr3, "arr3");
}

Czy o to chodziło?
https://wandbox.org/permlink/qsQGvyLXsVDZxfRH

Można też użyć jednowymiarowej tablicy z widokiem dwuwymiarowym.


Nie pisz na priv. Zadaj dobre pytanie na forum.
edytowany 4x, ostatnio: YooSy
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
1

A samo std::copy sobie tu nie da sobie rady?
Dobra rada tak ogólnie: wyrzuć książki/tutoriale do C++, których używasz.i zapomnij, że nie new i delete w ogóle istnieją.

YooSy
Da radę, chciałem pokazać samą ideę.
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
2

Ten memset w przypadku bliżej nieokreślonego typu T jest błędem (zresztą źle go używasz). Jeśli T może być czymś więcej niż typem liczbowym, zastanowiłbym się nad użyciem std::allocator.

PS. ten sposób tworzenia tablicy 2D nie jest zbyt optymalny pamięciowo.

edytowany 1x, ostatnio: _0x666_
CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0

Panowie,

Wszystkim bardzo dziekuje za konstruktywne wypowiedzi.

tajny_agent
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad rok
  • Postów:1340
1
Constantic napisał(a):
  1. Alez bron Cie Panie Boze :). W drugim przypadku chodzi o to ze kopiowana tablica (arr2DPtr) w zalozeniu jest lokalna w ciele pewnej metody klasy, natomiast kopiujaca (arr2DCopyPtr) jest tej samej klasy atrybutem. I tutaj jest problem bo w przypadku kopiowania o ktorym mowisz oba wskazniki sa identyczne. Kiedy metoda konczy swoje dzialanie szlak trafia tablice arr2DPtr co (o ile dobrze rozumiem zawilosci w kwestii wskaznikow w C++) ma fatalne konsekwencje dla arr2DCopyPtr. Zatem w skrocie chodzilo mi o skopiowanie wartosci z jednej tablicy do drugiej a nie jej klonowanie w przypadku kiedy obie maja rozny zasieg.
    Oczywiscie jest wysoce prawdopodobne, ze moge nie brac pewnych istotnych rzeczy pod uwage (c++ to nie moja bajka, jestem php-owcem), ale wg mojego aktualnego (niewielkiego zreszta) stanu wiedzy wlasnie w taki sposob moge sobie poradzic.

W kwestii wskaźników oczywiście masz rację. Kopiowanie wskaźnika nie powoduje skopiowania wszystkiego co się pod nim tak naprawdę kryje(o to właśnie chodzi we wskaźnikach :P).
Dlatego zasugerowałem użycie klasy std:vector lub std:array. Nie musisz sobie zawracać głowy alokowaniem/zwalnianiem pamięci, kopiowanie odbywa się za pomocą zwykłego operatora przypisania = i dodatkowo oferują kilka pomocnych funkcji. Prostsze jest również ich użycie w funkcjach z <algorithm>.


"I love C++. It's the best language in the world right now for me to write the code that i need and want to write"
~ Herb Sutter
CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0

Panowie jesli mozna pojsc za ciosem to mam pytanie w zwiazku z "vector".

Otoz w jednym z naglowkow aplikacji "zapodalem" sobie taka definicje typu:

Kopiuj
//ArrayHelper.h
//...
typedef std::vector<std::vector<string>> ArrString2D;

namespace CoreHelper
{
	class ArrayHelper
	{
	//...
	}
}

Zakladajac, iz w ten sposob bedzie ona dostepna globalnie - i tutaj pierwsze pytanie - czy praktyczniej nie bedzie umiescic definicji od razu w czasie "odpalenia" aplikacji ?
Ok, ale przejdzmy do meritum.
W innym miejscu chce wykorzystac zdefiniowany przez siebie typ w przypadku lokalnej tablicy, ale w ponizszym przypadku

Kopiuj
//DataReader.cpp

ArrString2D DataReader::readFromFile(string file)
{
	ArrString2D arrString2D(*rowsNumberPtr, vector<string>(*colsNumberPtr));
}

Na gwiazdce "*rowsNumberPtr" wywala mi blad "no istance of constructor...". Sprobowalem zatem czegos takiego:

Kopiuj
//DataReader.cpp

ArrString2D DataReader::readFromFile(string file)
{
	ArrString2D arrString2D(*rowsNumberPtr);
       //...
	while (!reader.eof()) {
       //...
		vector<string> col(*colsNumberPtr);
       //...
		while ((pos = line.find(delimiter)) != string::npos) {
       //...
			col.at(j) = line.substr(0, pos);
       //...
		}
       //...
		arrString2D.at(i).resize(*colsNumberPtr);
		arrString2D.at(i) = col;
       //...
	}
       //...        
}

Ale w momencie przypisania: "arrString2D.at(i) = col;" pojawia sie kolejny blad : "no operator "=" matches these operands".

Jesli jednak zrobie cos takiego:

Kopiuj
//DataReader.cpp

ArrString2D DataReader::readFromFile(string file)
{
	vector<vector<string>> arrString2D(*rowsNumberPtr, vector<string> (*rowsNumberPtr));
}

Przypisanie dziala bez zarzutu, ale typ "vector<vector<string>>" deklarowany w ciele metody nie jest tozsamy z "typedef std::vector<std::vector<string>> ArrString2D;" :/

W jaki zatem sposob powinienem postapic ?
Z gory dziekuje za sugestie.

edytowany 2x, ostatnio: Constantic
RE
co to jest rowsNumberPtr ? Wskaźnik na int?
RE
  • Rejestracja:ponad 18 lat
  • Ostatnio:16 minut
1

przejże sobie dokładnie jak wrócę z pracy ale:

  • using zamiast typedef
Kopiuj
ArrString2D arrString2D(*rowsNumberPtr, vector<string>(*colsNumberPtr));

Co ty chcesz tu zrobić? masz typ vector<vector<>> i skąd weźmiesz taki konstruktor? Po prostu zrób tak

Kopiuj
ArrString2D arrString2D;
// rezerwacja pamięci i dodawanie wektorów przez emplace_back itd. czy jakieś inne listy inicjalizacyjne. sprawdź dokumentacje

http://en.cppreference.com/w/cpp/container/vector

at() rzuca wyjątkami jak pamiętam do tego:
https://stackoverflow.com/questions/9912223/c-fill-a-vector-with-another-vector


We are the 4p. Existence, as you know it, is over. We will add your biological and technological distinctiveness to our own. Resistance is futile
CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0
revcorey napisał(a):
Kopiuj
ArrString2D arrString2D;
// rezerwacja pamięci i dodawanie wektorów przez emplace_back itd. czy jakieś inne listy inicjalizacyjne. sprawdź dokumentacje

Works like a charm :D. Wczesniej probowalem identycznej deklaracji ale "sypalo" mi sie na push_back'u wiec nawet nie probowalem z emplace_back, a jednak okazalo sie, ze powinienem byl.

Bardzo Ci dziekuje.

RE
  • Rejestracja:ponad 18 lat
  • Ostatnio:16 minut
0

ogólnie mógłbys przedstawić zamysł Bo mi się coś tu nie podoba. Szczególnie te pointery na int.


We are the 4p. Existence, as you know it, is over. We will add your biological and technological distinctiveness to our own. Resistance is futile
tajny_agent
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad rok
  • Postów:1340
1
Constantic napisał(a):

Przypisanie dziala bez zarzutu, ale typ "vector<vector<string>>" deklarowany w ciele metody nie jest tozsamy z "typedef std::vector<std::vector<string>> ArrString2D;" :/

Nie masz gdzieś przypadkiem użyte using namespace std?

revcorey napisał(a):
Kopiuj
ArrString2D arrString2D(*rowsNumberPtr, vector<string>(*colsNumberPtr));

Co ty chcesz tu zrobić? masz typ vector<vector<>> i skąd weźmiesz taki konstruktor? Po prostu zrób tak

A co jest z tym nie tak? test


"I love C++. It's the best language in the world right now for me to write the code that i need and want to write"
~ Herb Sutter
RE
zgadzam się z tobą, spojrzałem do specki jest taki konstruktor.
tajny_agent
cpp potrafi nie raz pozytywnie zaskoczyć ;)
CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0
revcorey napisał(a):

ogólnie mógłbys przedstawić zamysł Bo mi się coś tu nie podoba. Szczególnie te pointery na int.

Hmm, zamysl jest taki, ze utworzylem sobie klase do poboru danych konfiguracyjnych roznego typu. Ze wzgledu na poprzednia wersje tablic, klasa ta ma osobna metode do odczytu wymiarow tablic oraz osobna metode to ich odczytu i zapisu w postaci tablicy string (potem te tablice sa konwertowane na odpowiednie typy docelowe w klasach obslugujacych wlasciwe sobie zestawy konfiguracyjne).

Jesli chodzi o te pointery parametrach integer to odnosza sie one do atrybutow wymiarow tablicy tej samej klasy do ktorej nalezy metoda. Oczywiscie na pierwszy rzut oka wydaje sie zbedne przekazywanie atrybotow klasy do metody ktora rowniez do tej samej klasy nalezy - nie jestem jednak pewien czy nie bede uzywal tej funkcji w przypadku danych innych niz konfiguracyjne zatem postanowilem pozostawic ja w postaci odrobine bardziej uniwersalnej. Nadal pozostaje kwestia pointerow - chyba dlatego zeby miec pewnosc ze za kazdym razem odwoluje sie do odpowiednich wartosci jednak co tu duzo mowic - jeszcze troche kodu "uplynie" zanim tak naprawde zaczne nimi swobodnie operowac.

CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0
tajny_agent napisał(a):
Constantic napisał(a):

Przypisanie dziala bez zarzutu, ale typ "vector<vector<string>>" deklarowany w ciele metody nie jest tozsamy z "typedef std::vector<std::vector<string>> ArrString2D;" :/

Nie masz gdzieś przypadkiem użyte using namespace std?

No wlasnie o to chodzi, ze tak. Dzieki temu kilka innych deklaracji method zamiast "std::string" strkocilem do "string". Jak sie domyslam nie zadales tego pytania ot tak sobie i mozliwe, ze masz w zwiazku z tym cos do dodania :/ ...

tajny_agent
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad rok
  • Postów:1340
0

Zainteresował mnie ten typedef i niekonsekwencja z przedrostkiem std

Kopiuj
typedef std::vector<std::vector<string>> ArrString2D;

Ale w sumie VS bez problemu mi taki misz-masz przepuścił, więc mój strzał raczej chybiony ;)


"I love C++. It's the best language in the world right now for me to write the code that i need and want to write"
~ Herb Sutter
RE
  • Rejestracja:ponad 18 lat
  • Ostatnio:16 minut
0

Hmm, zamysl jest taki, ze utworzylem sobie klase do poboru danych konfiguracyjnych roznego typu.

czy możemy użyć std::map w w stylu std::map<string,string> gdzie jedno to parametr drugie wartość albo nawet std::vector<std::pair<string,string>> albo nawet std::tuple(jest jeszcze std::variant w c++17) w ostatecznej ostateczności jeśli jest taka potrzeba? Przejrzyj to.
Więcej później bo jestem zajęty. :)


We are the 4p. Existence, as you know it, is over. We will add your biological and technological distinctiveness to our own. Resistance is futile
edytowany 2x, ostatnio: revcorey
RE
  • Rejestracja:ponad 18 lat
  • Ostatnio:16 minut
0

esli chodzi o te pointery parametrach integer to odnosza sie one do atrybutow wymiarow tablicy tej samej klasy do ktorej nalezy metoda. Oczywiscie na pierwszy rzut oka wydaje sie zbedne przekazywanie atrybotow klasy do metody ktora rowniez do tej samej klasy nalezy - nie jestem jednak pewien czy nie bede uzywal tej funkcji w przypadku danych innych niz konfiguracyjne zatem postanowilem pozostawic ja w postaci odrobine bardziej uniwersalnej. Nadal pozostaje kwestia pointerow - chyba dlatego zeby miec pewnosc ze za kazdym razem odwoluje sie do odpowiednich wartosci jednak co tu duzo mowic - jeszcze troche kodu "uplynie" zanim tak

std::vector rozszerza się automatycznie. Oczywiście jak uprzednio zarezerwujesz pamięć to może nie być albo może być mniej alokacji później.Proste prymitywne typy jak int czyli tu rozmiar tablicy/vectora przekazuj przez wartość, taki zapis foo(int size) zostanie zoptymalizowany przez kompilator(użycie referencji mogło by tu sprawę pogorszyć, jeśli idzie o proste typy). A jak już tak chcesz przekazać takie rzeczy przez wskaźnik czy referencje pamiętaj o const.

No wlasnie o to chodzi, ze tak. Dzieki temu kilka innych deklaracji method zamiast "std::string" strkocilem do "string". Jak sie domyslam nie zadales tego pytania ot tak sobie i mozliwe, ze masz w zwiazku z tym cos do dodania :/ ...

Kolizja nazw np. jak będziesz chciał użyć innej biblioteki stringów?


We are the 4p. Existence, as you know it, is over. We will add your biological and technological distinctiveness to our own. Resistance is futile
edytowany 3x, ostatnio: revcorey
CO
CO
  • Rejestracja:prawie 7 lat
  • Ostatnio:prawie 5 lat
  • Postów:92
0
revcorey napisał(a):

std::vector rozszerza się automatycznie. Oczywiście jak uprzednio zarezerwujesz pamięć to może nie być albo może być mniej alokacji później.

Wlasnie ze wzgledu na te koniecznsc wielokrotnych alokacji zdecydowalem sie najpierw szybciutko odczytac rozmiary tablicy, a nastepnie zadeklarowac ja jednznacznie (dynamicznie) w celu przypisania danych. Fakt to podwojna robota, ale pliki konfiguracyjne do obslugi sa malenkie i mam ich ok 7 sztuk.

revcorey napisał(a):

Proste prymitywne typy jak int czyli tu rozmiar tablicy/vectora przekazuj przez wartość, taki zapis foo(int size) zostanie zoptymalizowany przez kompilator(użycie referencji mogło by tu sprawę pogorszyć, >jeśli idzie o proste typy). A jak już tak chcesz przekazać takie rzeczy przez wskaźnik czy referencje pamiętaj o const.

Tu mnie masz, tego nie bylem swiadomy, dzieki.

revcorey napisał(a):

Kolizja nazw np. jak będziesz chciał użyć innej biblioteki stringów?

To tez prawda, chociaz w moim przypadku a zwlaszcza w przypadku aplikacji ktora pisze to raczej malo prawdopodobne - jesli chodzi o programowanie jestem "prymitywista" :) z wyboru i za wszelka cene staram sie opierach na jak najbardziej podstawowych rozwiazaniach.

Bardzo Ci dziekuje za wskazowki i sugestie.

RE
  • Rejestracja:ponad 18 lat
  • Ostatnio:16 minut
0

lasnie ze wzgledu na te koniecznsc wielokrotnych alokacji zdecydowalem sie najpierw szybciutko odczytac rozmiary tablicy, a nastepnie zadeklarowac ja jednznacznie (dynamicznie) w celu przypisania danych. Fakt to podwojna robota, ale pliki konfiguracyjne do obslugi sa malenkie i mam ich ok 7 sztuk.

To jest przerost formy nad treścią według mnie ze względu że to będą małe vectory, nie ma w standardzie tego określonego ale zazwyczaj startowe capacity to 0, tyle że później vector potrafi sobie na zapas zaalokować aby uniknąć zbyt wielu odwołań menadżera pamięci.

To tez prawda, chociaz w moim przypadku a zwlaszcza w przypadku aplikacji ktora pisze to raczej malo prawdopodobne - jesli chodzi o programowanie jestem "prymitywista" :) z wyboru i za wszelka cene staram sie opierach na jak najbardziej podstawowych rozwiazaniach.

To jest zajebisty błąd. Po to porobiono te mapy, vectory i inne w std czy w języku jakieś r-wartości żeby z tego korzystać. Te kontenery czy algorytmy std też są pisane tak żeby być dość wydajne, oczywiście nie zawsze to będzie najwydajniejsze rozwiązanie ze względu na mnogość sytuacji. Co więcej jak zaczniesz budować jakieś swoje własne cuda możesz się pomylić albo porobi się takie spageti że spadnie ci wydajność. jechanie na dziś dzień na gołych wskaźnikach bez wyraźnego powodu to błąd. C++ to nie java script i frontend że co byś na tym nie napisał będzie mulić.

edit:
Polecam ci lekturę clean code.
poczytaj też o clang-tidy.


We are the 4p. Existence, as you know it, is over. We will add your biological and technological distinctiveness to our own. Resistance is futile
edytowany 2x, ostatnio: revcorey
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
1

Bezpiecznie jest założyć, że w temacie struktur danych typu wektor, hashmapa itd. kompilator wie co robi. Ba, bezpiecznie jest założyć, że sami nie wiemy. Na CodeDive w 2015 bodajże ktoś robił zestawienie memset vs std::fill vs pętla i wyszło, że nawet dla małego embedded typu AVR STL potrafi być o parę procent szybszy jeżeli ten kod ma być czytelny. Czyli jak zwykle: „(jeszcze) nie optymalizuj”. Z mojego doświadczenia: raz wygrałem z kompilatorem walkę „C kontra C++”, tzn przepisanie wszystkiego w C pomogło, ale i tak bez dodatkowych flag kompilacji i atrybutów funkcji się nie obeszło. Ugraliśmy jedną czy dwie instrukcje asemblerowe, czyli w sumie może 8 bajtów objętości kodu (pewnie mniej, już nie pamiętam) w stosunku do 1kB całości. Tyle, że to było gotowe urządzenie z ATTiny13 z flashem 1kB zajętym w 95% i z całą odpowiedzialnością pisałem kod tak, żeby się zmieścił, nie żeby był czytelny. Piszesz na takie urządzenia? Nawet jeśli, to zmierz, potem optymalizuj, inaczej tylko powtarzasz mitologię.

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)