<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>m1chu.eu - another devblog &#187; Programowanie</title>
	<atom:link href="http://m1chu.eu/category/programowanie/feed/" rel="self" type="application/rss+xml" />
	<link>http://m1chu.eu</link>
	<description>we live, as we dream... alone - another devblog</description>
	<lastBuildDate>Fri, 25 Jun 2010 22:04:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Proste uruchamianie i zamykanie zewnętrznych programów w Visual C++/C# .NET&#8230;</title>
		<link>http://m1chu.eu/2008/09/06/proste-uruchamianie-i-zamykanie-zewnetrznych-programow-w-visual-c-net/</link>
		<comments>http://m1chu.eu/2008/09/06/proste-uruchamianie-i-zamykanie-zewnetrznych-programow-w-visual-c-net/#comments</comments>
		<pubDate>Sat, 06 Sep 2008 00:11:27 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Visual C#]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[uruchamianie programów]]></category>
		<category><![CDATA[visual c++]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[winapi]]></category>

		<guid isPermaLink="false">http://m1chu.eu/?p=52</guid>
		<description><![CDATA[W czasach kiedy rozpoczynałem swoją zabawę z C++ (a w gruncie rzeczy żadnym wielkim wygą nie jestem ;]) takie rzeczy starano się robić w WinAPI z wykorzystaniem ShellExecute, czy SendMessage. Bo jak sam temat mówi wpis ten będzie dotyczył systemu Windows. Wraz z rozwojem języków i środowisk sporą część tychże funkcji można wykorzystać poprzez łatwiejsze [...]]]></description>
			<content:encoded><![CDATA[<p>W czasach kiedy rozpoczynałem swoją zabawę z <strong>C++</strong> (a w gruncie rzeczy żadnym wielkim wygą nie jestem ;]) takie rzeczy starano się robić w <a target="_blank" href="http://utnij.eu/winapi/"  title="Windows API">WinAPI</a> z wykorzystaniem <a target="_blank" href="http://utnij.eu/shellexecute/"  title="ShellExecute">ShellExecute</a>, czy <a target="_blank" href="http://utnij.eu/sendmessage/"  title="SendMessage">SendMessage</a>. Bo jak sam temat mówi wpis ten będzie dotyczył systemu Windows. Wraz z rozwojem języków i środowisk sporą część tychże funkcji można wykorzystać poprzez łatwiejsze w użyciu zamienniki.</p>
<p><span id="more-52"></span></p>
<p>Tematem dzisiejszego wykładu jest poruszony na pewnym forum problem uruchamiania zewnętrznego programu z aplikacji napisanej w C++ (bonusowo na końcu wpisu zamieszczę także klasę tego typu pisaną w C#, a ponieważ tłumaczenia rozwiązania w obydwu językach by się pokrywały to opis będę opierał na C++). Ponieważ idziemy z duchem czasu, a bodajże chodziło tam o system Windows to postaram się przybliżyć Wam proste i kompleksowe rozwiązanie działające w <strong>Visual C++ .NET</strong>.</p>
<p style="text-align: center;"><img src="http://farm4.static.flickr.com/3287/2830885881_2cf0c2a826.jpg" alt="Pierwszy krok tworzenia nowego projektu" /></p>
<p>Nie będziemy sobie w tym wypadku zaprzątać głowy natywnym Win32. Projekt stworzymy w trybie okienkowym jako Windows Forms. Do dzieła więc! Kolejno po wejściu do środowiska należy w menu wybrać <strong>File (Plik) -> New (Nowy) -> Project&#8230; (Projekt&#8230;)</strong>. W nowym okienku należy wybrać <strong>Visual C++ -> CLR -> Windows Forms Application (Aplikacja Windows Forms)</strong>. Wystarczy jeszcze powyżej ustawić z listy <strong>.NET Framework 2.0</strong> (wyższe wersje też są dozwolone, ale w gruncie rzeczy niepotrzebne dla tego co będziemy starali się osiągnąć), a także na samym dole wybrać nazwę nowego programu (<strong>Name/Nazwa:</strong>, w przykładzie będzie to <strong>process_starter</strong>) i ewentualnie zmienić miejsce zapisu projektu (<strong>Location/Lokacja:</strong>). Niektórych może zdziwić nazwa przykładowego projektu, ale fakt jest taki, że otwieranie i zamykanie programów w naszym przypadku będzie odbywać się w głównej mierze na procesach systemu.</p>
<p style="text-align: center;"><img src="http://farm4.static.flickr.com/3271/2830935887_d266dcb251.jpg" alt="Drugi krok tworzenia nowego projektu" /></p>
<p>Automatycznie został wygenerowany domyślny kod wraz z klasą formularza. Ponieważ projekt całego rozwiązania jest prosty, pozwolicie że zacznę od krótkiego wytłumaczenia części okienkowej. Dla przykładu będziemy potrzebować dwóch <em>textbox&#8217;ów</em> (nazwanych tutaj <strong>filenameValue</strong> i <strong>argsVal</strong>) i jednego <em>button&#8217;a</em> (<strong>makeButton</strong>). Nie wymieniam tu użytych <em>label&#8217;ów</em>, czy <em>progressbar&#8217;a</em>, bo to tylko części estetyczna.</p>
<p style="text-align: center;"><img src="http://farm4.static.flickr.com/3268/2831794806_ff526f0ee3.jpg" alt="Wygląd formatki" /></p>
<p>Teraz możecie kliknąć dwa razy na wspomniany już przycisk i przechodzimy do partii kodu.</p>
<p>Pora więc na trochę teorii, czyli krótki opis jak będziemy wywoływać i niszczyć procesy. Skorzystamy tu z przestrzeni nazw, wraz z klasą przeznaczoną do tego typu rzeczy.</p>
<pre class="brush: cpp;">using namespace System::Diagnostics::Process;</pre>
<p>Poprzez odpowiednie użycie jej elementów i metod możemy bez problemu uruchomić zewnętrzny program, a później go zabić bez wprowadzania dodatkowych danych jak w przypadku użycia WinAPI. Tyle z teoretyzowania.</p>
<p>Kod który stworzymy proponuję podzielić na trzy oddzielne metody, plus jedna obsługująca zdarzenie przyciśnięcia przycisku. Zajmijmy się najpierw dwoma głównymi:</p>
<ul>
<li><strong>runProcess(plik_do_otwarcia, opcjonalne_argumenty_pliku)</strong> pozwalająca na otwarcie programu,</li>
<li><strong>killProcess()</strong> zamykająca proces otwartego programu.</li>
</ul>
<p>W pierwszym z nich przede wszystkim należy wywołać metodę statyczną odpowiadającą za otwarcie pliku. Ponieważ jednak będziemy chcieli go później zamknąć to musimy jej wynik przypisać do zmiennej przechowującej stan procesu. Prócz tego przydałoby się sprawdzać wcześniej czy podana ścieżka do pliku istnieje (z tym wiąże się dodanie przestrzeni nazw <strong>System::IO</strong>). A co za tym idzie typ naszej metody musimy zmienić na logiczny, gdyż będzie zwracała wartość zależną od tego czy w.w. argument jest prawidłowy.</p>
<pre class="brush: cpp;">#using &lt;system.dll&gt; // dodajemy korzystanie z danego rozszerzenia (dla klasy Process i RegEx)

namespace process_starter {
[...]
	using namespace System::Data;
	using namespace System::IO; // przestrzeń nazw dla File::Exists
	using namespace System::Diagnostics; // dodajemy przestrzeń nazw
[...]
	private: System::Windows::Forms::Button^  makeButton;

	private:
		Process^ process; // dodajemy deklarację zmiennej obsługującej stan procesu
[...]
#pragma endregion
		/**
		 * Rozpoczęcie procesu podanego w parametrze proc w wypadku,
		 * gdy plik podany w parametrze istnieje.
		 *
		 * @access:		private
		 * @param:		System::String^		proc
		 * @param:		System::String^		args
		 * @return:		bool
		 */
		bool runProcess(System::String^ proc, System::String^ args)
		{
			if ( File::Exists(proc) ) // sprawdzenie, czy plik istnieje
			{
				process = Process::Start(proc, args); // wywolanie zadanego procesu
				return true;
			}
			return false;
		}
[...]</pre>
<p>Druga metoda opiera się na sprawdzeniu, czy program który wywołaliśmy nie został już czasami zamknięty (np. ręcznie przez użytkownika) i jeśli tak się nie stało na jego zamknięciu. Wszystko zostało opatrzone dodatkowo w wyłapywanie ewentualnych wyjątków. Poniższą funkcję klasy możemy dodać pod tą zajmującą się uruchamianiem.</p>
<pre class="brush: cpp;">
/**
		 * Łagodne zabicie procesu programu wywołanego wcześniej w przypadku
		 * kiedy nie został on zamknięty w międzyczasie przez użytkownika.
		 *
		 * @access:		private
		 **/
		void killProcess()
		{
			try {
				if ( !process-&gt;HasExited ) // sprawdzenie czy proces istnieje
				{
					process-&gt;Refresh(); // pozbycie się scacheowanych informacji o procesie
					process-&gt;CloseMainWindow(); // zamknięcie procesu
					process-&gt;Close(); // zwolnienie zasobów związanych z procesem
				}
			}
			catch ( Exception^ e ) // wyłapanie ewentualnego wyjątku
			{
				MessageBox::Show(&quot;Niespodziewany błąd:\n\n&quot; + e-&gt;Message, &quot;Błąd!&quot;, MessageBoxButtons::OK, MessageBoxIcon::Error);
			}
		}</pre>
<p>Jakby nie patrzeć wszystko co miał poruszać ten wpis zostało już pokazane. Teraz dodatkowo należałoby złożyć to jakoś w całość (czyli nadać ciut życia i funkcjonalności przyciskowi odpowiedzialnemu za interakcję), a także napisać choć podstawowe zabezpieczenia czyniące program &#8220;idiotoodpornym&#8221;. Tutaj pojawia się trzecia metoda która za pomocą wyrażeń regularnych pozwala na sprawdzenie wprowadzonego adresu pliku z wzorcem. Ten kod także wstawiamy w sekcji <strong>private</strong>, tak jak powyższe. Dodatkowo należy także dodać przestrzeń nazwa dla klasy <strong>RegEx</strong>.</p>
<pre class="brush: cpp;">[...]
	using namespace System::Drawing;
[...]
	using namespace System::Text::RegularExpressions; // przestrzeń nazwa wyrażeń regularnych
[...]
		/**
		 * Porównanie ciągu znaków z wprowadzonym wzorcem dzięki wyrażeniom
		 * regularnym.
		 *
		 * @access:		private
		 * @param:		System::String^		string
		 * @param:		System::String^		pattern
		 * @return:		bool
		 */
		bool checkExpression(System::String^ string, System::String^ pattern)
		{
			Regex^ regex = gcnew Regex(pattern); // tworzymy definicję klasy RegEx
			Match^ match = regex-&gt;Match(string); // tworzymy definicję klasy Match
			if ( match-&gt;Value-&gt;Length &gt; 0 ) // sprawdzamy, czy ciąg odpowiada wzorcowi
			{
				return true;
			}
			return false;
		}</pre>
<p>No i ostatecznie kwestia nawigacji. Osobiście proponuję zdefiniowanie zmiennej klasy przetrzymującej stan przycisku (czy ma nastąpić uruchomienie, czy zamknięcie). Wg. tego po sprawdzeniu, czy wpisane dane dostępu do pliku nie są puste lub nie są nieprawidłowe wywołujemy odpowiednio, albo metodę wywołującą plik, albo zamykającą go.</p>
<pre class="brush: cpp;">[...]
	public:
		Form1(void)
		{
			this-&gt;button_mode		= true; // true, jesli uruchamia program, false jesli zabija
[...]
	private:
		bool button_mode; // dodajemy deklarację stanu przycisku
[...]
		private: System::Void makeButton_Click(System::Object^  sender, System::EventArgs^  e)
		{
			/**
			 * Sprawdzenie, czy pole tekstowe odpowiadające za ścieżkę dostępu
			 * do pliku nie jest puste lub nie jest nieprawidłowo wypełnione.
			 * Pola argumentów nie jest sprawdzane, gdyż nie są one wymagane.
			 */
			if ( this-&gt;filenameValue-&gt;Text != &quot;&quot; &amp;&amp; this-&gt;checkExpression(this-&gt;filenameValue-&gt;Text, &quot;(([a-zA-Z]{1}):|)(.*)\\.([a-z0-9A-Z]{1,3})&quot;) == true )
			{
				switch ( this-&gt;button_mode )
				{
					case true:
						// wywołanie metody otwierającej plik
						if ( this-&gt;runProcess(this-&gt;filenameValue-&gt;Text, ( this-&gt;argsVal-&gt;Text != &quot;&quot; ? this-&gt;argsVal-&gt;Text : &quot;&quot; )) == true )
						{
							this-&gt;button_mode = false;
							this-&gt;makeButton-&gt;Text = &quot;Zamknij&quot;;
						}
						else {
							MessageBox::Show(&quot;Plik nie istnieje!&quot;, &quot;Błąd!&quot;, MessageBoxButtons::OK, MessageBoxIcon::Error);
						}
						break;
					default:
						this-&gt;killProcess(); // wywołanie metody zamykającej program
						this-&gt;button_mode = true;
						this-&gt;makeButton-&gt;Text = &quot;Uruchom&quot;;
						break;
				}
			}
			else if ( this-&gt;filenameValue-&gt;Text == &quot;&quot; ) // wyświetlenie ostrzeżenia o niewypełnieniu pola
			{
				MessageBox::Show(&quot;Nie wprowadzono nazwy lub ścieżki pliku!&quot;, &quot;Błąd!&quot;, MessageBoxButtons::OK, MessageBoxIcon::Warning);
			}
			else { // wyświetlenie ostrzeżenia o błędnym wypełnieniu pola
				MessageBox::Show(&quot;Wprowadzono niepoprawną ścieżkę lub nazwę pliku!&quot;, &quot;Błąd!&quot;, MessageBoxButtons::OK, MessageBoxIcon::Warning);
			}
		}</pre>
<p>Teraz wystarczy tylko skompilować kod i uruchomić program. Wykorzystanie jest chyba proste. W jednym polu tekstowym wpisujemy nazwę pliku jeżeli znajduje się on w katalogu aplikacji lub pełną ścieżkę z nazwą pliku w wypadku, gdy znajduje się on w innym folderze. Drugie pole tekstowe (argumentów) jest niewymagane do uzupełnienia. Można tam umieścić &#8220;old schoolowe&#8221; parametry elementu docelowego skrótów, bądź spróbować np. podać adres internetowy do otwarcia w przypadku wywoływania przeglądarki. Należy wspomnieć, że w wypadku podania błędnego parametru klasa <strong>Process</strong> zlekceważy go.</p>
<p>Na koniec kilka przykładowych danych:</p>
<ul>
<li>ścieżka: <strong>c:\windows\explorer.exe</strong>; argumenty: <strong>brak</strong>,</li>
<li>ścieżka: <strong>c:\program files\mozilla firefox\firefox.exe</strong>; argumenty: <strong>http://utnij.eu/</strong></li>
</ul>
<p>PS: zamieszczam gotowy plik <a target="_blank" href="http://6thavenue.org/stro/-execs/get_ps_exe.php"  title="Program przykładowy - C++"><strong>exe (kompilowany z C++)</strong></a> i <a target="_blank" href="http://6thavenue.org/stro/-sources/-cpp/get_ps_h.php"  title="Cała klasa C++"><strong>klasa C++</strong></a> składająca się z powyższego kodu. Na życzenie dodaję także <a target="_blank" href="http://6thavenue.org/stro/-execs/get_ps_cs_exe.php"  title="Program przykładowy - C#"><strong>plik wykonywalny (kompilowany z C#)</strong></a> oraz <a target="_blank" href="http://6thavenue.org/stro/-sources/-csharp/get_ps_cs.php"  title="Klasa C#"><strong>klasę pisaną w c#</strong></a> (po ściągnięciu tego pliku jego rozszerzenie należy zmienić z <strong>.h</strong> na <strong>.cs</strong>).</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2008/09/06/proste-uruchamianie-i-zamykanie-zewnetrznych-programow-w-visual-c-net/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Czy pamiętacie Pegasusa?</title>
		<link>http://m1chu.eu/2008/03/29/czy-pamietacie-pegasusa/</link>
		<comments>http://m1chu.eu/2008/03/29/czy-pamietacie-pegasusa/#comments</comments>
		<pubDate>Sat, 29 Mar 2008 01:06:15 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[Projekty]]></category>
		<category><![CDATA[Visual C#]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[emulatory]]></category>
		<category><![CDATA[gry]]></category>
		<category><![CDATA[nes]]></category>
		<category><![CDATA[pegasus]]></category>

		<guid isPermaLink="false">http://m1chu.eu/programowanie/czy-pamietacie-pegasusa</guid>
		<description><![CDATA[Ludzie co to były za czasy :D Kiedy ponad dziesięć lat temu otrzymałem ten &#8220;sprzęcior&#8221; nie spodziewałem się, że pomiędzy długimi godzinami przebieganymi na podwórkach będzie to największy zjadacz czasu mojego dzieciństwa. I jakże wielkim pozytywnym zaskoczeniem kilka dni temu była możliwość pozyskania kilku gier wraz z emulatorami na tą &#8220;platformę&#8221;&#8230;

Z tej strony podziękowania dla [...]]]></description>
			<content:encoded><![CDATA[<p>Ludzie co to były za czasy :D Kiedy ponad dziesięć lat temu otrzymałem ten &#8220;sprzęcior&#8221; nie spodziewałem się, że pomiędzy długimi godzinami przebieganymi na podwórkach będzie to największy zjadacz czasu mojego dzieciństwa. I jakże wielkim pozytywnym zaskoczeniem kilka dni temu była możliwość pozyskania kilku gier wraz z emulatorami na tą &#8220;platformę&#8221;&#8230;</p>
<p><span id="more-37"></span></p>
<p>Z tej strony podziękowania dla <strong>Biedrzola</strong> za ukazanie sprawy i te kilka godzin bez przerwy z stukaniem w klawiaturę w celu przejścia kolejnego &#8220;stage-a&#8221; w Tanku :D</p>
<p>I tak właśnie wpadłem na pomysł, żeby z chaotycznie porozrzucanych po internecie plików zrobić jedną paczkę instalacyjną. Na razie jest to wersja początkowa, nazwijmy ją dla koneserów <strong>alpha</strong>. Wymaga <a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=333325FD-AE52-4E35-B531-508D977D32A6&amp;displaylang=en"  title=".net framework 3.5"><strong>.net framework 3.5</strong></a> i pozwala na odpalenie z poziomu na szybko pisanej przeze mnie aplikacji ponad 150 gier na Pegasusa w trzech różnych emulatorach. Sam program, pisany w <strong>Visual C# .NET</strong> nie uracza masą opcji, ale jeśli będzie zainteresowanie to postaram się go udoskonalić, dodać ciut ustawień, auto-aktualizacji i ściągania nowych gier.<br />
<center></p>
<p style="border: 1px solid #cccccc; padding: 2px; text-align: center; width: 500px; height: 334px;"><img src="http://farm4.static.flickr.com/3239/2842551829_bee7746419_o.png" style="width: 500px; height: 334px;" /></p>
<p></center><br />
Program można do testów i własnej przyjemności w zabawie ściągnąć pod <a target="_blank" href="http://utnij.eu/pgp-1_0alpha/"  title="Ściągnij"><strong>tym</strong></a> adresem. Waga to <strong>13.8MiB</strong>. Wszelkie propozycje, opinie i informację o błędach proszę umieszczać w komentarzach.</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2008/03/29/czy-pamietacie-pegasusa/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Sortowanie bąbelkowe metodą szablonów wektorowych</title>
		<link>http://m1chu.eu/2007/12/01/sortowanie-babelkowe-metoda-szablonow-wektorowych/</link>
		<comments>http://m1chu.eu/2007/12/01/sortowanie-babelkowe-metoda-szablonow-wektorowych/#comments</comments>
		<pubDate>Fri, 30 Nov 2007 23:46:28 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[algorytm]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[sortowanie bąbelkowe]]></category>
		<category><![CDATA[stl]]></category>
		<category><![CDATA[szablony]]></category>
		<category><![CDATA[wektor]]></category>
		<category><![CDATA[win32]]></category>

		<guid isPermaLink="false">http://m1chu.eu/programowanie/sortowanie-babelkowe-metoda-szablonow-wektorowych</guid>
		<description><![CDATA[Dostałem ostatnio jako jeden z wielu kolejne &#8220;ambitne&#8221; zadanie stworzenia programu wieńczącego kolejne laboratoria z informatyki. Mianowicie chodziło o zaimplementowanie algorytmu metodą wektorów biblioteki STL w C++.

Sprawa niby prosta, ale jednak jeśli tak jak chciałem to zrobić ja ktoś stara się zaimplementować algorytm nie tylko dla liczb całkowitych to można łatwo wpaść w zbędny poślizg [...]]]></description>
			<content:encoded><![CDATA[<p>Dostałem ostatnio jako jeden z wielu kolejne &#8220;ambitne&#8221; zadanie stworzenia programu wieńczącego kolejne laboratoria z informatyki. Mianowicie chodziło o zaimplementowanie algorytmu metodą wektorów biblioteki STL w C++.</p>
<p><span id="more-29"></span></p>
<p>Sprawa niby prosta, ale jednak jeśli tak jak chciałem to zrobić ja ktoś stara się zaimplementować algorytm nie tylko dla liczb całkowitych to można łatwo wpaść w zbędny poślizg i uzyskać niepowołany wynik. Postanowiłem utworzyć dwie osobne funkcje wektorowe oparte na tego samego typu tablicach, jedną typu <strong>string</strong>, drugą <strong>float</strong>. Wiem, wiem&#8230; mogłem pobawić się stricte szablonami i nie rozdrabniać się. Nie mniej jednak dla mnie ważny był wtedy tzw. <strong>deadline</strong> zdania pracy, a kopiuj wklej jest na pewno bardziej efektywne pod względem czasu niż samo pisanie ;]</p>
<p style="text-align: center;"><img src="http://farm4.static.flickr.com/3069/2843334214_30b2df8eb9_o.jpg" alt="BubbleSortI" style="width: 666px; height: 336px;" /></p>
<p>Cała moja praca ograniczyła się do optymalizacji gotowego algorytmu, dodania funkcji zmniejszającej litery w stringach w celu uniknięcia wstawienia słowa pisanego dużymi literami, przed tym samym słowem pisanym małymi literami, a także pokazanie przykładowego wykorzystania szablonów. W kodzie wynikowym <strong>float-y</strong> są wyświetlane przed <strong>string-ami</strong>. Domyślnie wyświetla wartości od &#8220;pierwszej&#8221; do &#8220;ostatniej&#8221;.</p>
<p>Mam nadzieję, że kod się komuś przyda. Jeśli ktoś jest zainteresowany opisem dokładniejszym i plikiem źródłowym zapraszam <a href="http://forum.thenet.pl/viewtopic.php?f=62&amp;t=122"  title="Sortowanie Bąbelkowe - thenet.pl" onclick="this.target='_blank';">tutaj</a> (opcjonalne źródło pliku także <a href="http://6thavenue.org/stro/-sources/-cpp/get_bs.php"  title="Opcjonalne źródło" onclick="this.target='_blank';">tutaj</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2007/12/01/sortowanie-babelkowe-metoda-szablonow-wektorowych/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
