<?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>Ahmet Kakıcı &#187; Programlama</title>
	<atom:link href="http://www.ahmetkakici.com/category/programlama/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ahmetkakici.com</link>
	<description>Blog</description>
	<lastBuildDate>Sun, 03 Apr 2011 10:48:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Programlama İpuçları</title>
		<link>http://www.ahmetkakici.com/programlama/programlama-ipuclari/</link>
		<comments>http://www.ahmetkakici.com/programlama/programlama-ipuclari/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 12:37:42 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=271</guid>
		<description><![CDATA[Bugün Jeff Atwood&#8217;un blogunda genelde yazılım geliştirme üzerine yazılan &#8220;En iyi 10 ipucu&#8221; listelerinin listesini gördüm ve yazının hoşuma giden bölümlerini paylaşmak istedim. Maddeler genelde teorik olsa da ders çıkarılabilindiği takdirde pratik ipuçlarından çok daha faydalı olacağına eminim. Orjinali ingilizce olduğundan dolayı mecburen Türkçeye çevirerek yazıyorum. Çeviri yapmak anlam kaybına yol açacağından dolayı orjinalini de [...]]]></description>
			<content:encoded><![CDATA[<p>Bugün Jeff Atwood&#8217;un <a rel="nofollow" alt="Coding Horror" href="http://www.codinghorror.com/blog/">blogunda</a> genelde yazılım geliştirme üzerine yazılan &#8220;En iyi 10 ipucu&#8221; listelerinin listesini gördüm ve yazının hoşuma giden bölümlerini paylaşmak istedim. Maddeler genelde teorik olsa da ders çıkarılabilindiği takdirde pratik ipuçlarından çok daha faydalı olacağına eminim. </p>
<p>Orjinali ingilizce olduğundan dolayı mecburen Türkçeye çevirerek yazıyorum. Çeviri yapmak anlam kaybına yol açacağından dolayı <a rel="nofollow" href="http://www.codinghorror.com/blog/archives/000822.html">orjinalini</a> de okumanızı tavsiye ederim. </p>
<p><a rel="nofollow" href="http://www.codinghorror.com/blog/archives/000584.html"> Jerry Weinberg: The 10 Commandments of Egoless Programming</a><br />
<br />
Egolarınıza yenilmeden çalışabilmek için</p>
<ol>
<li>Hata yapabileceğinizi kabullenin.</li>
<li>Siz ve yazdığınız kod bir değilsiniz.</li>
<li>Ne kadar çok karete bildiğiniz önemli değildir, her zaman sizden iyisi vardır. </li>
<li>Kimseye danışmadan/haber vermeden kodunuzu değiştirip yeniden yazmayın.</li>
<li>Sizden daha az bilgili olan insanlara saygı ve sabır gösterin.</li>
<li>Değişmeyen tek şey değişimin kendisidir.</li>
<li>Gerçek yetki bilgiden gelir, mevkiden değil.</li>
<li>İnandığınız şeyler için savaşın ancak yenilgiyi de kabullenebilin.</li>
<li>Odadaki çocuk <a  rel="nofollow"  href="http://www.codinghorror.com/blog/archives/000080.html">*</a> olmayın.</li>
<li>İnsanları değil kodu eleştrin. Koda karşı değil insanlara karşı nazik olun.</li>
</ol>
<p><span id="more-271"></span></p>
<hr />
<p><a rel="nofollow" href="http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=a76eab63-70f0-48b4-8b75-66c366a651cd">Dare Obasanjo: Top 10 Signs Your Software Project is Doomed</a><br />
<br />
Projenizin çuvallamasına sebep olacak on madde</p>
<ol>
<li>Programın ilk sürümünde çok fazla şey yapmaya çalışmak.</li>
<li>Yeni ve geçerliliği kanıtlanmamış teknolojilere bağlı çalışmak.</li>
<li>Varolan ve çok tutulmuş bir proje ile yarışmaya kalkmak.</li>
<li>Yetersiz kadroya sahip olmak.</li>
<li>&#8220;Karmaşık problemlerin, karmaşık çözümleri vardır&#8221;.</li>
<li>Gerçekçi olmayan proje takvimi/zamanlaması çıkarmak.</li>
<li>Proje kapsamında ani değişiklikler yapmak.</li>
<li>Second System Effect <a rel="nofollow" href="http://en.wikipedia.org/wiki/Second-system_effect">*</a></li>
<li>Giriş stratejisi belirlememek.</li>
<li>Nasıl çözüleceği bilinmeyen sorunlarla uğraşmak.</li>
</ol>
<hr />
<p><a rel="nofollow" href="http://www.arkitectrue.com/the-top-10-things-they-never-taught-me-in-design-school/">Michael McDonough: The Top 10 Things They Never Taught Me in Design School</a><br />
<br />
Tasarım okulunda öğretilmeyen on şey</p>
<ol>
<li>Başarının sadece üçte biri yetenektir.</li>
<li>Yaratıcı mesleklerde %95&#8242;i boş işlerle uğraşılır.</li>
<li>Her şey aynı aynı derecede önemliyse, hiçbir şey gerçekten önemli değildir.</li>
<li>Bir problem üzerinde fazla düşünme.</li>
<li>Bildiklerinle başla ve bilinmeyenleri yok et.</li>
<li>Amacını unutma.</li>
<li>Çevrendeki ağırlıkları attığında genelde dengen bozulur.</li>
<li>Cehenneme giden yol iyi niyetten geçer, hiçbir iyilik cezasız kalmaz.</li>
<li>Her şey &#8216;çıktı&#8217;dan ibarettir.</li>
<li>Dünya sizden ibaret değildir.</li>
</ol>
<hr />
<p>4 &#8211; <a rel="nofollow" href="http://www.taylor.se/blog/2007/03/22/top-ten-things-ten-years-of-professional-software-development-has-taught-me/">Andres Taylor: Top 10 Things Ten Years of Professional Software Development Has Taught Me</a><br />
<br />
On yıllık programlama tecrübesi sonucunda ortaya çıkan on madde</p>
<ol>
<li>Nesnel programlama düşündüğünüzden daha zordur.</li>
<li>Yazılım geliştirmenin zor olan kısmı iletişimdir.</li>
<li>&#8216;Hayır&#8217; demeyi öğrenin.</li>
<li>Her şey aynı aynı derecede önemliyse, hiçbir şey gerçekten önemli değildir.</li>
<li>Bir problem üzerinde fazla düşünme.</li>
<li>İşin derinine inmekten korkmayın ama orada takılıp kalmayın.</li>
<li>Yazılım geliştirme işinin diğer safhaları hakkında da bilgi sahibi olun.</li>
<li>İş arkadaşlarınız en iyi öğretmenlerinizdir.</li>
<li>Her şey &#8216;çalışan&#8217; bir programdan ibarettir.</li>
<li>Some people are assholes. <a rel="nofollow" href="http://www.google.com.tr/search?q=Some+people+are+assholes">*</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/programlama-ipuclari/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>C# ile Görüntü İşleme &#8211; 3</title>
		<link>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-3/</link>
		<comments>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-3/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 09:27:35 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[görüntü işleme]]></category>
		<category><![CDATA[image processing]]></category>
		<category><![CDATA[kod]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=200</guid>
		<description><![CDATA[İlk iki yazının ardından ( 1 &#8211; 2 ) sonunda üçüncü yazıyı da yazabildim. Bu yazıya sadece morfolojik filtreler kaldı. Diğer yazılara gelen yorumlardan sonra açıklamadan çok koda ihtiyaç olduğu anladım, onun için aşağıda genleşme (dilation) ve aşınma (erosion) işlemini yapan fonksiyonları bulacaksınız. Benim kullandığım genleşme ve aşınma maskeleri en basit olanları. Siz kendi maskelerinizi [...]]]></description>
			<content:encoded><![CDATA[<p>İlk iki yazının ardından ( <a title="C# ile Görüntü İşleme - 1" href="http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-1/" target="_self">1</a> &#8211; <a title="C# ile Görüntü İşleme - 2" href="http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-2/" target="_self">2</a> ) sonunda üçüncü yazıyı da yazabildim. Bu yazıya sadece morfolojik filtreler kaldı. Diğer yazılara gelen yorumlardan sonra açıklamadan çok koda ihtiyaç olduğu anladım, onun için aşağıda genleşme (dilation) ve aşınma (erosion) işlemini yapan fonksiyonları bulacaksınız. Benim kullandığım genleşme ve aşınma maskeleri en basit olanları. Siz kendi maskelerinizi if koşulu içine yazarak dilediğiniz gibi kullanabilirsiniz.</p>
<p>Eğer genleşme ve aşınma hakkında daha fazla bilgi istiyorsanız <a title="Dilation" href="http://homepages.inf.ed.ac.uk/rbf/HIPR2/dilate.htm" target="_blank">Dilation</a> &#8211; <a title="Erosion" href="http://homepages.inf.ed.ac.uk/rbf/HIPR2/erode.htm" target="_blank">Erosion</a> bağlantılarını takip edebilirsiniz.<br />
<span id="more-200"></span></p>
<pre class="brush: csharp; title: ; notranslate">
void Dilation()
{
    if (!dilationDone)
    {

        dilationPixelArray = new int[imageWidth, imageHeight];
        for (int i = 1; i &lt; imageWidth - 1; i++)
        {
            for (int j = 1; j &lt; imageHeight - 1; j++)
            {
                if (binaryPixelArray[i, j] == 255)
                {
                    dilationPixelArray[i - 1, j] = 255;
                    dilationPixelArray[i, j - 1] = 255;
                    dilationPixelArray[i, j + 1] = 255;
                    dilationPixelArray[i + 1, j] = 255;
                }
            }
        }
    }
    else
    {
        int[,] tempArray = new int[imageWidth, imageHeight];
        Array.Copy(dilationPixelArray, tempArray, imageWidth * imageHeight);
        for (int i = 1; i &lt; imageWidth - 1; i++)
        {
            for (int j = 1; j &lt; imageHeight - 1; j++)
            {
                if (tempArray[i, j] == 255)
                {
                    dilationPixelArray[i - 1, j] = 255;
                    dilationPixelArray[i, j - 1] = 255;
                    dilationPixelArray[i, j + 1] = 255;
                    dilationPixelArray[i + 1, j] = 255;
                }
            }
        }
    }

}
void Erosion()
{
    if (!erosionDone)
    {
        erosionPixelArray = new int[imageWidth, imageHeight];
        for (int i = 1; i &lt; imageWidth - 1; i++)
        {
            for (int j = 1; j &lt; imageHeight - 1; j++)
            {
                if (binaryPixelArray[i, j] == 255)
                {
                    if (binaryPixelArray[i, j - 1] == 0 ||
                        binaryPixelArray[i - 1, j] == 0 ||
                        binaryPixelArray[i + 1, j] == 0 ||
                        binaryPixelArray[i, j + 1] == 0
                        )
                    {
                        erosionPixelArray[i - 1, j] = 0;
                        erosionPixelArray[i, j - 1] = 0;
                        erosionPixelArray[i, j + 1] = 0;
                        erosionPixelArray[i + 1, j] = 0;
                        erosionPixelArray[i, j] = 0;
                    }
                    else
                    {
                        erosionPixelArray[i, j] = binaryPixelArray[i, j];
                    }
                }
                else
                {
                    erosionPixelArray[i, j] = binaryPixelArray[i, j];
                }
            }
        }
    }
    else
    {
        int[,] tempArray = new int[imageWidth, imageHeight];
        Array.Copy(erosionPixelArray, tempArray, imageWidth * imageHeight);
        for (int i = 1; i &lt; imageWidth - 1; i++)
        {
            for (int j = 1; j &lt; imageHeight - 1; j++)
            {
                if (tempArray[i, j] == 255)
                {
                    if (tempArray[i, j - 1] == 0 ||
                        tempArray[i - 1, j] == 0 ||
                        tempArray[i + 1, j] == 0 ||
                        tempArray[i, j + 1] == 0
                        )
                    {
                        erosionPixelArray[i - 1, j] = 0;
                        erosionPixelArray[i, j - 1] = 0;
                        erosionPixelArray[i, j + 1] = 0;
                        erosionPixelArray[i + 1, j] = 0;
                        erosionPixelArray[i, j] = 0;
                    }
                    else
                    {
                        erosionPixelArray[i, j] = tempArray[i, j];
                    }
                }
                else
                {
                    erosionPixelArray[i, j] = tempArray[i, j];
                }
            }
        }
    }
}
</pre>
<p>Bundan önceki yazılardaki yapıyı kullandığınızı varsayarak yukarıdaki iki fonksiyonu aşağıdaki şekilde çağırmanız gerekli. Bu fonksiyonların yaptığı iş ise eğer resim ikili seviyeye indirgenmemişse (siyah-beyaz) önce bu işlemi yapmak. Tabii ikiliye çevirmek için herhangi bir eşik değeri belirlenmemişse otsu fonksiyonunu çağırarak önce bir eşik değeri hesaplatıyoruz. Binary fonksyionu ise 0-255 arasındaki parametreyi eşik değeri olarak kullanarak resmi ikili seviyeye indirgiyor, parametrenin 256 olması ise otsu ile hesaplanan eşik değerini alması içindir.</p>
<pre class="brush: csharp; title: ; notranslate">
public void ShowDilation()
{
    if (!dilationDone)
    {
        if (!binaryDone)
        {
            if (otsuValue == 0)
                Otsu();
            Binary(256);
        }
        Dilation();
        dilationDone = true;
    }
    else
    {
        Dilation();
    }
    SetImage(ref dilationPixelArray);
}

public void ShowErosion()
{
    if (!erosionDone)
    {
        if (!binaryDone)
        {
            if (otsuValue == 0)
                Otsu();
            Binary(256);
        }
        Erosion();
        erosionDone = true;
    }
    else
    {
        Erosion();
    }
    SetImage(ref erosionPixelArray);
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-3/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Java Soket Programlama &#8211; NetBeans Projesi</title>
		<link>http://www.ahmetkakici.com/programlama/java-soket-programlama-netbeans-projesi/</link>
		<comments>http://www.ahmetkakici.com/programlama/java-soket-programlama-netbeans-projesi/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 11:01:32 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[socket]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=193</guid>
		<description><![CDATA[Daha önceden detaylı açıklamasını yaptığım programın kaynak kodlarını vermiştim ancak o kodlarda ide tarafından oluşturulan bölümler mevcut değildi. Bugün netbeans kurduktan sonra eski projeleri de su yüzüne çıkardım ve paylaşıma sunuyorum. İndireceğiniz arşivin içinde serverGUI &#8211; odev &#8211; odevx klasörleri mevcut. odevx istemci tarafının kodlarının olduğu klasör, odev ise istemci tarafına ait proje klasörü. serverGUI [...]]]></description>
			<content:encoded><![CDATA[<p>Daha önceden detaylı açıklamasını <a href="http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/" target="_self">yaptığım</a> programın kaynak kodlarını vermiştim ancak o kodlarda ide tarafından oluşturulan bölümler mevcut değildi. Bugün netbeans kurduktan sonra eski projeleri de su yüzüne çıkardım ve paylaşıma sunuyorum.</p>
<p>İndireceğiniz arşivin içinde <strong>serverGUI</strong> &#8211; <strong>odev</strong> &#8211; <strong>odevx</strong> klasörleri mevcut. <strong>odevx </strong>istemci tarafının kodlarının olduğu klasör, <strong>odev</strong> ise istemci tarafına ait proje klasörü. <strong>serverGUI</strong> ise adından da anlaşılabileceği gibi sunucuya ait proje klasörü. <strong>serverGUI </strong>klasörü altıntaki<strong> dist </strong>klasöründe ise projeye ait jar dosyası mevcut, dilerseniz sunucuyu direk olarak bu dosyadan başlatabilirsiniz.</p>
<p>Aşağıda kendi kendime yaptığım konuşmaya ait iki istemci  ve sunucuya ait pencere görüntüsü mevcuttur. Arayüz konusunda çok da yetenekli olmadığım için olabildiğince basit bir şekilde bıraktım.</p>
<p>İndirmek için <a title="İndir beni!" href="http://ahmetkakici.com/dosyalar/java-socket.rar" target="_self">tıklayın</a>, umarım işinize yarar.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/java-soket-programlama-netbeans-projesi/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Tarayıcı ve Sürümünü Belirleme</title>
		<link>http://www.ahmetkakici.com/programlama/tarayici-ve-surumunu-belirleme/</link>
		<comments>http://www.ahmetkakici.com/programlama/tarayici-ve-surumunu-belirleme/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 10:01:03 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=141</guid>
		<description><![CDATA[Tarayıcı pazarında firmalar ve sürümler arttıkça tasarımcıların işi de günden güne zorlaşıyor. X tarayıcısında sorunsuz görünen bir tasarım Y tarayıcısı tarafından yorumlanınca istenmedik sonuçlar verebiliyor bunun içinde tarayıcıya özel tasarımlar yazmak veya kullanıcıyı uyarmak gerekiyor. Genelde sunucu taraflı kod yazdığım için beni pek ilgilendirmeyen bu sorunu son zamanlarda javascript ve az da olsa css ile [...]]]></description>
			<content:encoded><![CDATA[<p>Tarayıcı pazarında firmalar ve sürümler arttıkça tasarımcıların işi de günden güne zorlaşıyor. X tarayıcısında sorunsuz görünen bir tasarım Y tarayıcısı tarafından yorumlanınca istenmedik sonuçlar verebiliyor bunun içinde tarayıcıya özel tasarımlar yazmak veya kullanıcıyı uyarmak gerekiyor. Genelde sunucu taraflı kod yazdığım için beni pek ilgilendirmeyen bu sorunu son zamanlarda javascript ve az da olsa css ile uğraştığım için ben de yaşadım ve internette tarayıcı belirlemek için yazılan hazır bir kod bulmak için hemen google&#8217;a doğru yol aldım. Derdimi google&#8217;a anlatamamdan olsa gerek tam olarak aradığımı bulamadım ve aşağıdaki kod ortaya çıktı. Benim gibi google&#8217;a başvurup aradığını bulamayanlar için de paylaşayım dedim. Aşağıdaki kod kullanılan tarayıcının adını ve sürümünü bulmakta. Bana sürüm numarasının ilk hanesi gerektiği için sadece ilk haneyi aldım, düzenli ifadeyi kendinize göre ayarlayıp istediğiniz userAgent bilgisini alabilirsiniz.</p>
<p><span id="more-141"></span></p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script&gt;
var application = navigator.appName;
var agent = navigator.userAgent;
var browser;
var version;

if (application == 'Microsoft Internet Explorer'){
	var patternIE = &quot;MSIE ([0-9])&quot;;
	if (RegExp(patternIE).exec(agent) != null){
		browser = &quot;Microsoft Internet Explorer&quot;;
		version = RegExp.$1;
	}
}
else if (application == 'Netscape'){
	var patternFF = &quot;Firefox/([0-9])&quot;;
	var patternCH = &quot;Chrome/([0-9])&quot;;
	if (RegExp(patternFF).exec(agent) != null){
		browser = &quot;Mozilla Firefox&quot;;
		version = RegExp.$1;
	}
	else if (RegExp(patternCH).exec(agent) != null){
		browser = &quot;Google Chrome&quot;;
		version = RegExp.$1;
	}
}
else if (application == 'Opera'){
	var patternOP = &quot;Opera/([0-9])&quot;;
	if (RegExp(patternOP).exec(agent) != null){
		browser = &quot;Opera&quot;;
		version = RegExp.$1;
	}
}
alert (browser+'  '+ version);
&lt;/script&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/tarayici-ve-surumunu-belirleme/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hangi Programlama Dilini Öğrenelim?</title>
		<link>http://www.ahmetkakici.com/programlama/hangi-programlama-dilini-ogrenelim/</link>
		<comments>http://www.ahmetkakici.com/programlama/hangi-programlama-dilini-ogrenelim/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 11:17:55 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=135</guid>
		<description><![CDATA[İnternette programlama üzerine yazılan çizilen forumların ve sitelerin en gözde muhabbetlerinden biridir bu; hangi dili öğrenmeliyim? Bu sitelerdeki yazıları takip ediyorum da bazen o kadar ilginç şeyler yazılıyor ki soran kişi de sorduğunu pişman olabiliyor. Dil seçimi yanında bazen de dilleri mukayese edip duruyorlar; asp &#8211; php, java &#8211; .net , vs gibi diller onlarca [...]]]></description>
			<content:encoded><![CDATA[<p>İnternette programlama üzerine yazılan çizilen forumların ve sitelerin en gözde muhabbetlerinden biridir bu; hangi dili öğrenmeliyim? Bu sitelerdeki yazıları takip ediyorum da bazen o kadar ilginç şeyler yazılıyor ki soran kişi de sorduğunu pişman olabiliyor. Dil seçimi yanında bazen de dilleri mukayese edip duruyorlar; asp &#8211; php, java &#8211; .net , vs gibi diller onlarca kez kez karşılaştırılmış ve karşılaştırılmaya da devam edecektir.</p>
<p>Aslında hangi dili öğreneceğini veya hangi dilin iyi olduğunu bulması çok kolay. Bunun cevabı tam olarak dili öğrenmek isteyen kişilerde saklı ama malesef bu soruyu kendilerine sormak yerine başkalarına soruyorlar.</p>
<p><span id="more-135"></span>Bir bebek düşünün Türkiye toprakları üzerinde dünyaya gelmiş. Gelmiş ama ne konuşması var ne okuması ne de yazması. Sonra çevresinden görüyor bakıyor ki türkçe oldukça popüler bir dil, öğrenmeye başlıyor. Sorgulama var mı? Yok. Tereddüt var mı ? Yok. Peki bu çocuğun çevresinde onlarca dil bilen kişi olsaydı ne olacaktı? İşte o zaman sorgulamaya başlayacak; hangi dili öğrenmeliyim? Ama asıl soracağı a veya b bu dili neden öğrenmeliyim olmalıdır..</p>
<p>Bu bebeğimiz ömrü boyunca Türkiye sınırları içinde yaşayacak ise başlangıç için ne ingilizce ne fransızca öğrenmesinin bir anlamı yoktur. Türkiye&#8217;de yaşayacağı sonucunu çıkarttıktan sonra dil öğrenmeye karar verirse hiçbir sorun yaşamadan dilini öğrenir ve kullanır. Ancak eğer bu sonucu çıkarmadan acaba ne öğreneyim diye sağına soluna sorular sormaya başlarsa işler karışıyor.</p>
<p>Kimileri gelip ingilizce öğrenmelisin diyor. Sebep? Evrensel bir dildir, herkes onu bilir ve bilmeyen iş/ekmek bulamaz. O sırada başka biri geliyor ve diyor ki; fransızca öğren. Sebep? Kibar bir dilmiş, kulağa hoş geliyormuş hatta kadınlar bayılıyormuş! Kimisi hemen itiraz ediyor; çince öğren, diyor. Neden ? Efendim Çin gelecek yüzyıl içinde çok büyüyecekmiş, dünya devi olacakmış ve şimdi çok popüler olmasa da ileride ortalığı kasıp kavuracakmış.</p>
<p>Bizim bebeğin epey kafası karışacak sanırım. Zira Türkiye sınırları dışına çıkmayacak olmasına rağmen ve hatta hayatı boyunca herhangi bir yabancı ile konuşma fırsatı bile olmayacakken kafasına onlarca şey yığılıyor. Sonra her birinden azar azar öğrenip abidik kubidik konuşuyor.</p>
<p>Olması gereken ise hayat boyunca yaşayabileceğiniz şeyleri göz önüne alarak bir dil öğrenmek. Benzetmeleri bırakıp biraz programlama tarafına dönecek olursak örneğin web programlama ile uğraşmayı isteyen bir kişiye C++ öğren demenin bir anlamı yoktur. Kafasına koyduğu iş web programlama ise öncelikle oturup bu işi yapabileceği dilleri çıkartıp artılarını ve eksilerini çıkarması gerekir, daha sonra karşısında oluşan artı ve eksilere göre seçimini yapması daha kolay olur. Bu noktada yine forumlara yazıp sorabilir tabii ki. Benim bu sebeplerden dolayı şu dillerden birini öğrenemem gerekli, elimdekiler bunlar ve yapacaklarım da şunlar. İşte bu aşamadan sonra çok daha mantıklı cevaplar gelecektir.</p>
<p>Kimin söylediğini bilmediğim bir söz ile bu yazıya da son vereyim. Nereye gideceğini bilmiyorsan hangi yoldan gittiğinin hiçbir önemi yoktur.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/hangi-programlama-dilini-ogrenelim/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Java ile Sohbet Programı</title>
		<link>http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/</link>
		<comments>http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 20:49:17 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[socket]]></category>
		<category><![CDATA[tcp]]></category>
		<category><![CDATA[udp]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=132</guid>
		<description><![CDATA[Sonunda uzun zamandır ertelediğim bu yazıyı da yayınladım ve kafamdan sildim. Aşağıda göreceğiniz kodlar basit bir sohbet programının kodlarıdır. Ayırca java&#8217;da soket programlama için de bir örnek teşkil etmektedir. Programı NetBeans ile yazdım ve NetBeans tarafından otomatik olarak eklenen kodlar aşağıda yer almamaktadır. Kodları ve programın işleyişini daha iyi anlayabilmeniz için bir takım terimleri ve [...]]]></description>
			<content:encoded><![CDATA[<p>Sonunda uzun zamandır ertelediğim bu yazıyı da yayınladım ve kafamdan sildim. Aşağıda göreceğiniz kodlar basit bir sohbet programının kodlarıdır. Ayırca java&#8217;da soket programlama için de bir örnek teşkil etmektedir. Programı NetBeans ile yazdım ve NetBeans tarafından otomatik olarak eklenen kodlar aşağıda yer almamaktadır.</p>
<p>Kodları ve programın işleyişini daha iyi anlayabilmeniz için bir takım terimleri ve yapıları bilmeniz gerektiğini düşünerekten öncelikle bu bilgileri verelim.</p>
<p><strong>Protokol Nedir?</strong></p>
<p>Herhangi bir ağ içerisinde bulunan cihazların birbirleriyle haberleşmeleri için bellirli protokoller tanımlanmıştır. Bu protokoller sayesinde kullanıcılar alt yapıdaki detaylarla uğraşmadan veri alışverişini gerçekletirebilir.<span id="more-132"></span></p>
<p>Farklı amaçlar için farklı protokoller geliştirilmiştir. Bu farklı protokollerin birbirlerine göre üstünlük ve zayıflıkları vardır. Kullanım alanına göre doğru protokol seçilmelidir.</p>
<p>Yaztığım programda User Datagram Protokol  &#8211; UDP protokolünü kullandım.  UDP protokolü veri iletişimini bağlantı kurmaksızın paketler gönderir. Bağlantı kurulmadığından dolayı protokolden mesajın iletildiğine dair herhangi bir bilgi edinilemez. Bu tip bir onay sistemi kullanıcı tarafından isteğe bağlı olarak ayrıca yazılmalıdır. UDP’de gönderilen paketlerin herhangi bir sıra numarası ve sırayla ulaşma garantisi de yoktur. Bu tip özellikler için ekstra başlık bigileri gerekmektedir, UDP bu başlık bilgilerini içermediğinden başlık bilgisi de diğer protokllere göre (ör:TCP) daha küçüktür. Başlık bilgilerinin küçük olması sayesinde UDP daha az bant genişliğine ihtiyaç duyar. Bu avantajından dolayı gerçek zamanlı ses veya görüntü iletişiminde tercih edilir.</p>
<p><strong>Port Nedir ?</strong></p>
<p>Portlar bir bilgisayarın ağda sahip olduğu IP adresinden dışarıya açılan birbirinden bağımsız kapılar olarak tanımlanabilir. Port numaraları 16bit ile ifade edildiğinden 65536 adet port mevcuttur. Herhangi bir uygulamanın kullanacağı port numarası seçilirken daha önceden başka bir programın bu portu kullanıp kullanmadığına dikkat edilmelidir. Aksi halde iki uygulama da düzgün çalışmayabilir.</p>
<p>UDP protokolünde veri iletişimi yapmak için IP ve PORT ikilisini kullanarak adresleme yapmak gerekir. Bu ikili kullanar bir soket yaratılır ve iletişim soket üzerinden yapılır.</p>
<p><strong>Soket Nedir ?</strong></p>
<p>Soket IP adresi ve Port birleşiminden oluşan uygulamalarda ağ içerisinde bulunan alt düzey ayrıntılarla uğraşmadan veri alışverişi yapmayı sağlayan ve unix sistemlerde bulunan dosya yapısına benzer bir yapıdır.  TCP/IP protokolünde mevcut olan soketler uygulama seviyesinde bağlantıları simgelemeye yarar.</p>
<p>Yaygın olarak kullanılan iki türlü soket yapısı mevcuttur. Bunlardan biri SOCK_STREAM ile tanımlanan ve streaming yapmaya yarıyan soket tipidir. Bu soket yapısında bağlantılı (connection oriented) haberleşme kullanılır. Yani haberleşme sırasında aktif olan bağlantı ve soket yapısı mevcuttur. TCP protokolü SOCK_STREAM tipinde soketler üzerinden haberleşme yapar. Bu soketlerden yapılan iletişim tamamen güvenlidir. Yani yanlış veri iletimi olması durumunda protokolden dolayı sistem kararlı ve doğru veriyi iletene kadar tekrar gönderme/isteme işlemini yapar. Ayrıca bu soketler üzerinden gönderilern verilerin alıcı tarafa da aynı sırayla ulaşacağı garanti edilmiştir. “A” ve “B” datasını içeren iki mesajı gönderdiğimizde alıcı tarafta yine “A” ve “B” sırasıyla alınacağı garanti edilmiştir.</p>
<p>Diğer bir soket türü ise SOCK_DGRAM ile tanımlanan datagram tipi soketlerdir. TCP’ye göre güvensiz veri iletişimi yapar. Bunun nedeni gönderilerecek datayı UDP protokolü üzerinden yollaması ve paketi bir kez ağa bıraktıktan sınra herhangi bir takip işlemi yapmamasıdır. Yani kullanıcıya verinin ulaşıp ulaşmadığına dair herhangi bir bilgi sağlamaz. Buna karşılık alıcıdan onay mesajı yollatarak iletimi biraz daha olsun kararlı hale getirebilinir. Bu soketin tercih edilme sebebi ise stream türünde yayınlardır. Her ne kadar streaming soket “streaming” için daha uygun gibi görünsede datagram tipi soketler bu iş için daha uygundur. Bunun sebebi kayıp paketlerin tekrar yollanması, aşırı başlık bilgisi, çok bant genişliği harcaması, bağlantının sürekli olarak aktif kalması gibi dezavantajlarından dolayı datagram soketler streaming işlemi için tercih edilmektedir.</p>
<p><strong>Paket Nedir ?</strong></p>
<p>UDP ile bağlantısız haberleşme yapıldığından veriler birbirinden bağımsız paketler ile gönderilir. TCP protokolünde bağlantılı haberleşme yapıldığından veri iletişimi başlarken bir bağlantı kurulur ve sürekli olarak bu bağlantı üzerinden haberleşme sağlanır. Veri iletişimi olmasa dahi bağlantı açık kalır. UDP  protokolü için Java dilinde belirlenen paket değişken tipi  Datagram Packet’dir.  Her bir paket içerisinde gönderilecek veri ve paketteki veri miktarını belirten değişkenler vardır. Bunun yanı sıra paketi gönderdiğimiz bilgisayarın IP adresi ve port numarası da pakete dahil edilmelidir.</p>
<p>Gönderici ve alıcı adresleri de UDP paketinin içinde olmasına rağmen bu paketler tek başına iletişim için yeterli değildir. UDP paketleri de ağda iletim için IP protokolünü kullanır. Bundan dolayı her paketin başına IP başlık bilgileri de eklenir. Aşağıdaki şekilde bir IP başlığı ve altında ise UDP paketinin temel yapısı gösterilmiştir:</p>
<p><a class="thickbox" href="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/paket.jpg"><img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/paket.jpg" alt="paket.jpg" /></a></p>
<p><a class="thickbox" href="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/udp.jpg"><img class="ngg-singlepic ngg-center" src="http://www.ahmetkakici.com/wp-content/gallery/java-sohbet/udp.jpg" alt="udp.jpg" /></a></p>
<p><strong>Programın Genel Yapısı</strong></p>
<p>Program sunucu/istemci mimarisine dayanarak çalışmaktadır. İstemci kısmı Applet olarak yazıldı ve web üzerinden sohbet edebilme imkanı sağlamaktadır. Sunucu kısmı ise masaüstü uygulaması olarak yazılmıştır. Sunucu çalışmaya başlar başlamaz ilgili portu dinleyerek gelen paketleri değerlendirerek mesajları istemciler arasında iletmektedir. İstemciler birbirleri arasında direk mesajlaşmak yerine sunucu üzerinden mesajlaşmaktadır. Bundan dolayı istemcilerde diğer istemcilerin adresleri yerine sadece isimleri tutulmaktadır.</p>
<p><strong>İstemci Tarafı</strong></p>
<p>İstemci kodu iki temel sınıftan oluşmaktadır. ClientMsgHandler ve ClientGUI. ClientMsgHandler veri iletim fonksiyonlarını içermektedir. ClientGUI ise arayüzü ve ClientMsgHandler’dan gelen verileri kullanıcıya göstermektedir. ClientMsgHandler thread sınıfını implement ederek oluşturulmuştur. Bu sayede arayüzde herhangi bir takılma olmadan veri iletişim işlemleri eş zamanlı olarak yapılmaktadır.</p>
<p>Programda iki türde istemci vardır. Birincisi sunucu üzerinde çalışan ve web üzerinden hizmet veren istemcidir. Web üzerinden sunucuya bağlanan istemciler için yazılmıştır ve sunucu adresini bilmeksizin her istemci bu sunucuya bağlanabilir. Diğer istemci türünde ise istemci kodu bilgisayara indirilip web tarayıcısı üzerinden local olarak çalıştırılabilir. Bu istemcide ise sunucunun ip adresini de ayrıca bilmek gerekmektedir.</p>
<p><strong>İstemci Tarafındaki Sınıflar ve Fonksiyonları</strong></p>
<p><strong>ClientMsgHandler</strong> sınıfına ait fonksiyonlar:<br />
<strong>Send:</strong>String tipinde tutulan gönderilecek mesajı byte dizisine çevirir. Daha sonra DatagramSocket üzerinden yollamak üzere yeni bir PatagramPacket hazırlayak oluşturulan byte dizsini, alıc adresini ve iletişimde kullanılacak port numarasını da pakete ekler. Son olarak paketi DatagramSocket üzerinden gönderir.</p>
<p><strong>Recieve</strong>: DatagramSocket üzerinden gelen paketi alabilmek için yeni bir DatagramSocket yaratır. Okunan veriyi bu pakete yazdıktan sonra mesaj kısmını byte dizisinden string tipine çevirir. Daha sonra mesajı işlemek üzere ParseMsg ve HandleMsg fonkisyonlarını çağırır.</p>
<p><strong>SetHost</strong>: Parametre olarak host adresini alıp bu adresi InetAddress türüne çevirir.<br />
<strong></strong></p>
<p><strong>BuildMsg</strong>: Parametre olarak aldığı mesaj türüne göre gönderilecek mesajı string olarak oluşturur. String türündeki mesajın formatı aşağıdaki gibidir:<br />
gönderici_adı  &gt; alıcı_adı &gt; mesaj_türü &gt; mesaj_içeriği<br />
Bu yapıda “&gt;” sembolü ayraç olarak kullanılmıştır.<br />
Mesaj türleri ise aşağıdaki şekildedir:</p>
<p><strong>ADD_ME</strong> – Kullanıcı ekleme<br />
<strong>REMOVE_ME</strong> – Kullanıcı silme<br />
<strong>SEND_MSG</strong> – Normal mesaj<br />
<strong>GET_USERS</strong> – Kullanıcı listesi isteği<br />
<strong>ACK_MSG</strong> – Onay mesajı</p>
<p><strong>ParseMsg</strong>: Alınan mesajı “&gt;” ayracına göre bölümleyerek mesajın içeriğini gerekli değişkenlere atar.</p>
<p><strong>HandleMsg</strong>: Parse edilen mesajın türüne bağlı olarak işlemleri gerçekleştirir.  Mesaj türlerine göre yaptığı işlemler aşağıdaki gibidir:<br />
<strong></strong></p>
<p><strong>SEND_MSG</strong>: Gelen mesajı arayüzde göstermek üzere ClientGUI sınıfına gönderir.<strong></strong></p>
<p><strong>REMOVE_ME</strong>: Gelen kullanıcı adını ClientGUI’de gösterilen listeden silmek üzere ClientGUI sınıfına iletir. Aynı zamanda istemcilerin tutulduğu vector yapısından ilgili istemciyi silmesi için RemoveClient fonksiyonuna kullanıcı adını iletir.<strong></strong></p>
<p><strong>ACK_MSG</strong>: Bağlantının kurulduğunu onaylayan bu mesaj alındığı zaman arayüzde gerekli değişiklikler yapılarak mesaj iletimine uygun yapı oluşturulur.<strong></strong></p>
<p><strong>ADD_ME</strong>: Gelen kullanıcı adını istemcilerin tutulduğu vector yapısına ekler ve arayüz sınıfının da bu kullanıcı adını göstermesini sağlar.<strong></strong></p>
<p><strong>GET_USERS</strong>: Kullanıcı isteğinin karşılığı niteliğindedir. İlk  kez bağlantı kuruluduğunda liste alınarak arayüzde gösterilir. Aynı zamanda istemcilerin her birini vector yapısına ekler. Bu mesaj alındıktan sonra bağlantı tamamlanmış ve kullanıcı listesi alınmış olduğundan dolayı mesaj dinleme işlemini başlatacak thread çalıştırılr. Sonsuz bir döngü içinde ilgili port sürekli olarak dinlenir.</p>
<p><strong>Connect</strong>: ClientGUI’den alınan kullanıcı adını içeren bir mesaj ile sunucuya bağlantı isteğini gönderir. Send methodunu çağırarak mesajın iletimini sağlar, daha sonra Recieve methoduyla bağlantı isteğine gelcek cevabı bekler. Cevap gelmeme ihtimaline karşı soket’in bloklanma süresi 2sn olarak ayarlanmıştır. Sunucundan cevap alınırsa veya soket süresi dolarsa bağlantı kurulamadığı ClientGUI’de gösterilir ve soket’in bloklanma süresi tekrar sıfıra setlenir (sonsuz).</p>
<p><strong>Disconnect</strong>: Sunucuylya yapılan bağlantının bitirilmesi isteğini gönderir. Bu sayede bağlantıyı kapatan istemciler diğer istemcilerin listesinden silinecektir. UDP gibi bağlantısız bir iletişim protokolü kullanıldığından dolayı bu işlem gereklidir. Aksi halde sunucu  &#8211; istemci arasında sürekli ping gönderek her iki tarafında hala hatta olduğu kontrol edilmelidir.</p>
<p><strong>GetClientList</strong>: Sunucu ile ilk defa bağlantı kurulduğu zaman varolan istemcilerin listesini almak için gerekli mesajı oluşturup gönderir ve cevabı alır. Kullanıcı listesi alınmadan önce ilgili port ayrı bir thread ile dinlenmediği için bu fonksiyon içinden Recieve fonkisyonu çağrılmıştır.</p>
<p><strong>BuildClientList</strong>:  Sunucu istemciye diğer istemcilerin isim listesini gönderirken isimleri “|” ayracı ile ayırır. HandleMsg fonksiyonu bu ayraça göre gelen veriyi bölerek BuildClientList fonksiyonuna string dizisi olarak iletir. BuildClientList fonksiyonu ise gelen bu diziyi vector yapısına çevirerek kaydeder. Vector yapısı kullanılmasının amacı istemci sayısının dinamik olarak değişmesi ve ClientGUI’de ki listede istemcilerin kolaylıkla gösterilmesidir.</p>
<p><strong>RemoveClient</strong>: Herhangi bir istemci sunucuya ayrıdığını bildirdiğinde sunucu geride kalan bütün istemcilere bu mesajı iletir ve istemciler bu fonksiyon ile ayrılan istemcinin adını vector yapısından ve ClientGUI’de kullanılan listeden siler.</p>
<p><strong>ClientGUI </strong>sınıfına ait fonkisyonlar:</p>
<p><strong>SendMessage</strong>: TextField2’ye girilen mesajı ve JList1’den seçilen kullanıcı adını ClientMsgHandler sınıfına göndererek mesajın sunucuya iletilmesini sağlar.</p>
<p><strong>AddMessage</strong>: ClientMsgHandler tarafından alınan mesajları jTextArea’ya kimden geldiğini göstererek ekler.</p>
<p><strong>UpdateUserList</strong>: Sunucuya herhangi bir istemci bağlandığında veya ayrıldığında arayüzde gösterilen istemci isimlerini yeniler.</p>
<p><strong>SetStatus</strong>: Sunucuya bağlanıp bağlanılmadığını ve mesaj gönderirken hangi kullanıcının seçildiğini jTextFeild3’e yazdırır.</p>
<p><strong>Connect</strong>: Bağlan butonuna basıldığı zaman kullanıcıdan alınan ip adresi (veya host adı) ve kullanıcı adıyla sunucuya bağlanmak için ClientMsgHandler’da bulunan Connect fonksiyonun çağırır.</p>
<p><strong>Destroy</strong>: Kullanıcı tarayıcıyı kapattığı zaman sunucuya bağlantıyı sonlandırma mesajını gönderir.</p>
<p><strong>Sunucu Tarafı </strong></p>
<p>Sunucu işlemleri genel olarak istemcilerin listesini tutmak ve gelen mesajları iletmek üzerine kuruludur.  ClientHandler sınıfı sürekli olarak ilgili portu dinleyerek mesaj iletim işini üstlenmektedir. Onun haricinde serverGUI mesajlaşmaların ve sisteme gelip giden istemcilerin özetini gösteren bir arayüz oluşturmaktadır.</p>
<p><strong>ClientHandler </strong>sınıfına ait fonksiyonlar:<br />
<strong></strong></p>
<p><strong>BuildMsg</strong>: Parametre olarak aldığı mesaj türüne göre gönderilecek mesajı string olarak oluşturur. String türündeki mesajın formatı aşağıdaki gibidir:<br />
gönderici_adı  &gt; alıcı_adı &gt; mesaj_türü &gt; mesaj_içeriği<br />
Bu yapıda “&gt;” sembolü ayraç olarak kullanılmıştır.<br />
Mesaj türleri ise aşağıdaki şekildedir:<br />
<strong></strong></p>
<p><strong>ADD_ME</strong> – Kullanıcı ekleme<br />
<strong>REMOVE_ME</strong> – Kullanıcı silme<br />
<strong>SEND_MSG</strong> – Normal mesaj<br />
<strong>GET_USERS</strong> – Kullanıcı listesi isteği<br />
<strong>ACK_MSG</strong> – Onay mesajı</p>
<p><strong>ParseMsg</strong>:  Alınan mesajı “&gt;” ayracına göre bölümleyerek mesajın içeriğini gerekli değişkenlere atar.</p>
<p><strong>HandleMsg</strong>: Parse edilen mesajın türüne bağlı olarak işlemleri gerçekleştirir.  Mesaj türlerine göre yaptığı işlemler aşağıdaki gibidir:<br />
<strong></strong></p>
<p><strong>SEND_MSG</strong>: Mesaj gönderilecek istemcinin adını clients vector yapısı içinde arar. Bulduğu elemandan adresi alarak mesajı  ilgili istemciye gönderir.  Ayrıca sunucu arayüzünde de mesajı ve kimden kime gönderildiğini yazar.<br />
<strong></strong></p>
<p><strong>REMOVE_ME</strong>:  İstemci sunucudan ayrıldığı zaman client vector yapısı içinden bu istemciyi siler ve diğer tüm istemcilere ilgili istemci adını yollayarak listelerinden silmesini bildirir. Buna ek olarak sunucu arayüzünde de çıkan istemcinin adını yazar.</p>
<p><strong>ADD_ME</strong>: Yeni istemcinin adını ve adresini arayüzde gösterir. Daha sonra istemcilerin tutulduğu vektöre yeni bir istemci sınıfı nesnesi yaratıp ekler. Bundan sonra ise istemciye bağlantının kabul edildiğine dair bir onay mesajı yollar. Yeni gelen kullanıcıya onay mesajı gönderip bağlantıyı kabul ettikten sonra önceden bağlanan istemcilere yeni gelen istemcinin adını gönderir.</p>
<p><strong>GET_USERS</strong>:  Bu mesajdan sonra sunucu mesajı gönderen istemciye o anda bağlı olan istemcilerin isimlerini gönderir. İsimler birbirinden “|” ayracı ile ayrılmıştır.</p>
<p><strong>ServerSend</strong>: Gönderilecek mesajı byte dizisine çevirerek datagram paketi içine koyar ve datagram soketi üzerinden gönderir.</p>
<p><strong>ServerRecieve</strong>: İlgili portu dinleyerek gelen mesajları string tipine çevirir. Ayrıca gönderenin adresini de datagram paketinden çıkararak kaydeder.</p>
<p><strong>NotifyAllClients</strong>:  Belirlenen mesajı o anda bağlı olan istemcilerin hepsine gönderir.</p>
<p><strong>BuildClientList</strong>: Bağlı olan istemcilerin isimlerini bir string’de birleştirerek mesajı gönderilmeye hazır hale getirir.</p>
<p><strong>GetReceiverAddressByName</strong>: Sunucuya gelen mesajlarda sadece gönderilecek istemcinin adı bulunmaktadır. Adresler ise sunucuda tutulan clients vector yapısındadır. Bu fonksiyon mesaj gönderilecek istemcinin adını vector elemanlarıyla karşılaştırıp ilgili adresi bulur.</p>
<p><strong>RemoveClient</strong>: Parametre olarak aldığı kullanıcı adını clients vector yapısında arar ve ilgili istemciyi  vector’den siler. Daha sonra geride kalan istemcilere bu silme işlemini bildirir.</p>
<pre class="brush: java; title: ; notranslate">

/**
*
* @author Ahmet
*/
import java.io.*;
import java.net.*;
import java.util.*;

public class clientMsgHandler extends Thread{

private DatagramSocket socket;
private DatagramPacket giden;
private DatagramPacket gelen;
private InetAddress address;

private int msgType;
private String received;
private String[] parsedMsg;
public String myName;
public String message;
public String receiverName;
public String senderName;

private static final int PORT = 4444;
private static final String MSG_SEPERATOR = &quot;&gt;&quot;;
private static final int ADD_ME=0;
private static final int REMOVE_ME=1;
private static final int SEND_MSG=2;
private static final int GET_USERS=3;
private static final int ACK_MSG = 4;
public clientGUI parent;

public boolean connected = false;
public String hostname;
public String msg2send;
public Vector clients = new Vector();

public clientMsgHandler(String argHostname) throws IOException{
hostname = argHostname;
address = InetAddress.getByName(hostname);
socket = new DatagramSocket();
socket.setSoTimeout(0);
}

@Override
public void run(){
while(true){
try{
Recieve();
socket.setSoTimeout(0);
}catch(Exception e){}
}

}
public void SetHost(String argHostname) throws UnknownHostException{
hostname = argHostname;
address = InetAddress.getByName(hostname);
}
private void Send(){
byte[] buf = new byte[msg2send.length()];
buf = msg2send.getBytes();
giden = new DatagramPacket(buf, buf.length, address, PORT);
try{
socket.send(giden);
}catch(Exception e){}
System.out.println(&quot;Giden mesaj: &quot; + msg2send);
}

public void Recieve(){
byte[] buf = new byte[256];
gelen = new DatagramPacket(buf, buf.length);
try{
socket.receive(gelen);
}catch(Exception e){}
received = new String(gelen.getData(), 0, gelen.getLength());
System.out.println(&quot;Gelen mesaj: &quot; + received);
ParseMsg();
HandleMsg();
}

private void BuildMsg(int argFlag){
msg2send = myName+MSG_SEPERATOR+receiverName+MSG_SEPERATOR+argFlag+MSG_SEPERATOR+message;
}

public void SendMsg(){
BuildMsg(SEND_MSG);
Send();
}

public void ParseMsg(){

try {
parsedMsg = received.split(MSG_SEPERATOR);
senderName = parsedMsg[0];
msgType = Integer.parseInt(parsedMsg[1]);
message = parsedMsg[2];
} catch (Exception exception) {
parent.SetStatus(&quot;Bağlantı kurulamadı.&quot;);
msgType = -1;
message = &quot;&quot;;
}
}

public void Connect(){
try {
message = myName;
receiverName = &quot;Server&quot;;
BuildMsg(ADD_ME);
Send();
socket.setSoTimeout(2000);
Recieve();
socket.setSoTimeout(0);

} catch (SocketException ex) {}
}

public void Disconnect(){
receiverName= &quot;Server&quot;;
BuildMsg(REMOVE_ME);
Send();
connected=false;
}

public void HandleMsg(){
if(msgType==SEND_MSG){
parent.AddMessage(message,senderName);
}
else if(msgType==REMOVE_ME){
RemoveClient(message);
parent.UpdateUserList();
}
else if(msgType==ACK_MSG){
connected=true;
}
else if(msgType==ADD_ME){
clients.add(message);
parent.UpdateUserList();
}
else if(msgType==GET_USERS){
String[] clientList = parsedMsg[2].split(&quot;\\|&quot;);
BuildClientList(clientList);
start();
}
}

public void GetClientList(){
message = myName;
BuildMsg(GET_USERS);
Send();
Recieve();
}

private void BuildClientList(String[] clientList){
clients.removeAllElements();
for (int i = 0; i &lt; clientList.length; i++) {
if(!myName.equalsIgnoreCase(clientList[i].toString()))
clients.add(clientList[i]);
}
}

private void RemoveClient(String argName){
for (int i = 0; i &lt; clients.size(); i++) {
String tmp = (String) clients.elementAt(i);
if (tmp.equals(argName)) {
clients.remove(i);
break;
}

}

}

}
</pre>
<pre class="brush: java; title: ; notranslate">

import java.io.IOException;

/*
* clientGUI.java
*
* Created on 16 Nisan 2008 Çarşamba, 21:26
*/
import java.net.UnknownHostException;
import javax.swing.JOptionPane;

/**
*
* @author  Ahmet
*/
public class clientGUI extends javax.swing.JApplet {

private clientMsgHandler tr;

private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
// Kullanıcı adı girişi
Connect();
}

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// Bağlan butonu
Connect();
}

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// Gönderme işlemi
int selected = jList1.getSelectedIndex();
if(selected&gt;-1)
SendMessage();
jTextField2.requestFocusInWindow();
}

private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {
// Gönderme işlemi
int selected = jList1.getSelectedIndex();
if(selected&gt;-1)
SendMessage();
}

private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {
// Listeden kişi seçildiğinde:
jTextField3.setText(jList1.getSelectedValue().toString());
jButton2.setEnabled(true);
}

private void jTextField1FocusGained(java.awt.event.FocusEvent evt) {
// Kullanıcı adı girişi
if(jTextField1.getText().equalsIgnoreCase(&quot;Kullanıcı Adı&quot;))
jTextField1.setText(&quot;&quot;);
}

private void jTextField4FocusGained(java.awt.event.FocusEvent evt) {
// Server IP
if(jTextField4.getText().equalsIgnoreCase(&quot;Server IP&quot;))
jTextField4.setText(&quot;&quot;);
}

public void SendMessage(){
tr.message = jTextField2.getText();
tr.receiverName = jList1.getSelectedValue().toString();
tr.SendMsg();
AddMessage(tr.message,tr.myName);
jTextField2.setText(&quot;&quot;);
}

public void AddMessage(String argMsg, String argSender){
jTextArea1.append(&quot;\n&quot; + argSender + &quot;:&quot; + argMsg);

}

public void UpdateUserList(){
jList1.removeAll();
jList1.setListData(tr.clients);
}

public void Connect(){
try {
tr.myName = jTextField1.getText();
tr.SetHost(jTextField4.getText());
tr.Connect();
if (tr.connected) {
jList1.setVisible(true);
jTextField2.setVisible(true);
jButton2.setVisible(true);
jTextField1.setEnabled(false);
jTextField4.setEnabled(false);
tr.GetClientList();
jList1.setListData(tr.clients);
jButton1.setEnabled(false);
SetStatus(&quot;Bağlantı Kuruldu&quot;);
}
} catch (UnknownHostException ex) {

}
}

public void SetStatus(String argMsg){
jTextField3.setText(argMsg);
}

}
</pre>
<pre class="brush: java; title: ; notranslate">

class ClientHandler extends Thread{

private static final int PORT = 4444;
private static final int BUFFER_LENGTH = 256;
private static final String MSG_SEPERATOR = &quot;&gt;&quot;;

private static final int ADD_ME=0;
private static final int REMOVE_ME=1;
private static final int SEND_MSG=2;
private static final int GET_USERS=3;
private static final int ACK_MSG = 4;

public Vector clients = new Vector();
protected DatagramSocket socket = null;

String receivedMsg;					// Parse edilmemis mesaj
private String message;					// Mesajin icerigi - yazi
private int msgType;					// Mesaj turu
private String msg2send;				// Gonderilecek mesaj
private SocketAddress receiverAdress;                   // Mesajin gidecegi adres
private SocketAddress senderAddress;                    // Mesajin geldigi adres
private String receiverName;                            // Mesajin gidecegi kisi
private String senderName;                              // Mesaj gonderen kisi
public ServerGUIView parent;

@Override
public void run(){
while(true){
try{
ServerReceive();
ParseMsg();
HandleMsg();
}catch(Exception e){}

}
}

public ClientHandler() throws IOException {
super(&quot;ClientHandler&quot;);
socket = new DatagramSocket(PORT);
}

public void RemoveClient(String argName){
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
if (tmp.clientName.equals(argName)){
clients.remove(i);
break;
}
}
}

public void GetReceiverAddressByName(){
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
if (tmp.clientName.equalsIgnoreCase(receiverName)){
receiverAdress = tmp.clientAddress;
break;
}
}
}
private void BuildClientList(){
message = &quot;&quot;;
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
message += tmp.clientName+&quot;|&quot;;
}

}

private void NotifyAllClients(){
message = senderName;
senderName = &quot;Server&quot;;
for(int i=0;i&lt;clients.size();i++){
Client tmp = (Client)clients.get(i);
if (!tmp.clientName.equalsIgnoreCase(message)){
receiverAdress = tmp.clientAddress;

ServerSend();
}

}
}

private void BuildMsg(int argFlag){
msg2send = senderName+MSG_SEPERATOR+argFlag+MSG_SEPERATOR+message;
}

public void ServerReceive()throws IOException{
byte[] buffer = new byte[BUFFER_LENGTH];
DatagramPacket gelenPaket = new DatagramPacket(buffer, BUFFER_LENGTH);
try{
socket.receive(gelenPaket);
}catch(Exception e){}
receivedMsg = new String(gelenPaket.getData(), 0, gelenPaket.getLength());
senderAddress = gelenPaket.getSocketAddress();
}

public void ServerSend(){
try{
byte[] buffer = new byte[msg2send.length()];
buffer = msg2send.getBytes();
DatagramPacket gidenPaket = new DatagramPacket(buffer, buffer.length, receiverAdress);
socket.send(gidenPaket);
}
catch(Exception e){

}
}

private void ParseMsg(){
String[] parsedMsg = receivedMsg.split(MSG_SEPERATOR);
senderName = parsedMsg[0];
receiverName = parsedMsg[1];
msgType = Integer.parseInt(parsedMsg[2]);
message = parsedMsg[3];
}

public void HandleMsg()throws IOException{
if(msgType==ADD_ME){
parent.AddTextarea(&quot;Yeni kullanici: &quot; + message + &quot;, adresi:&quot; + senderAddress+&quot;\n&quot;);
clients.add(new Client(message,senderAddress));
receiverAdress = senderAddress;
BuildMsg(ACK_MSG);
ServerSend();
BuildMsg(ADD_ME);
NotifyAllClients();
}
else if(msgType==SEND_MSG){
GetReceiverAddressByName();
parent.AddTextarea(senderName + &quot; -&gt; &quot; + receiverName + &quot; mesaj gonderiyor :'&quot; + message + &quot;'\n&quot;);
BuildMsg(SEND_MSG);
ServerSend();
}
else if(msgType==REMOVE_ME){
parent.AddTextarea(senderName + &quot;, bağlantıyı sonlandırdı.\n&quot;);
RemoveClient(senderName);
message = senderName;
BuildMsg(REMOVE_ME);
NotifyAllClients();
}
else if(msgType==GET_USERS){
parent.AddTextarea(senderName+&quot; kullanicisina liste yollaniliyor.\n&quot;);
BuildClientList();
senderName = &quot;Sunucu&quot;;
receiverAdress = senderAddress;
BuildMsg(GET_USERS);
ServerSend();
}
}
}

class Client{
String clientName;
SocketAddress clientAddress;

public Client(String argName,SocketAddress argAddress){
clientName = argName;
clientAddress = argAddress;
}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/java-ile-sohbet-programi/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Yapay Sinir Ağlarına Giriş</title>
		<link>http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/</link>
		<comments>http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 13:37:28 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[Yapay Sinir Aglari]]></category>
		<category><![CDATA[Yazılım]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=123</guid>
		<description><![CDATA[Bitirme ödevim için uğraşmaya başladığım ve tezimde de genişçe yer ayırdığım yapay sinir ağları hakkında tezimden ufak tefek alıntılar yaparak burada paylaşmaya başlıyorum. Tezin tamamını yayınlamak yerine can alıcı noktalarını bir yazı dizisi halinde burada yayınlayacağım. Öncelikle yapay sinir ağlarının ne olduğu ve özellikleri hakkındaki bölüm ile başlamak iyi olur diyerekten yazıma geçiyorum; Yapay Sinir [...]]]></description>
			<content:encoded><![CDATA[<p>Bitirme ödevim için uğraşmaya başladığım ve tezimde de genişçe yer ayırdığım yapay sinir ağları hakkında tezimden ufak tefek alıntılar yaparak burada paylaşmaya başlıyorum. Tezin tamamını yayınlamak yerine can alıcı noktalarını bir yazı dizisi halinde burada yayınlayacağım.</p>
<p>Öncelikle yapay sinir ağlarının ne olduğu ve özellikleri hakkındaki bölüm ile başlamak iyi olur diyerekten yazıma geçiyorum;</p>
<p><span id="more-123"></span></p>
<p><strong>Yapay Sinir Ağlarının Tanımı</strong></p>
<p>Yapay sinir ağları canlılarda bulunan sinir sisteminin çalışmasını elektronik ortama taşımayı hedefleyen bir programlama yaklaşımıdır. Yapay sinir ağlarının da canlılarda olduğu gibi öğrenme, hatırlama ve öğrendiklerini güncelleme gibi yeteneklerinin olması hedeflenmektedir.</p>
<p>Sinir sisteminin davranışlarını kopyalayabilmek için yapısının da kopyalanması gerektiğini düşünen bilim adamları yapay sinir ağlarını modellerken de sinir sisteminin yapısını örnek almışlardır.</p>
<p>Yapay sinir hücrelerinin birbirine bağlanmasıyla oluşan bir yapay sinir ağı öğrenme algoritmalarından herhangi birini kullanarak öğrenme sürecini tamamladığında kullanıma hazır hale gelir. Yapay sinir ağı çalıştığı sürece öğrenme ve bilgilerini güncelleme yeteneğine de sahiptir.</p>
<p><strong>Yapay Sinir Ağlarının Genel Özellikleri</strong></p>
<p>Yapay sinir ağları genel olarak canlı beyninin yapısını gerçekleştirmeyi hedefler. Aşağıdaki işlemleri gerçekleştirebilir:</p>
<ul>
<li>Öğrenme</li>
<li>İlişkilendirme</li>
<li>Sınıflandırma</li>
<li>Genelleme</li>
<li>Tahmin</li>
<li>Özellik belirleme</li>
<li>Optimizasyon</li>
</ul>
<p>Bu işlemleri yapan sinir ağlarının ortak noktası ise bir müdahale yapılmaksızın, elinde bulunan bilgilere göre sonuç üretebilmesidir.<br />
Yapay sinir ağları öğrenme işlemi sırasında verilen bilgiler ile kendini düzenleyerek daha sonraki girdiler için doğru kararlar verebilme yeteneğine sahiptir.</p>
<p><strong>Yapay Sinir Ağlarının Üstünlükleri</strong><br />
Yapay sinir ağ modelleri biyolojik sinir ağlarının çalışmasından esinlenerek ortaya çıkarılmıştır. Canlılarda bulunan sinir sisteminin modellenmesi sayesinde yapay sinir ağları biyolojik sinir sisteminin üstünlüklerine sahip olmuştur.</p>
<ul>
<li><strong>Doğrusal Olmama </strong></li>
<p>Yapay sinir ağları özellikle doğrusal olmayan sistemlerde tahmin yapma açısından istatistik hesaplamalarına göre daha kolay ve doğru sonuç vermesinden dolayı sık kullanılan bir yöntem haline gelmiştir. Özellikle işletmecilik ve finans alanlarında olmak üzere tahmin gerektiren birçok alanda kullanılmaktadır.<br />
Yapay sinir ağlarının temel elemanlarından olan yapay sinir hücrelerinin (nöron) doğrusal sonuçlar vermeyişinden dolayı bu özellik ağa da yansımıştır. Doğrusal olmama özelliğinden dolayı yapay sinir ağları karmaşık problemlerin çözümünde de sıkça kullanılmaktadır</p>
<li><strong>Paralellik</strong></li>
<p>Klasik problem çözme algoritmalarının aksine yapay sinir ağları paralel çalışmaya uygun bir yapıya sahiptir. Bu özelliği sayesinde çok daha hızlı problem çözebilme yeteneğine sahip olmuştur.</p>
<li><strong>Hata Toleransı</strong></li>
<p>Yapay sinir ağları özellikle doğrusal olmayan sistemlerde tahmin yapma açısından istatistik hesaplamalarına göre daha kolay ve doğru sonuç vermesinden dolayı sık kullanılan bir yöntem haline gelmiştir. Özellikle işletmecilik ve finans alanlarında olmak üzere tahmin gerektiren birçok alanda kullanılmaktadır.<br />
Yapay sinir ağlarının temel elemanlarından olan yapay sinir hücrelerinin (nöron) doğrusal sonuçlar vermeyişinden dolayı bu özellik ağa da yansımıştır. Doğrusal olmama özelliğinden dolayı yapay sinir ağları karmaşık problemlerin çözümünde de sıkça kullanılmaktadır</p>
<p>Bilgisayar üzerinde çalışan bir elemanın zarar görüp devre dışı kalması o elmanın içinde bulunduğu sistemin çalışmamasına neden olur. Ancak paralel çalışabilme özelliği ve yapay sinir hücrelerinin bağımsız çalışabilme yapısından dolayı yapay sinir ağında herhangi bir eleman zarar gördüğünde ağın geri kalanı sorunsuz bir şekilde çalışmaya devam eder. İlk olarak yanlış sonuçlar verebilse de daha sonra yeni yapısını öğrenerek eski performansında çalışmaya devam edebilir.</p>
<li><strong>Öğrenebilirlik</strong></li>
<p>Klasik algoritmaların çoğu verilen formüllerin hesaplanması ile aynı girdiler için daima aynı çıktıları üretirler. Lineer olan bu algoritmaların aksine yapay sinir ağları sayesinde programlar öğrenme yeteneği de kazanmışlardır. Klasik algoritmalarda tam olarak tanımlı bir çözüm yolu olmayan problemler çözülemezken yapay sinir ağları sayesinde problemler çözüm yöntemi hakkında herhangi bir bilgi verilmeksizin çözülebilir. Yapay sinir ağlarının bu tip problemleri çözebilmesi için gereken tek şey örnek girdiler için sonuçların verilmesidir.</p>
<li><strong>Genelleme </strong></li>
<p>Yapay sinir ağları üzerinde çalıştığı probleme göre eğitildikten sonra eğitim sırasında karşılaşmadığı durumlar için de yanıt verebilir. Örneğin bir satranç taşının görüntüsünün tanıtılmasından sonra bu taşın görüntüsünü içeren ancak gürültülü bir görüntü verildiğinde bile yapay sinir ağı bu taşı tanıyabilir.</p>
<li><strong>Uyarlanabilirlik </strong></li>
<p>Yapay sinir ağı üzerinde çalıştığı probleme gör kendini düzenleyerek ağırlıklarını belirler. Bir problemi çözmek için eğitilen yapay sinir ağı herhangi bir başka problemde de kolaylıkla kullanılabilir. Bunun için gereken tek şey yeni problemin girdi ve çıktılarıyla ağın tekrar eğitilmesidir.</p>
<li><strong>Hız </strong></li>
<p>Yapay sinir ağları paralel yapısı nedeniyle hızlı bir şekilde çalışıp problem çözme yeteneğine sahiptir. Aynı özelliğinden dolayı donanım üzerinde de kolaylıkla gerçeklenebilir.</p>
<li><strong>Analiz ve Tasarım Kolaylığı </strong></li>
<p>Yapay sinir ağlarının temel yapı taşı olan yapay sinir yapısı bütün yapay sinir ağlarında aynıdır. Bundan dolayı yapay sinir hücresinin tasarımından sonra bu temel eleman ile yapay sinir ağları kolaylıkla oluşturulabilir. Yapay sinir ağlarının temel yapısının da aynı olmasından dolayı bu ağlar her türlü problemin çözümünde kullanılabilinir.</ul>
<p><strong>Yapay Sinir Ağlarının Dezavantajları</strong></p>
<ul>
<li><strong>Eğitim Süreci</strong></li>
<p>Yapay sinir ağları oluşturulduklarında hiçbir bilgi içermediğinden dolayı direk olarak kullanılamazlar. Herhangi bir problem çözümünde kullanılacak olan yapay sinir ağının problemde kullanılmadan önce eğitilmesi şarttır. Bu eğitim süresi problemin çözümünden çok daha uzun zaman alabilir.</p>
<li><strong>Başlangıç Koşullarına Bağlı Olması</strong></li>
<p>Yapay sinir ağları başlangıç koşullarından bağımsız olarak çok kolay dahi olsa herhangi bir problemi çözemezler. Karar verme anında sadece daha önce öğrendiği koşullara göre sonuç üretebilir. Eğitim sırasında verilen örnekler ağın sonraki problemleri çözmesinde de etkilidir.</ul>
<p><a href="http://www.ahmetkakici.com/yapay-sinir-aglari/yapay-sinir-aglarinin-mimarisi-ve-yapi-elemanlari/" target="_blank">Bir sonraki yazıda</a> biyolojik sinir sisteminin yapısına kısaca değinerek yapay sinir ağlarının yapısını anlatan bir yazı ile beraber olacağız. Daha sonrasında ise yapay sinir ağlarının işleyişini ele alabiliriz :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/yazilim/yapay-sinir-aglarina-giris/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>C# ile Görüntü İşleme &#8211; 2</title>
		<link>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-2/</link>
		<comments>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-2/#comments</comments>
		<pubDate>Fri, 02 Jan 2009 14:31:41 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[görüntü işleme]]></category>
		<category><![CDATA[image processing]]></category>
		<category><![CDATA[kod]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=105</guid>
		<description><![CDATA[Daha önce görüntü okuma, gösterme ve kaydetme gibi başlıca fonksiyonları vermiştim. Aşağıda ise asıl görüntüyü işeyecek fonksiyonlar bulunmaktadır. Tabii buradaki fonksiyonları kullanbilmek için daha önceden verdiğim şekilde görüntünün dizilere aktarılmış olması gerekiyor. Önceki yazıda gri seviyeye çevirilmiş görüntümüz vardı eğer bu görüntüyü siyah beyaza çevirmek istiyorsanız bunun için bir eşik değeri seçerek 0-255 arasındaki gri [...]]]></description>
			<content:encoded><![CDATA[<p>Daha önce görüntü okuma, gösterme ve kaydetme gibi başlıca fonksiyonları <a href="http://www.ahmetkakici.com/yazilim/goruntu-isleme-c/" target="_blank">vermiştim</a>. Aşağıda ise asıl görüntüyü işeyecek fonksiyonlar bulunmaktadır. Tabii buradaki fonksiyonları kullanbilmek için daha önceden verdiğim şekilde görüntünün dizilere aktarılmış olması gerekiyor.</p>
<p>Önceki yazıda gri seviyeye çevirilmiş görüntümüz vardı eğer bu görüntüyü siyah beyaza çevirmek istiyorsanız bunun için bir eşik değeri seçerek 0-255 arasındaki gri seviye görüntüyü bu seviyeye göre siyah veya beyaz olarak ayırmak gerekiyor. Eşik değerini sabit bir değer olarak belirleyebileceğiniz gibi her görüntüye göre dinamik olarak bir eşik değeri belirleyebilen bir yöntem de mevcuttur: otsu. Otsu algoritması sayesinde üzerinde çalıştığınız görüntüye özel bir eşik değerini otomatik olarak belirleyebilirsiniz. Bunun için görüntünün histogram dizisine ihtiyacınız olacak. İlk yazıda verdiğim kodda histogram çıkartma özelliği yoktu. Bunun için aşağıdaki kodu kullanabilirsiniz:</p>
<p><span id="more-105"></span></p>
<pre class="brush: csharp; title: ; notranslate">

int[,] pixelArray = new int[pictureBox1.Image.Height, pictureBox1.Image.Width];
int[,] greyPixelArray = new int[pictureBox1.Image.Height, pictureBox1.Image.Width];
int[] histogram = new int[256];

void BuildPixelArray(ref Image myImage)
{
pixelArray = new int[imageWidth, imageHeight];
greyPixelArray = new int[imageWidth, imageHeight];
Rectangle rect = new Rectangle(0, 0, myImage.Width, myImage.Height);
Bitmap temp = new Bitmap(myImage);
BitmapData bmpData = temp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int remain = bmpData.Stride - bmpData.Width * 3;
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
for (int j = 0; j &lt; bmpData.Height; j++)
{
for (int i = 0; i &lt; bmpData.Width; i++)
{
pixelArray[i, j] = ptr[0] + ptr[1] * 256 + ptr[2] * 256 * 256;
greyPixelArray[i, j] = (int)((double)ptr[0] * 0.11 + (double)ptr[1] * 0.59 + (double)ptr[2] * 0.3);
histogram[greyPixelArray[i, j]]++;
ptr += 3;
}
ptr += remain;
}
}
temp.UnlockBits(bmpData);
}
</pre>
<p>Burada histogram dizisini de oluşturduktan sonra artık otsu algoritması sayesinde dinamik olarak eşik değerini belirleyebiliriz:</p>
<pre class="brush: csharp; title: ; notranslate">

int otsuValue;

void Otsu()
{
double fmax = -1.0;
double m1, m2, S, toplam1 = 0.0, toplam2 = 0.0;
int nTop = 0, n1 = 0, n2;

for (int i = 0; i &lt; 256; i++)
{
toplam1 += (double)i * (double)histogram[i];
nTop += histogram[i];
}

for (int i = 0; i &lt; 256; i++)
{
n1 += histogram[i];
if (n1 == 0)
continue;
n2 = nTop - n1;
if (n2 == 0)
break;
toplam2 += (double)i * (double)histogram[i];
m1 = toplam2 / n1;
m2 = (toplam1 - toplam2) / n2;
S = (double)n1 * (double)n2 * (m1 - m2) * (m1 - m2);
if (S &gt; fmax)
{
fmax = S;
otsuValue = i;
}
}
}
</pre>
<p>Otsu veya sabit bir değere göre görüntüyü siyah beyaza çevirecek kod ise aşağıdadır. Bu fonksiyonun aldığı argThreshold parametresi eşik değerini belirtern 0-255 arasında bir değerdir.</p>
<pre class="brush: csharp; title: ; notranslate">

void Binary(int argThreshold)
{
binaryPixelArray = new int[imageWidth, imageHeight];
for (int i = 0; i &lt; imageWidth; i++)
{
for (int j = 0; j &lt; imageHeight; j++)
{
if (greyPixelArray[i, j] &lt; threshold)
binaryPixelArray[i, j] = 0;
else
binaryPixelArray[i, j] = 255;
}
}
}
</pre>
<p>Görüntüyü siyah beyaza çevirdikten sonra eğer kenar bulma algoritmalarını kullanmak isterseniz bir kaç seçeneğiniz mevcut. Bunlardan en popüleri sobel kenar bulma filtresidir. Aşağıdaki fonksiyonda type parametresi hangi tür kenarların bulunacağını belirtmek içindir. Dikey, yatay, köşegen şeklindeki kenarları veya tamamını ayrı ayrı bulabilirsiniz.</p>
<pre class="brush: csharp; title: ; notranslate">

void Sobel(int type)
{
int normalizeMax = 0;
int normalizeMin = maxIntVal;

sobelPixelArray = new int[imageWidth, imageHeight];
int[,] sobelArray1 =
new int[3, 3] {
{ 1, 0, -1 },
{ 2, 0, -2 },
{ 1, 0, -1 }
};

int[,] sobelArray2 =
new int[3, 3] {
{ 1, 2, 1 },
{ 0, 0, 0 },
{-1,-2,-1 }
};
int[,] sobelArray3 =
new int[3, 3] {
{ 2, 1, 0 },
{ 1, 0,-1 },
{ 0,-1,-2 }
};

int G1, G2, G3;
for (int i = 1; i &lt; imageWidth - 1; i++)
{
for (int j = 1; j &lt; imageHeight - 1; j++)
{
G1 = 0;
G2 = 0;
G3 = 0;
for (int k = -1; k &lt; 2; k++)
{
for (int l = -1; l &lt; 2; l++)
{
G1 += greyPixelArray[i + k, j + l] * sobelArray1[k + 1, l + 1];
G2 += greyPixelArray[i + k, j + l] * sobelArray2[k + 1, l + 1];
G3 += greyPixelArray[i + k, j + l] * sobelArray3[k + 1, l + 1];
}
}
if(type == 0)
{
sobelPixelArray[i, j] = Math.Abs(G1) + Math.Abs(G2) + Math.Abs(G3);
}
else if (type == 1)
{
sobelPixelArray[i, j] = Math.Abs(G2);
}
else if (type == 2)
{
sobelPixelArray[i, j] = Math.Abs(G1);
}
else if (type == 3)
{
sobelPixelArray[i, j] = Math.Abs(G3);
}

if (normalizeMax &lt; sobelPixelArray[i, j])
normalizeMax = sobelPixelArray[i, j];
if (normalizeMin &gt; sobelPixelArray[i, j])
normalizeMin = sobelPixelArray[i, j];
}
}

NormalizeArray(ref sobelPixelArray, normalizeMax, normalizeMin);
}
</pre>
<p>Yukarıda bulunan kodun en altında çağırılan normalize fonksiyonu ise sonuç dizisini 0-255 değerleri arasına düşürmek içindir:</p>
<pre class="brush: csharp; title: ; notranslate">

void NormalizeArray(ref int[,] sourceArray,int normalizeMax,int normalizeMin)
{

int factor = normalizeMax - normalizeMin;
for (int i = 0; i &lt; sourceArray.GetLength(0); i++)
{
for (int j = 0; j &lt; sourceArray.GetLength(1); j++)
{
sourceArray[i, j] = (sourceArray[i, j] - normalizeMin) * 255 / factor;
}
}
}
</pre>
<p>Bir diğer kenar bulma yöntemi ise Prewitt&#8217;tir:</p>
<pre class="brush: csharp; title: ; notranslate">

int[,] prewittPixelArray;

void Prewitt()
{
int normalizeMax = 0;
int normalizeMin = maxIntVal;
prewittPixelArray = new int[imageWidth, imageHeight];
int[,] PrewittArray1 =
new int[3, 3] {
{-1,-1,-1 },
{ 0, 0, 0 },
{ 1, 1, 1 }
};

int[,] PrewittArray2 =
new int[3, 3] {
{ -1, 0, 1 },
{ -1, 0, 1 },
{ -1, 0, 1 }
};
int[,] PrewittArray3 =
new int[3, 3] {
{-1,-1, 0 },
{-1, 0, 1 },
{ 0, 1, 1 }
};

int[,] PrewittArray4 =
new int[3, 3] {
{ 1, 1, 0 },
{ 1, 0,-1 },
{ 0,-1,-1 }
};

int G1, G2, G3, G4;
for (int i = 1; i &lt; imageWidth - 1; i++)
{
for (int j = 1; j &lt; imageHeight - 1; j++)
{
G1 = 0;
G2 = 0;
G3 = 0;
G4 = 0;
for (int k = -1; k &lt; 2; k++)
{
for (int l = -1; l &lt; 2; l++)
{
G1 += greyPixelArray[i + k, j + l] * PrewittArray1[k + 1, l + 1];
G2 += greyPixelArray[i + k, j + l] * PrewittArray2[k + 1, l + 1];
G3 += greyPixelArray[i + k, j + l] * PrewittArray3[k + 1, l + 1];
G4 += greyPixelArray[i + k, j + l] * PrewittArray4[k + 1, l + 1];
}
}

prewittPixelArray[i, j] = Math.Abs(G1) + Math.Abs(G2) + Math.Abs(G3) + Math.Abs(G4);
if (normalizeMax &lt; prewittPixelArray[i, j])
normalizeMax = prewittPixelArray[i, j];
if (normalizeMin &gt; prewittPixelArray[i, j])
normalizeMin = prewittPixelArray[i, j];
}
}

int factor = normalizeMax - normalizeMin;
for (int j = 1; j &lt; imageHeight - 1; j++)
{
for (int i = 1; i &lt; imageWidth - 1; i++)
{
prewittPixelArray[i, j] = (prewittPixelArray[i, j] - normalizeMin) * 255 / factor;
}
}
}
</pre>
<p>Prewitt ve sobel&#8217;e alternatif olarak Robert kenar bulma filtresi de mevcuttur :</p>
<pre class="brush: csharp; title: ; notranslate">

int[,] robertPixelArray;

void Robert()
{

robertPixelArray = new int[imageWidth, imageHeight];
for (int i = 1; i &lt; imageHeight - 1; i++)
{
for (int j = 1; j &lt; imageWidth - 1; j++)
{
robertPixelArray[j, i] = Math.Abs(greyPixelArray[j, i] - greyPixelArray[j - 1, i - 1]) + Math.Abs(greyPixelArray[j, i - 1] - greyPixelArray[j - 1, i]);
}
}
}
</pre>
<p>Eğer kenar bulma algoritmalarını kullanmadan önce görüntüdeki gürültüleri temizlemek istiyorsanız mean, median ve gaussian filtereleri ile bu işlemi yapabilirsiniz.</p>
<p>Mean filtresi :</p>
<pre class="brush: csharp; title: ; notranslate">

int[,] meanPixelArray;

void Mean()
{
meanPixelArray = new int[imageWidth, imageHeight];
for (int i = 1; i &lt; imageHeight - 1; i++)
{
for (int j = 1; j &lt; imageWidth - 1; j++)
{
meanPixelArray[j, i] =
(
greyPixelArray[j, i - 1]
+ greyPixelArray[j, i + 1]
+ greyPixelArray[j, i]
+ greyPixelArray[j - 1, i - 1]
+ greyPixelArray[j - 1, i + 1]
+ greyPixelArray[j - 1, i]
+ greyPixelArray[j + 1, i - 1]
+ greyPixelArray[j + 1, i + 1]
+ greyPixelArray[j + 1, i]
) / 9;
}
}
}
</pre>
<p>Median filtresi:</p>
<pre class="brush: csharp; title: ; notranslate">

int[,] medianPixelArray;

void Median()
{

medianPixelArray = new int[imageWidth, imageHeight];
int[] tempArray = new int[9];
for (int i = 1; i &lt; imageHeight - 1; i++)
{
for (int j = 1; j &lt; imageWidth - 1; j++)
{
int counter = 0;
for (int k = -1; k &lt; 2; k++)
{
for (int l = -1; l &lt; 2; l++)
{
tempArray[counter++] = greyPixelArray[j + l, i + k];
}
}
System.Array.Sort(tempArray);
medianPixelArray[j, i] = tempArray[4];
}
}
}
</pre>
<p>Gaussian filtresi</p>
<pre class="brush: csharp; title: ; notranslate">

int[,] gaussianPixelArray;

void Gaussian()
{
gaussianPixelArray = new int[imageWidth, imageHeight];

int[,] gaussianArray =
new int[5, 5] {
{1,4,7,4,1},
{4,16,26,16,4},
{7,26,41,26,7},
{4,16,26,16,4},
{1,4,7,4,1}
};
int tempSum;
for (int i = 2; i &lt; imageHeight - 2; i++)
{
for (int j = 2; j &lt; imageWidth - 2; j++)
{
tempSum = 0;
for (int k = -2; k &lt; 3; k++)
{
for (int l = -2; l &lt; 3; l++)
{
tempSum += greyPixelArray[j + l, i + k] * gaussianArray[k + 2, l + 2];
}
}
gaussianPixelArray[j, i] = tempSum / 273;
}
}
}
</pre>
<p>Daha sonraki yazıda yapısal (morfolojik) işlemleri yapan filtreleri de açıklamalarıyla birlikte vermeyi düşünüyorum. O zamana kadar hepinize kolay gelsin.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/c-ile-goruntu-isleme-2/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Prolog ile Determinant Hesabı</title>
		<link>http://www.ahmetkakici.com/programlama/prolog-ile-determinant-hesabi/</link>
		<comments>http://www.ahmetkakici.com/programlama/prolog-ile-determinant-hesabi/#comments</comments>
		<pubDate>Wed, 24 Dec 2008 11:37:42 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[kod]]></category>
		<category><![CDATA[prolog]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=104</guid>
		<description><![CDATA[Determinant; bir kare matrisi, reel bir sayıyla eşleştiren özel bir fonksiyondur. Sadece kare matrislere uygulanabilir. Determinant hesabının temel yolu minör ve kofaktörlerinin hesaplanması yöntemidir. Buna ek olarak kolay hesaplama için Sarrus Yöntemi adında başka bir yöntem daha geliştirilmiştir. Minör ve kofaktör hesabı ile daha büyük matrisleri daha sistemli bir şekilde çarpabiliriz. Minör tanım olarak: A [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Determinant" target="_blank">Determinant</a>; bir kare matrisi, reel bir sayıyla eşleştiren özel bir fonksiyondur. Sadece kare matrislere uygulanabilir. Determinant hesabının temel yolu minör ve kofaktörlerinin hesaplanması yöntemidir. Buna ek olarak kolay hesaplama için <a href="http://en.wikipedia.org/wiki/Rule_of_Sarrus" target="_blank">Sarrus Yöntemi</a> adında başka bir yöntem daha geliştirilmiştir.<br />
<span id="more-104"></span><br />
Minör ve kofaktör hesabı ile daha büyük matrisleri daha sistemli bir şekilde çarpabiliriz.<br />
Minör tanım olarak: A = (aij) nxn kare matrisinde bir aij ( 1≤i,j≤n)  öğesinin bulunduğu i. satır ve j. sütunun çıkarılmasıyla elde edilen n-1. dereceden kare matrisinin determinantıdır. Mij ile ifade edilir.<br />
A = (aij) nxn matrisinde aij öğesinin minörü olan Mij ‘nin (-1)^(i+j) ile çarpılmasıyla elde edilen sayıya aij öğesinin kofakötür denir ve Aij ile gösterilir.<br />
Bir kare matrisin minör ve kofaktörlerinin çarpımlarının toplamı o matrisin determinantını verir.<br />
Prolog dilinde yazılan programda da kofaktör ve minör hesabı ile determinant hesabı yapılmıştır. Goal kısmında örnek bir matris verilerek determinantı hesaplanıştır.</p>
<pre class="brush: jscript; title: ; notranslate">

DOMAINS
liste=integer*
matris = liste*
int=integer

PREDICATES
ilkEleman(liste,int)
uzunluk(liste,int)
detBul(liste,liste,int)
ilkleriSil(matris,matris)
negatif(int,int)
sonaAt(matris,matris)
tersCevirListe(matris,matris)
tersCeviriciListe(matris,matris,matris)
det(matris,int,int,int)

CLAUSES
ilkEleman([X|_],X).

uzunluk([],0).
uzunluk([_|K],U):-uzunluk(K,X),U=X+1.

ilkleriSil([],[]).
ilkleriSil([[_|BasKuyruk]|Kuyruk1],[ BasKuyruk |SonucKuyruk]):-
ilkleriSil(Kuyruk1,SonucKuyruk).

negatif(-1,1).
negatif(1,-1).

sonaAt([Bas|Kuyruk],Sonuc):-
tersCevirListe(Kuyruk,TersKuyruk),
tersCevirListe([Bas|TersKuyruk],Sonuc).

tersCevirListe(X,Y):-tersCeviriciListe(X,[],Y).
tersCeviriciListe([],X,X).
tersCeviriciListe([B|K],TMP,SONUC) :-
tersCeviriciListe(K,[B|TMP],SONUC).

detBul([Bas1,Kuyruk1|_],[Bas2,Kuyruk2|_],Sonuc):-
Sonuc = Bas1*Kuyruk2-Bas2*Kuyruk1.

det([Bas1,Bas2|_],_,Sonuc,_):-
uzunluk(Bas1,En),
En&lt;=2,
detBul(Bas1,Bas2,Sonuc),!.

det([Bas|_],Sayac,0,_):-uzunluk(Bas,En),En&lt;=Sayac,!.

det([Bas|Kuyruk],Sayac,Sonuc,_):-
YeniSayac=Sayac+1,
uzunluk(Bas,En),
En&gt;Sayac,
En&lt;=3,
sonaAt([Bas|Kuyruk],Sonda),
ilkEleman(Bas,KatSayi),
ilkleriSil(Kuyruk,KuyrukOrta),
det(KuyrukOrta,0,OrtaSonuc,_),
det(Sonda,YeniSayac,YanSonuc,_),
Sonuc=(KatSayi*OrtaSonuc)+YanSonuc,!.

det([Bas|Kuyruk],Sayac,Sonuc,X):-
YeniSayac=Sayac+1,
uzunluk(Bas,En),
En&gt;Sayac,
sonaAt([Bas|Kuyruk],Sonda),
ilkEleman(Bas,KatSayi),
ilkleriSil(Kuyruk,KuyrukOrta),
negatif(X,Y),
det(KuyrukOrta,0,OrtaSonuc,Y),
det(Sonda,YeniSayac,YanSonuc,Y),
Sonuc=(X*KatSayi*OrtaSonuc)+YanSonuc.

GOAL
write(&quot;_____&quot;),nl,det([[1,2,4,8],[2,2,7,11],[3,6,3,12],[4,13,0,5]],0,Sonuc,1),write(Sonuc).
</pre>
<p>Programda kullanılan yüklemlere tek tek bakacak olursak yüklemlerin yaptığı görevler aşağıda açıklanmıştır:</p>
<ul>
<li>ilkEleman(liste,int):  aldığı tamsayı listesinin ilk elemanını vermektedir.</li>
<li>uzunluk(liste,int) :  aldığı tamsayı listesinin eleman sayısını vermektedir.</li>
<li>detBul(liste,liste,int) :  2&#215;2 matrisin çarpımını yapar. Aldığı iki listenin uzunluğu da birbirine eşit ve iki olmalıdır.</li>
<li>ilkleriSil(matris,matris) :  Minörleri ilk satıra göre açtığım için verilen matrisin ilk satırını silmek için bu yüklem kullanılmıştır.</li>
<li>negatif(-1,1) :  Kofaktörlerin katsayılarını hesaplamak için kullanılmıştır. Her kofaktörde bir önceki kofaktörün katsayısının negatifi hesaplanmıştır.</li>
<li>sonaAt(matris,matris) :  Minörlerin hesabında bir sonraki sütuna göre açılım yapıldığında bu yüklem sayesinde ilk sütun sona atılarak ikinci sütun ilk sütun haline getirilir. Ayrıca 3&#215;3 matrislerde determinant hesaplanırken katsayılarının sırasıyla +1 ve -1 ile çarpılmasına bu yüklem sayesinde gerek kalmamıştır.</li>
<li>tersCevirListe(matris,matris) :  Sona at yükleminde ilk sütunu sona atmak için varolan matrisin ilk sütunu alınarak kalan matris ters çevirilerek ilk sütun başa koyulduktan sonra matris tekrar ters çevrilmiştir. Bu yüklem ters çevirme işlemini yapmaktadır.</li>
<li>tersCeviriciListe(matris,matris,matris) :  tersCevirListe yükleminde kullanılan geçici matrisi bu yüklem ile tanımlayarak asıl yüklemin iki parametre ile gerekli çevirmeyi yapması sağlanmıştır.<br />
det(matris,int,int,int) ) : det yüklemi bütün determinant çarpım işlemlerini gerçekleştirmektedir.</li>
</ul>
<p>Yukarıdan aşağıya doğru yazılmış dört yüklemi sırasıyla incelersek;</p>
<ol>
<li>İlk yüklem 2&#215;2 matris kaldığı zaman bunu detBul yüklemi sayesinde hesaplar ver geri döndürür.</li>
<li>İkinci yüklem ise ilk sütunu sona atarak hesaplanan determinantların durma koşulunu belirler. Eğer sayac değişkeni sıfır olmuşsa yani n sütun varsa ve her biri için açılım yapılmışsa sonuç değeri sıfır olarak döndürür.</li>
<li>Üçüncü yüklem ise 3. dereceden matrislerin determinant hesabında kullanılmıştır. 3. Dereceden matrislerde daha fazla alt matris olmadığından dolayı katsayı değişimine gerek kalmamıştır.</li>
<li>Dördüncü yüklem ise 4. derece ve üstü matrislerin determinantını hesaplarken kofaktörü değiştirmek için kullanılmıştır.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/prolog-ile-determinant-hesabi/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Prolog ile Liste İşlemleri</title>
		<link>http://www.ahmetkakici.com/programlama/prolog-ile-liste-islemleri/</link>
		<comments>http://www.ahmetkakici.com/programlama/prolog-ile-liste-islemleri/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 13:43:46 +0000</pubDate>
		<dc:creator>Ahmet Kakıcı</dc:creator>
				<category><![CDATA[Programlama]]></category>
		<category><![CDATA[kod]]></category>
		<category><![CDATA[prolog]]></category>

		<guid isPermaLink="false">http://www.ahmetkakici.com/?p=102</guid>
		<description><![CDATA[Prolog&#8217;un bel kemiği olan liste veri yapısı için daha önceden kullandığım liste fonksiyonlarını aşağıda listeledim. Fonksiyonların isimlerinden ne iş yaptıkları belli oluyor yine de anlamadığınız yer olursa bir yorum bırakabilirsiniz.]]></description>
			<content:encoded><![CDATA[<p>Prolog&#8217;un bel kemiği olan liste veri yapısı için daha önceden kullandığım liste fonksiyonlarını aşağıda listeledim. Fonksiyonların isimlerinden ne iş yaptıkları belli oluyor yine de anlamadığınız yer olursa bir yorum bırakabilirsiniz.</p>
<p><span id="more-102"></span></p>
<pre class="brush: jscript; title: ; notranslate">

PREDICATES
listeGoster(liste)
uzunluk(liste,int)
uye(int,liste)
ekle(int,liste,liste)
yoksaEkle(int,liste,liste)
sil(int,liste,liste)
hepsiniSil(int,liste,liste)
elemanTopla(liste,int)
arttir(int,liste,liste)
birles(liste,liste,liste)
birlesim(liste,liste,liste)
kesisim(liste,liste,liste)
buda(liste,liste)
tersCevir(liste,liste)
tersCevirici(liste,liste,liste)
prefix(liste,liste)
suffix(liste,liste)

CLAUSES
listeGoster([]).
listeGoster([B|K]):-write(B),nl,listeGoster(K).

uzunluk([],0).
uzunluk([_|K],U):-uzunluk(K,X),U=X+1.

uye(X,[X|_]).
uye(X,[_|K]):-uye(X,K).

ekle(X,L,[X|L]).

yoksaEkle(X,L,L):-uye(X,L),!.
yoksaEkle(X,L,[X|L]).

sil(X,[X|L],L).
sil(X,[B|K1],[B|K2]):-sil(X,K1,K2).

hepsiniSil(_,[],[]).
hepsiniSil(X,[X|L],M):-sil(X,L,M),!.
hepsiniSil(X,[Y|K1],[Y|K2]):-sil(X,K1,K2).

elemanTopla([],0).
elemanTopla([X|K],T):-elemanTopla(K,Y),T=Y+X.

arttir(_,[],[]).
arttir(X,[B1|K1],[B2|K2]):-B2=B1+X,arttir(X,K1,K2).

birles([],L,L).
birles([B|K1],L2,[B|K2]):-birles(K1,L2,K2).

birlesim([],L,L).
birlesim([B|K1],L2,K2):- uye(B,L2),birlesim(K1,L2,K2),!.
birlesim([B|K1],L2,[B|K2]):- birlesim(K1,L2,K2).

kesisim([],_,[]).
kesisim(_,[],[]).
kesisim([B|K1],L2,[B|K2]):-uye(B,L2),kesisim(K1,L2,K2),!.
kesisim([_|K1],L2,K2):-kesisim(K1,L2,K2).

buda([],[]).
buda([B|K],L):- uye(B,K),buda(K,L),!.
buda([B|K1],[B|K2]):- buda(K1,K2).

tersCevir(X,Y):-tersCevirici(X,[],Y).
tersCevirici([],X,X).
tersCevirici([B|K],TMP,SONUC) :- tersCevirici(K,[B|TMP],SONUC).

prefix([],_).
prefix([B|K1],[B|K2]):-prefix(K1,K2).

suffix(X,Y):-tersCevir(X,TX),tersCevir(Y,TY),prefix(TX,TY).
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ahmetkakici.com/programlama/prolog-ile-liste-islemleri/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

