<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-20T12:05:42+00:00</updated><id>https://program.sonsuz.us/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">Arduino ve Raspberry Pi ile Robotik Eğitimi Herkes İçin Erişilebilir</title><link href="https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir/" rel="alternate" type="text/html" title="Arduino ve Raspberry Pi ile Robotik Eğitimi Herkes İçin Erişilebilir" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir</id><content type="html" xml:base="https://program.sonsuz.us/posts/arduino-ve-raspberry-pi-ile-robotik-egitimi-herkes-icin-erisilebilir/"><![CDATA[<p>Bir zamanlar robot geliştirmek; pahalı laboratuvarlara, özel üretim devrelere ve kalın mühendislik kitaplarına erişmeyi gerektiriyordu. Arduino ve Raspberry Pi gibi açık kaynaklı donanım platformları ise bu tabloyu önemli ölçüde değiştirdi. Öğrenciler artık birkaç sensör, motor ve internetten erişilebilen örneklerle çalışan bir robot geliştirebiliyor. Böylece robotik eğitimi, yalnızca uzmanların bulunduğu laboratuvarlardan çıkarak sınıflara, atölyelere ve hatta mutfak masalarına kadar ulaşıyor.</p>

<p>``</p>

<h2 id="açık-kaynak-erişilebilirliği-nasıl-artırıyor">Açık kaynak erişilebilirliği nasıl artırıyor?</h2>

<p>Açık kaynaklı donanımda devre şemaları, yazılım araçları, kütüphaneler ve örnek projeler toplulukla paylaşılır. Kullanıcı yalnızca hazır bir ürünü tüketmez; sistemin nasıl çalıştığını inceleyebilir, değiştirebilir ve yeniden üretebilir. Bu yaklaşım erişilebilirliği üç yönden güçlendirir:</p>

<ul>
  <li><strong>Ekonomik erişim:</strong> Düşük maliyetli kartlar ve uyumlu yan ürünler kullanılabilir.</li>
  <li><strong>Bilgiye erişim:</strong> Ücretsiz belgeler, videolar ve topluluk forumları öğrenme sürecini destekler.</li>
  <li><strong>Deneysel erişim:</strong> Öğrenci, hata yapmaktan korkmadan devreyi ve kodu değiştirebilir.</li>
</ul>

<p>Robotik sistemlerin temelinde algılama, karar verme ve hareket etme döngüsü bulunur. Sensör çevreden veri toplar, kontrol birimi bu veriyi işler ve aktüatörler fiziksel tepki üretir:</p>

\[Algılama \rightarrow Karar \rightarrow Hareket\]

<p>Örneğin ultrasonik sensörün gönderdiği ses dalgasının geri dönüş süresi $t$, ses hızı $v$ ve engel uzaklığı $d$ arasındaki ilişki şöyledir:</p>

\[d = \frac{v \cdot t}{2}\]

<p>İkiye bölünmesinin nedeni, ölçülen sürenin sesin engele gidişini ve geri dönüşünü birlikte içermesidir. Böyle bir formül, fizik bilgisini doğrudan çalışan bir robot üzerinde görünür hâle getirir.</p>

<h2 id="arduino-mu-raspberry-pi-mı">Arduino mu, Raspberry Pi mı?</h2>

<p>Her iki platform da robotik eğitiminde değerlidir; ancak aynı işi yapmak üzere tasarlanmamıştır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Arduino</th>
      <th>Raspberry Pi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yapı</td>
      <td>Mikrodenetleyici kartı</td>
      <td>Tek kart bilgisayar</td>
    </tr>
    <tr>
      <td>İşletim sistemi</td>
      <td>Yok</td>
      <td>Genellikle Linux</td>
    </tr>
    <tr>
      <td>Başlangıç süresi</td>
      <td>Neredeyse anlık</td>
      <td>İşletim sistemi açılışı gerekir</td>
    </tr>
    <tr>
      <td>Güç tüketimi</td>
      <td>Düşük</td>
      <td>Daha yüksek</td>
    </tr>
    <tr>
      <td>Uygun görevler</td>
      <td>Sensör, motor, gerçek zamanlı kontrol</td>
      <td>Görüntü işleme, yapay zekâ, ağ uygulamaları</td>
    </tr>
    <tr>
      <td>Başlangıç zorluğu</td>
      <td>Elektronik odaklı ve sade</td>
      <td>Yazılım olanakları geniş, yapılandırması daha ayrıntılı</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/arduino-ve-raspberry-56.svg" alt="arduino-ve-raspberry-56" /></p>

<p>Arduino, çizgi izleyen veya engelden kaçan bir robot için güçlü bir başlangıçtır. Raspberry Pi ise kamera görüntüsünden nesne tanıyan ya da web arayüzüyle yönetilen robotlarda öne çıkar. İki kart birlikte de kullanılabilir: Raspberry Pi yüksek seviyeli kararları verirken Arduino motorları zamanlamaya duyarlı biçimde kontrol edebilir.</p>

<h2 id="küçük-bir-robot-refleksi">Küçük bir robot refleksi</h2>

<p>Aşağıdaki Arduino kodu, bir dijital sensör engel algıladığında motor kontrol çıkışını durdurur. Bu örnek, algılama-karar-hareket döngüsünün en sade hâlidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="kt">int</span> <span class="n">sensorPin</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">motorPin</span> <span class="o">=</span> <span class="mi">9</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">sensorPin</span><span class="p">,</span> <span class="n">INPUT</span><span class="p">);</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="n">OUTPUT</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span>
  <span class="kt">bool</span> <span class="n">engelVar</span> <span class="o">=</span> <span class="n">digitalRead</span><span class="p">(</span><span class="n">sensorPin</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">engelVar</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">analogWrite</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>    <span class="c1">// Motoru durdur</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="n">analogWrite</span><span class="p">(</span><span class="n">motorPin</span><span class="p">,</span> <span class="mi">180</span><span class="p">);</span>  <span class="c1">// Orta-yüksek hızda ilerle</span>
  <span class="p">}</span>

  <span class="n">delay</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span> <span class="c1">// Sensörü saniyede yaklaşık 50 kez kontrol et</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Kod yalnızca programlamayı değil, giriş-çıkış mantığını ve geri beslemeyi de öğretir. Öğrenci <code class="language-plaintext highlighter-rouge">180</code> değerini değiştirerek hızın davranışa etkisini gözlemleyebilir. Elbette gerçek bir motor doğrudan karta bağlanmamalı; motor sürücü devresi ve uygun güç kaynağı kullanılmalıdır.</p>

<h2 id="erişilebilirlik-yalnızca-düşük-fiyat-değildir">Erişilebilirlik yalnızca düşük fiyat değildir</h2>

<p>Ucuz kartlar tek başına eşit eğitim fırsatı oluşturmaz. İnternet erişimi, yerelleştirilmiş içerik, öğretmen eğitimi, yedek parça bulunabilirliği ve güvenli çalışma ortamı da önemlidir. Ayrıca açık kaynak projelerde belgelerin güncelliği değişebilir ve Raspberry Pi gibi kartların toplam maliyetine güç kaynağı, hafıza kartı ve çevre birimleri eklenebilir.</p>

<p>Buna rağmen bu platformların en büyük katkısı, öğrenciyi pasif kullanıcıdan üreticiye dönüştürmesidir. Bir LED’i yakmakla başlayan yolculuk; otonom araçlara, tarım robotlarına veya yapay zekâ destekli sistemlere uzanabilir. Robotik böylece ulaşılmaz bir gelecek teknolojisi değil, parçalarına ayrılıp anlaşılabilen ve yeniden tasarlanabilen bir öğrenme alanı hâline gelir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="arduino" /><category term="raspberry pi" /><category term="robotik" /><category term="açık kaynak" /><category term="stem" /><category term="elektronik" /><summary type="html"><![CDATA[Bir zamanlar robot geliştirmek; pahalı laboratuvarlara, özel üretim devrelere ve kalın mühendislik kitaplarına erişmeyi gerektiriyordu. Arduino ve Raspberry Pi gibi açık kaynaklı donanım platformları ise bu tabloyu önemli ölçüde değiştirdi. Öğrenciler artık birkaç sensör, motor ve internetten erişilebilen örneklerle çalışan bir robot geliştirebiliyor. Böylece robotik eğitimi, yalnızca uzmanların bulunduğu laboratuvarlardan çıkarak sınıflara, atölyelere ve hatta mutfak masalarına kadar ulaşıyor.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/arduino-ve-raspberry-56.png" /><media:content medium="image" url="https://program.sonsuz.us/img/arduino-ve-raspberry-56.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C# ile Multithreading: TPL, Task ve async/await Rehberi</title><link href="https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi/" rel="alternate" type="text/html" title="C# ile Multithreading: TPL, Task ve async/await Rehberi" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-ile-multithreading-tpl-task-ve-asyncawait-rehberi/"><![CDATA[<p>Bir uygulamanın aynı anda birden fazla iş yapabilmesi kulağa sihir gibi gelebilir; ancak C# dünyasında bu sihrin arkasında iş parçacıkları, görevler ve dikkatli bir zamanlama mekanizması bulunur. Task Parallel Library (TPL) CPU ağırlıklı işleri paralelleştirirken <code class="language-plaintext highlighter-rouge">async/await</code>, özellikle dosya, ağ ve veritabanı gibi beklemeli işlemlerde iş parçacıklarını gereksiz yere meşgul etmeden ölçeklenebilir uygulamalar kurmamızı sağlar.
``</p>
<h2 id="eşzamanlılık-ve-paralellik-aynı-şey-değildir">Eşzamanlılık ve paralellik aynı şey değildir</h2>

<p>Eşzamanlılık, birden fazla işin zaman aralıkları iç içe geçecek şekilde ilerlemesidir. Paralellik ise bu işlerin gerçekten aynı anda, örneğin farklı işlemci çekirdeklerinde çalışmasıdır.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Temel amaç</th>
      <th>Uygun iş türü</th>
      <th>C# aracı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Eşzamanlılık</td>
      <td>Beklerken başka işe geçmek</td>
      <td>Ağ, dosya, veritabanı</td>
      <td><code class="language-plaintext highlighter-rouge">async/await</code></td>
    </tr>
    <tr>
      <td>Paralellik</td>
      <td>Hesabı çekirdeklere dağıtmak</td>
      <td>Görüntü işleme, hesaplama</td>
      <td><code class="language-plaintext highlighter-rouge">Parallel</code>, TPL</td>
    </tr>
    <tr>
      <td>İş parçacığı</td>
      <td>Çalıştırma kaynağı sağlamak</td>
      <td>Düşük seviyeli kontrol</td>
      <td><code class="language-plaintext highlighter-rouge">Thread</code></td>
    </tr>
    <tr>
      <td>Görev</td>
      <td>Yapılacak işi temsil etmek</td>
      <td>Modern iş akışları</td>
      <td><code class="language-plaintext highlighter-rouge">Task</code></td>
    </tr>
  </tbody>
</table>

<p>Bir işin tek çekirdekte tamamlanma süresi $T_1$, $p$ çekirdekteki süresi $T_p$ ise teorik hızlanma şöyle ifade edilir:</p>

\[S_p = \frac{T_1}{T_p}\]

<p>İdeal durumda $S_p \approx p$ beklenir. Gerçekte görev oluşturma maliyeti, senkronizasyon ve paylaşılan kaynaklar nedeniyle bu değere nadiren ulaşılır.</p>

<h2 id="tpl-ile-cpu-ağırlıklı-işleri-çalıştırmak">TPL ile CPU ağırlıklı işleri çalıştırmak</h2>

<p>TPL, görevlerin uygun iş parçacıklarına dağıtılmasını <code class="language-plaintext highlighter-rouge">ThreadPool</code> üzerinden yönetir. Böylece her iş için elle <code class="language-plaintext highlighter-rouge">Thread</code> oluşturmak gerekmez.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Threading.Tasks</span><span class="p">;</span>

<span class="kt">int</span><span class="p">[]</span> <span class="n">sayilar</span> <span class="p">=</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">8</span><span class="p">).</span><span class="nf">ToArray</span><span class="p">();</span>

<span class="n">Parallel</span><span class="p">.</span><span class="nf">ForEach</span><span class="p">(</span><span class="n">sayilar</span><span class="p">,</span> <span class="n">sayi</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="kt">double</span> <span class="n">sonuc</span> <span class="p">=</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">sayi</span><span class="p">)</span> <span class="p">*</span> <span class="n">Math</span><span class="p">.</span><span class="nf">Pow</span><span class="p">(</span><span class="n">sayi</span><span class="p">,</span> <span class="m">3</span><span class="p">);</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"</span><span class="p">{</span><span class="n">sayi</span><span class="p">}</span><span class="s">: </span><span class="p">{</span><span class="n">sonuc</span><span class="p">}</span><span class="s"> - Thread: </span><span class="p">{</span><span class="n">Environment</span><span class="p">.</span><span class="n">CurrentManagedThreadId</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Parallel.ForEach</code>, koleksiyondaki hesaplamaları mümkün olduğunda farklı iş parçacıklarında yürütür. Ancak çok küçük işlemleri paralelleştirmek, yönetim maliyeti yüzünden normal bir döngüden daha yavaş olabilir. Önce ölçmek, sonra paralelleştirmek altın kuraldır.</p>

<p>Bağımsız görevleri başlatıp hepsinin bitmesini beklemek için <code class="language-plaintext highlighter-rouge">Task.WhenAll</code> kullanılabilir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="n">hesap1</span> <span class="p">=</span> <span class="n">Task</span><span class="p">.</span><span class="nf">Run</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">1_000_000</span><span class="p">).</span><span class="nf">Sum</span><span class="p">());</span>
<span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="n">hesap2</span> <span class="p">=</span> <span class="n">Task</span><span class="p">.</span><span class="nf">Run</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Enumerable</span><span class="p">.</span><span class="nf">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">500_000</span><span class="p">).</span><span class="nf">Sum</span><span class="p">());</span>

<span class="kt">int</span><span class="p">[]</span> <span class="n">sonuclar</span> <span class="p">=</span> <span class="k">await</span> <span class="n">Task</span><span class="p">.</span><span class="nf">WhenAll</span><span class="p">(</span><span class="n">hesap1</span><span class="p">,</span> <span class="n">hesap2</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Toplam: </span><span class="p">{</span><span class="n">sonuclar</span><span class="p">.</span><span class="nf">Sum</span><span class="p">()}</span><span class="s">"</span><span class="p">);</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Task.Run</code>, CPU ağırlıklı senkron kodu ThreadPool üzerinde çalıştırır. Buna karşılık zaten asenkron olan HTTP veya veritabanı çağrılarını ayrıca <code class="language-plaintext highlighter-rouge">Task.Run</code> içine koymak genellikle gereksizdir.</p>

<h2 id="asyncawait-ile-beklerken-kaynak-tüketmemek">async/await ile beklerken kaynak tüketmemek</h2>

<p><code class="language-plaintext highlighter-rouge">async</code>, metodun asenkron işlem içerebildiğini; <code class="language-plaintext highlighter-rouge">await</code> ise işlem tamamlanana kadar kontrolün çağırana geri verilebileceğini belirtir. Bu sırada iş parçacığının bloklanması gerekmez.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System.Net.Http</span><span class="p">;</span>

<span class="k">static</span> <span class="k">async</span> <span class="n">Task</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span> <span class="nf">SayfaBoyutuAsync</span><span class="p">(</span>
    <span class="kt">string</span> <span class="n">adres</span><span class="p">,</span>
    <span class="n">CancellationToken</span> <span class="n">iptal</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">using</span> <span class="nn">HttpClient</span> <span class="n">istemci</span> <span class="p">=</span> <span class="k">new</span><span class="p">();</span>
    <span class="kt">string</span> <span class="n">icerik</span> <span class="p">=</span> <span class="k">await</span> <span class="n">istemci</span><span class="p">.</span><span class="nf">GetStringAsync</span><span class="p">(</span><span class="n">adres</span><span class="p">,</span> <span class="n">iptal</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">icerik</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">using</span> <span class="nn">CancellationTokenSource</span> <span class="n">kaynak</span> <span class="p">=</span> <span class="k">new</span><span class="p">();</span>
<span class="n">kaynak</span><span class="p">.</span><span class="nf">CancelAfter</span><span class="p">(</span><span class="n">TimeSpan</span><span class="p">.</span><span class="nf">FromSeconds</span><span class="p">(</span><span class="m">5</span><span class="p">));</span>

<span class="k">try</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">boyut</span> <span class="p">=</span> <span class="k">await</span> <span class="nf">SayfaBoyutuAsync</span><span class="p">(</span><span class="s">"https://example.com"</span><span class="p">,</span> <span class="n">kaynak</span><span class="p">.</span><span class="n">Token</span><span class="p">);</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"İndirilen karakter: </span><span class="p">{</span><span class="n">boyut</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">OperationCanceledException</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"İşlem iptal edildi."</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">CancellationToken</code>, uzun süren işlemin kontrollü biçimde durdurulmasını sağlar. <code class="language-plaintext highlighter-rouge">await</code> edilen görev hata üretirse istisna normal bir senkron metottaki gibi <code class="language-plaintext highlighter-rouge">try/catch</code> ile yakalanabilir.</p>

<h2 id="paylaşılan-veriler-ve-yarış-durumları">Paylaşılan veriler ve yarış durumları</h2>

<p>Birden fazla görev aynı değişkeni değiştirirse sonuç öngörülemez olabilir. Örneğin <code class="language-plaintext highlighter-rouge">sayac++</code> atomik değildir; okuma, artırma ve yazma adımlarından oluşur. Güvenli artırma için <code class="language-plaintext highlighter-rouge">Interlocked.Increment(ref sayac)</code> veya daha karmaşık kritik bölgelerde <code class="language-plaintext highlighter-rouge">lock</code> kullanılmalıdır.</p>

<p>Modern C# kodunda temel yaklaşım basittir: I/O ağırlıklı işlemlerde doğal asenkron API’leri <code class="language-plaintext highlighter-rouge">await</code> edin, CPU ağırlıklı ve bağımsız hesaplamalarda TPL kullanın, paylaşılan durumu azaltın ve performans kararlarını mutlaka ölçümlerle doğrulayın.</p>

<p><img src="/img/c-ile-multithreading-31.svg" alt="c-ile-multithreading-31" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="csharp" /><category term="multithreading" /><category term="tpl" /><category term="async" /><category term="await" /><category term="paralel-programlama" /><summary type="html"><![CDATA[Bir uygulamanın aynı anda birden fazla iş yapabilmesi kulağa sihir gibi gelebilir; ancak C# dünyasında bu sihrin arkasında iş parçacıkları, görevler ve dikkatli bir zamanlama mekanizması bulunur. Task Parallel Library (TPL) CPU ağırlıklı işleri paralelleştirirken async/await, özellikle dosya, ağ ve veritabanı gibi beklemeli işlemlerde iş parçacıklarını gereksiz yere meşgul etmeden ölçeklenebilir uygulamalar kurmamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-ile-multithreading-31.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-ile-multithreading-31.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ RTTI ve Güvenli Tür Dönüşümleri: Nesnenin Gerçek Kimliğini Bulmak</title><link href="https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak/" rel="alternate" type="text/html" title="C++ RTTI ve Güvenli Tür Dönüşümleri: Nesnenin Gerçek Kimliğini Bulmak" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-rtti-ve-guvenli-tur-donusumleri-nesnenin-gercek-kimligini-bulmak/"><![CDATA[<p><img src="/img/c-rtti-ve-63.svg" alt="c-rtti-ve-63" /></p>

<p>C++ dünyasında bir nesne her zaman göründüğü şey olmayabilir. Elinizde <code class="language-plaintext highlighter-rouge">Karakter*</code> türünde bir işaretçi bulunurken, işaret edilen gerçek nesne bir <code class="language-plaintext highlighter-rouge">Buyucu</code> veya <code class="language-plaintext highlighter-rouge">Savasci</code> olabilir. Çalışma Zamanı Tür Bilgisi, yani RTTI (Run-Time Type Information), program çalışırken bu gerçek kimliği öğrenmemizi ve kalıtım hiyerarşilerinde güvenli dönüşümler yapmamızı sağlar.
``</p>

<h2 id="rtti-neden-gereklidir">RTTI neden gereklidir?</h2>

<p>C++ değişkenlerinin çoğu tür bilgisi derleme zamanında bellidir. Ancak polimorfizm kullanıldığında statik tür ile dinamik tür birbirinden ayrılır:</p>

<ul>
  <li><strong>Statik tür:</strong> Değişkenin kaynak kodunda bildirilen türdür.</li>
  <li><strong>Dinamik tür:</strong> Çalışma anında gerçekten oluşturulmuş nesnenin türüdür.</li>
</ul>

<p>Bir <code class="language-plaintext highlighter-rouge">Karakter*</code> değişkeninin statik türü <code class="language-plaintext highlighter-rouge">Karakter*</code>, gösterdiği nesne <code class="language-plaintext highlighter-rouge">Buyucu</code> ise dinamik türü <code class="language-plaintext highlighter-rouge">Buyucu</code> olur. Bunu kabaca şu ilişkiyle gösterebiliriz:</p>

\[T_{statik} \neq T_{dinamik}\]

<p>RTTI özellikle taban sınıf üzerinden yönetilen nesnelerin alt sınıflarını ayırt etmek gerektiğinde devreye girer. Bunun çalışabilmesi için taban sınıfın <strong>polimorfik</strong> olması, yani en az bir sanal (<code class="language-plaintext highlighter-rouge">virtual</code>) fonksiyon içermesi gerekir. Genellikle sanal yıkıcı tanımlamak yeterlidir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">virtual</span> <span class="o">~</span><span class="n">Karakter</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Buyucu</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Karakter</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">buyuYap</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Ateş topu!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Sanal yıkıcı hem RTTI kullanımını mümkün kılar hem de nesne taban sınıf işaretçisi üzerinden silindiğinde doğru yıkıcının çağrılmasını sağlar.</p>

<h2 id="typeid-ile-türü-incelemek"><code class="language-plaintext highlighter-rouge">typeid</code> ile türü incelemek</h2>

<p><code class="language-plaintext highlighter-rouge">typeid</code> operatörü bir ifade veya tür hakkında <code class="language-plaintext highlighter-rouge">std::type_info</code> nesnesi döndürür. İki türün aynı olup olmadığı güvenilir biçimde karşılaştırılabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;typeinfo&gt;</span><span class="cp">
</span>
<span class="n">Karakter</span><span class="o">*</span> <span class="n">karakter</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Buyucu</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="k">typeid</span><span class="p">(</span><span class="o">*</span><span class="n">karakter</span><span class="p">)</span> <span class="o">==</span> <span class="k">typeid</span><span class="p">(</span><span class="n">Buyucu</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Bu karakter gerçekten bir büyücü.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">delete</span> <span class="n">karakter</span><span class="p">;</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">typeid(*karakter)</code> dinamik türü bulur. Buna karşılık <code class="language-plaintext highlighter-rouge">typeid(karakter)</code> işaretçinin kendi türünü, yani <code class="language-plaintext highlighter-rouge">Karakter*</code> türünü verir. <code class="language-plaintext highlighter-rouge">type_info::name()</code> da kullanılabilir; ancak döndürdüğü metnin biçimi derleyiciye bağlıdır ve program mantığı için güvenilir değildir.</p>

<h2 id="dynamic_cast-ile-güvenli-dönüşüm"><code class="language-plaintext highlighter-rouge">dynamic_cast</code> ile güvenli dönüşüm</h2>

<p><code class="language-plaintext highlighter-rouge">dynamic_cast</code>, polimorfik kalıtım hiyerarşilerinde çalışma zamanı kontrolü yapar. İşaretçi dönüşümü başarısız olursa <code class="language-plaintext highlighter-rouge">nullptr</code> döndürür:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Karakter</span><span class="o">*</span> <span class="n">karakter</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Buyucu</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="n">Buyucu</span><span class="o">*</span> <span class="n">buyucu</span> <span class="o">=</span> <span class="k">dynamic_cast</span><span class="o">&lt;</span><span class="n">Buyucu</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">karakter</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">buyucu</span><span class="o">-&gt;</span><span class="n">buyuYap</span><span class="p">();</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Bu karakter büyü yapamaz.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

 <span class="k">delete</span> <span class="n">karakter</span><span class="p">;</span>
</code></pre></div></div>

<p>Referanslarda başarısızlık <code class="language-plaintext highlighter-rouge">nullptr</code> ile bildirilemez. Bu nedenle <code class="language-plaintext highlighter-rouge">dynamic_cast&lt;Buyucu&amp;&gt;</code> başarısız olduğunda <code class="language-plaintext highlighter-rouge">std::bad_cast</code> istisnası fırlatır.</p>

<h2 id="dönüşüm-araçlarının-karşılaştırması">Dönüşüm araçlarının karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Araç</th>
      <th>Kontrol zamanı</th>
      <th>Başarısızlık davranışı</th>
      <th>Tipik kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">dynamic_cast</code></td>
      <td>Çalışma zamanı</td>
      <td><code class="language-plaintext highlighter-rouge">nullptr</code> veya <code class="language-plaintext highlighter-rouge">std::bad_cast</code></td>
      <td>Güvenli aşağı dönüşüm</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">static_cast</code></td>
      <td>Derleme zamanı</td>
      <td>Otomatik güvenlik kontrolü yok</td>
      <td>Bilinen ve mantıksal dönüşümler</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const_cast</code></td>
      <td>Derleme zamanı</td>
      <td><code class="language-plaintext highlighter-rouge">const</code> niteliğini değiştirir</td>
      <td>Eski API uyumluluğu</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">reinterpret_cast</code></td>
      <td>Derleme zamanı</td>
      <td>Bit düzeyinde riskli yorumlama</td>
      <td>Düşük seviyeli sistem kodu</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">typeid</code></td>
      <td>Çalışma zamanı</td>
      <td>Tür bilgisi döndürür</td>
      <td>Gerçek türü karşılaştırma</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">static_cast</code> ile aşağı dönüşüm yapılabilir, fakat nesne hedef türde değilse davranış tanımsız olabilir. Başka bir deyişle hız uğruna emniyet kemerini çıkarmış olursunuz.</p>

<h2 id="tasarım-açısından-son-notlar">Tasarım açısından son notlar</h2>

<p>RTTI kullanışlıdır ancak her nesnenin türünü sürekli sorgulamak tasarım kokusuna dönüşebilir. Çoğu durumda sanal fonksiyonlar daha temiz bir çözüm sunar: nesneye “Sen büyücü müsün?” diye sormak yerine doğrudan <code class="language-plaintext highlighter-rouge">eylemYap()</code> çağrısı yapılabilir.</p>

<p>Yine de eklenti sistemleri, nesne editörleri ve heterojen koleksiyonlar gibi alanlarda RTTI oldukça değerlidir. Kural basittir: Tür gerçekten belirsizse <code class="language-plaintext highlighter-rouge">dynamic_cast</code>, davranış polimorfik biçimde ifade edilebiliyorsa sanal fonksiyon kullanın. Böylece C++ nesneleri maskelerini çıkarsa bile programınız şaşırmaz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="rtti" /><category term="dynamic-cast" /><category term="typeid" /><category term="tür-dönüşümü" /><category term="nesne-yönelimli-programlama" /><summary type="html"><![CDATA[C++ dünyasında bir nesne her zaman göründüğü şey olmayabilir. Elinizde Karakter* türünde bir işaretçi bulunurken, işaret edilen gerçek nesne bir Buyucu veya Savasci olabilir. Çalışma Zamanı Tür Bilgisi, yani RTTI (Run-Time Type Information), program çalışırken bu gerçek kimliği öğrenmemizi ve kalıtım hiyerarşilerinde güvenli dönüşümler yapmamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-rtti-ve-63.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-rtti-ve-63.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ STL’de Iterator Geçersizliği: erase Tuzağından Güvenle Kaçış</title><link href="https://program.sonsuz.us/posts/c-stlde-iterator-gecersizligi-erase-tuzagindan-guvenle-kacis/" rel="alternate" type="text/html" title="C++ STL’de Iterator Geçersizliği: erase Tuzağından Güvenle Kaçış" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-stlde-iterator-gecersizligi-erase-tuzagindan-guvenle-kacis</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-stlde-iterator-gecersizligi-erase-tuzagindan-guvenle-kacis/"><![CDATA[<p>Bir STL konteynerinde dolaşırken eleman silmek, ilk bakışta son derece masum görünür. Ancak yanlış kullanılan tek bir <code class="language-plaintext highlighter-rouge">erase</code>, yineleyiciyi geçersiz hâle getirerek tanımsız davranışa, atlanan elemanlara veya yalnızca cuma akşamları ortaya çıkan gizemli çökmelere neden olabilir. Bu tuzağın kaynağı, her konteynerin elemanlarını bellekte farklı biçimde saklamasıdır.</p>

<p>``</p>

<h2 id="iterator-neden-geçersiz-olur">Iterator neden geçersiz olur?</h2>

<p>Iterator, çoğu zaman bir elemana ulaşmayı sağlayan adres benzeri bir nesnedir. Bir eleman silindiğinde konteyner, belleğini yeniden düzenleyebilir. Iterator artık yaşayan bir elemana işaret etmiyorsa onu karşılaştırmak, artırmak veya dereference etmek güvenli değildir.</p>

<p>Örneğin <code class="language-plaintext highlighter-rouge">vector</code>, elemanlarını ardışık bellekte tutar. İndisi $i$ olan eleman silindiğinde arkasındaki yaklaşık</p>

\[n-i-1\]

<p>eleman sola taşınır. Böylece silinen elemanı ve sonrasını gösteren iterator’lar geçersizleşir. İşlemin zaman karmaşıklığı da bu taşıma nedeniyle genel olarak $O(n)$ olur.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sayilar</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
<span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">+</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 3</span>

<span class="n">sayilar</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span>
<span class="c1">// it artık geçersizdir!</span>
<span class="c1">// std::cout &lt;&lt; *it; // Tanımsız davranış</span>
</code></pre></div></div>

<p>Buradaki yaygın yanılgı, <code class="language-plaintext highlighter-rouge">it</code> değişkeninin otomatik olarak sıradaki elemana geçeceğini düşünmektir. Oysa <code class="language-plaintext highlighter-rouge">erase</code>, eski iterator’ı onarmaz; bunun yerine geçerli olan sonraki iterator’ı döndürür.</p>

<h2 id="güvenli-silme-deseni">Güvenli silme deseni</h2>

<p>Dolaşma sırasında silme yapılacaksa <code class="language-plaintext highlighter-rouge">erase</code> dönüş değeri kullanılmalıdır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sayilar</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span>

<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> <span class="n">it</span> <span class="o">!=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">end</span><span class="p">();</span> <span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">it</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">it</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span> <span class="c1">// Sonraki geçerli konumu al</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="o">++</span><span class="n">it</span><span class="p">;</span>                   <span class="c1">// Yalnızca silinmediyse ilerle</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Döngünün üçüncü bölümü özellikle boş bırakılmıştır. Hem <code class="language-plaintext highlighter-rouge">erase</code> sonrasında hem de döngü sonunda <code class="language-plaintext highlighter-rouge">++it</code> çalıştırılsaydı bir eleman atlanabilirdi.</p>

<h2 id="konteynerlere-göre-kurallar">Konteynerlere göre kurallar</h2>

<table>
  <thead>
    <tr>
      <th>Konteyner</th>
      <th>Silme sonrası genel iterator durumu</th>
      <th style="text-align: right">Silme maliyeti</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">vector</code></td>
      <td>Silinen ve sonrasındaki iterator’lar geçersiz</td>
      <td style="text-align: right">$O(n)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">deque</code></td>
      <td>Ortadan silmede çoğunlukla tüm iterator’lar geçersiz</td>
      <td style="text-align: right">$O(n)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">list</code>, <code class="language-plaintext highlighter-rouge">forward_list</code></td>
      <td>Yalnızca silinen elemana ait iterator geçersiz</td>
      <td style="text-align: right">$O(1)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">map</code>, <code class="language-plaintext highlighter-rouge">set</code></td>
      <td>Yalnızca silinen elemana ait iterator geçersiz</td>
      <td style="text-align: right">$O(\log n)$</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">unordered_map</code>, <code class="language-plaintext highlighter-rouge">unordered_set</code></td>
      <td>Genellikle yalnızca silinen elemana ait iterator geçersiz</td>
      <td style="text-align: right">Ortalama $O(1)$</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/c-stlde-iterator-54.svg" alt="c-stlde-iterator-54" /></p>

<p><code class="language-plaintext highlighter-rouge">list</code> düğüm tabanlı olduğu için bir düğümün çıkarılması diğer düğümlerin adreslerini değiştirmez. <code class="language-plaintext highlighter-rouge">map</code> ve <code class="language-plaintext highlighter-rouge">set</code> gibi ağaç tabanlı yapılarda da benzer bir güvence vardır. Buna rağmen silinen iterator’ın kendisini kullanmak her durumda hatadır.</p>

<p><code class="language-plaintext highlighter-rouge">deque</code> daha dikkatli ele alınmalıdır: Baştan veya sondan silmenin kuralları daha sınırlı etkiler doğurabilirken ortadan silme, iterator’ları geniş ölçüde geçersizleştirir. Kodun taşınabilir ve anlaşılır olması için daima <code class="language-plaintext highlighter-rouge">erase</code> dönüş değerini kullanmak en güvenli yaklaşımdır.</p>

<h2 id="modern-c-ile-erase_if">Modern C++ ile erase_if</h2>

<p>Amaç yalnızca koşula uyan elemanları temizlemekse C++20, iterator yönetimini gizleyen daha okunaklı bir araç sunar:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">sayilar</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">erase_if</span><span class="p">(</span><span class="n">sayilar</span><span class="p">,</span> <span class="p">[](</span><span class="kt">int</span> <span class="n">deger</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">deger</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Eski standartlarda <code class="language-plaintext highlighter-rouge">vector</code> için erase-remove deyimi kullanılır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sayilar</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span>
    <span class="n">std</span><span class="o">::</span><span class="n">remove_if</span><span class="p">(</span><span class="n">sayilar</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">sayilar</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
                   <span class="p">[](</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}),</span>
    <span class="n">sayilar</span><span class="p">.</span><span class="n">end</span><span class="p">()</span>
<span class="p">);</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">remove_if</code> fiziksel silme yapmaz; korunacak elemanları öne taşır ve mantıksal yeni sonu döndürür. Asıl küçültmeyi <code class="language-plaintext highlighter-rouge">erase</code> gerçekleştirir.</p>

<p>Kısa kural şudur: Bir silme işleminden sonra eski iterator’ın hâlâ geçerli olduğunu varsayma. Konteynerin geçersizleştirme kurallarını kontrol et, mümkünse <code class="language-plaintext highlighter-rouge">erase</code> tarafından döndürülen iterator’ı kullan ve toplu koşullu silmelerde <code class="language-plaintext highlighter-rouge">std::erase_if</code> tercih et. Böylece iterator’ların hayaletlere dönüşmesini engellersin.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="stl" /><category term="iterator" /><category term="konteynerler" /><category term="erase" /><category term="bellek" /><summary type="html"><![CDATA[Bir STL konteynerinde dolaşırken eleman silmek, ilk bakışta son derece masum görünür. Ancak yanlış kullanılan tek bir erase, yineleyiciyi geçersiz hâle getirerek tanımsız davranışa, atlanan elemanlara veya yalnızca cuma akşamları ortaya çıkan gizemli çökmelere neden olabilir. Bu tuzağın kaynağı, her konteynerin elemanlarını bellekte farklı biçimde saklamasıdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-stlde-iterator-54.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-stlde-iterator-54.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">grep, sed ve awk: Metin İşlerken Doğru Aleti Seçme Rehberi</title><link href="https://program.sonsuz.us/posts/grep-sed-ve-awk-metin-islerken-dogru-aleti-secme-rehberi/" rel="alternate" type="text/html" title="grep, sed ve awk: Metin İşlerken Doğru Aleti Seçme Rehberi" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/grep-sed-ve-awk-metin-islerken-dogru-aleti-secme-rehberi</id><content type="html" xml:base="https://program.sonsuz.us/posts/grep-sed-ve-awk-metin-islerken-dogru-aleti-secme-rehberi/"><![CDATA[<p>Komut satırında her metin problemi bir çivi gibi görünüyorsa, elimizdeki ilk komutu çekiç olarak kullanmak cazip gelir. Böylece <code class="language-plaintext highlighter-rouge">grep</code> ile hesap yapmaya, <code class="language-plaintext highlighter-rouge">sed</code> ile sütun toplamaya veya <code class="language-plaintext highlighter-rouge">awk</code> ile yalnızca bir kelime aramaya çalışırız. Sonuç bazen çalışır; fakat okunabilirlik, taşınabilirlik ve bakım kolaylığı sessizce pencereden kaçar.</p>

<p><img src="/img/grep-sed-ve-18.svg" alt="grep-sed-ve-18" /></p>

<p>``</p>
<h2 id="üç-aracın-temel-zihinsel-modeli">Üç aracın temel zihinsel modeli</h2>

<p>Bu araçların hepsi standart girdiyi okuyabilir ve boru hatlarında kullanılabilir; ancak metne farklı gözlüklerle bakarlar.</p>

<ul>
  <li><strong>grep</strong>, satırların belirli bir desene uyup uymadığıyla ilgilenir.</li>
  <li><strong>sed</strong>, metni satır satır dönüştüren bir akış düzenleyicisidir.</li>
  <li><strong>awk</strong>, kayıtları alanlara ayırıp koşul, değişken ve aritmetik kullanabilen küçük bir programlama dilidir.</li>
</ul>

<p>Bir dosyada $n$ satır, her satırda ortalama $m$ karakter varsa basit tarama maliyeti kabaca $O(nm)$ olur. Araç seçiminin asıl farkı çoğunlukla teorik karmaşıklık değil, aynı işi ifade etmek için gereken zihinsel ve sözdizimsel karmaşıklıktır.</p>

<table>
  <thead>
    <tr>
      <th>Görev</th>
      <th>Doğru başlangıç aracı</th>
      <th>Temel güç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Eşleşen satırları bulmak</td>
      <td><code class="language-plaintext highlighter-rouge">grep</code></td>
      <td>Düzenli ifadeyle filtreleme</td>
    </tr>
    <tr>
      <td>Metni değiştirmek veya silmek</td>
      <td><code class="language-plaintext highlighter-rouge">sed</code></td>
      <td>Akış üzerinde dönüşüm</td>
    </tr>
    <tr>
      <td>Sütunları işlemek ve hesaplamak</td>
      <td><code class="language-plaintext highlighter-rouge">awk</code></td>
      <td>Alanlar, koşullar ve aritmetik</td>
    </tr>
  </tbody>
</table>

<h2 id="grep-ile-tornavida-kullanmak">grep ile tornavida kullanmak</h2>

<p><code class="language-plaintext highlighter-rouge">grep</code> yalnızca eşleşen satırları seçmek için mükemmeldir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="nt">-i</span> <span class="s2">"error"</span> app.log
</code></pre></div></div>

<p>Bu komut, büyük-küçük harfi önemsemeden <code class="language-plaintext highlighter-rouge">error</code> içeren satırları getirir. Fakat ikinci sütundaki değerleri toplamak istiyorsak <code class="language-plaintext highlighter-rouge">grep</code>, görevi tek başına doğal biçimde ifade edemez. Karmaşık <code class="language-plaintext highlighter-rouge">grep</code>, <code class="language-plaintext highlighter-rouge">cut</code>, <code class="language-plaintext highlighter-rouge">paste</code> ve <code class="language-plaintext highlighter-rouge">bc</code> zincirleri kurulabilir; ancak bu, market alışverişine forkliftle gitmeye benzer.</p>

<p>Doğal çözüm <code class="language-plaintext highlighter-rouge">awk</code> kullanmaktır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'{ toplam += $2 } END { print toplam }'</span> satis.txt
</code></pre></div></div>

<p>Burada her satır bir kayıt, boşluklarla ayrılmış parçalar ise alan kabul edilir. <code class="language-plaintext highlighter-rouge">$2</code> ikinci alanı, <code class="language-plaintext highlighter-rouge">END</code> ise bütün kayıtlar işlendikten sonraki aşamayı temsil eder.</p>

<h2 id="sed-ile-muhasebe-yapmaya-çalışmak">sed ile muhasebe yapmaya çalışmak</h2>

<p><code class="language-plaintext highlighter-rouge">sed</code>, değiştirme işlemlerinde parlar:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sed</span> <span class="s1">'s/http:/https:/g'</span> adresler.txt
</code></pre></div></div>

<p>Komut, her satırdaki tüm <code class="language-plaintext highlighter-rouge">http:</code> ifadelerini <code class="language-plaintext highlighter-rouge">https:</code> ile değiştirir. Buna karşılık sayısal karşılaştırma, toplam veya ortalama gerektiğinde <code class="language-plaintext highlighter-rouge">sed</code> komutları hızla anlaşılmaz hâle gelir.</p>

<p>Örneğin üçüncü sütunu 100’den büyük kayıtları seçmek için doğru yaklaşım şudur:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'$3 &gt; 100 { print $1, $3 }'</span> veriler.txt
</code></pre></div></div>

<p>Ortalama hesaplamak da doğrudandır. Değerlerin toplamı $S$, kayıt sayısı $N$ ise ortalama</p>

\[\bar{x} = \frac{S}{N}\]

<p>olur:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'{ s += $3; n++ } END { if (n) print s / n }'</span> veriler.txt
</code></pre></div></div>

<h2 id="awk-ile-basit-aramayı-büyütmek">awk ile basit aramayı büyütmek</h2>

<p><code class="language-plaintext highlighter-rouge">awk '/hata/' app.log</code> geçerli bir komuttur; fakat yalnızca eşleşen satırları istiyorsak niyetimizi <code class="language-plaintext highlighter-rouge">grep 'hata' app.log</code> daha açık anlatır. <code class="language-plaintext highlighter-rouge">awk</code>, alan seçimi veya ek mantık devreye girdiğinde anlam kazanır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">awk</span> <span class="s1">'$2 == "ERROR" &amp;&amp; $4 &gt;= 500 { print $1, $4 }'</span> app.log
</code></pre></div></div>

<p>Bu örnek hem alan karşılaştırır hem sayısal koşul uygular. Yani <code class="language-plaintext highlighter-rouge">awk</code> burada gerçekten maaşını hak eder.</p>

<h2 id="araçlar-rakip-değil-ekip-arkadaşıdır">Araçlar rakip değil, ekip arkadaşıdır</h2>

<p>Tek bir komuta bütün işi yüklemek zorunda değiliz. Önce ilgili satırları filtreleyip sonra metni dönüştürebiliriz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">grep</span> <span class="s1">'^WARN'</span> app.log | <span class="nb">sed</span> <span class="s1">'s/^WARN/UYARI/'</span>
</code></pre></div></div>

<p>Yine de gereksiz süreçlerden kaçınmak gerekir. Aynı işlem tek ve anlaşılır bir <code class="language-plaintext highlighter-rouge">awk</code> programıyla yapılabiliyorsa uzun boru hattı kurmak hata ayıklamayı zorlaştırabilir.</p>

<p>Pratik karar kuralı basittir: <strong>Buluyorsan grep, değiştiriyorsan sed, alanlar üzerinde düşünüyor veya hesaplıyorsan awk.</strong> Görev büyüdükçe kabuk komutlarını zorlamak yerine Python gibi genel amaçlı bir dile geçmek de yenilgi değil, doğru mühendislik kararıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="shell" /><category term="grep" /><category term="sed" /><category term="awk" /><category term="linux" /><category term="metin işleme" /><summary type="html"><![CDATA[Komut satırında her metin problemi bir çivi gibi görünüyorsa, elimizdeki ilk komutu çekiç olarak kullanmak cazip gelir. Böylece grep ile hesap yapmaya, sed ile sütun toplamaya veya awk ile yalnızca bir kelime aramaya çalışırız. Sonuç bazen çalışır; fakat okunabilirlik, taşınabilirlik ve bakım kolaylığı sessizce pencereden kaçar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/grep-sed-ve-18.png" /><media:content medium="image" url="https://program.sonsuz.us/img/grep-sed-ve-18.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Java İstisna Yönetimi: try, catch ve finally ile Güvenli Kod</title><link href="https://program.sonsuz.us/posts/java-istisna-yonetimi-try-catch-ve-finally-ile-guvenli-kod/" rel="alternate" type="text/html" title="Java İstisna Yönetimi: try, catch ve finally ile Güvenli Kod" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/java-istisna-yonetimi-try-catch-ve-finally-ile-guvenli-kod</id><content type="html" xml:base="https://program.sonsuz.us/posts/java-istisna-yonetimi-try-catch-ve-finally-ile-guvenli-kod/"><![CDATA[<p>Bir uygulamada her şey planlandığı gibi gitmez: Dosya bulunamaz, kullanıcı sayı yerine metin girer veya ağ bağlantısı aniden kesilir. Java istisna yönetimi, bu beklenmeyen durumları kontrollü biçimde karşılayarak programın dramatik bir şekilde sahneden düşmesini engeller. Amaç hataları gizlemek değil; onları anlamlı, izlenebilir ve güvenli bir akış içinde yönetmektir.
``</p>
<h2 id="i̇stisna-nedir">İstisna nedir?</h2>

<p>İstisna, programın normal çalışma akışını bozan bir olaydır. Java’da istisnalar nesne olarak temsil edilir ve temel olarak <code class="language-plaintext highlighter-rouge">Throwable</code> sınıfından türetilir. Bir sorun oluştuğunda istisna “fırlatılır”; uygun bir yönetici bulunduğunda ise “yakalanır”.</p>

<p>Bu davranışı basitçe şöyle düşünebiliriz:</p>

\[\text{Güvenli Akış} = \text{Riskli İşlem} + \text{Hata Yakalama} + \text{Temizlik}\]

<p>Java’daki hata hiyerarşisinin iki önemli kolu vardır:</p>

<table>
  <thead>
    <tr>
      <th>Tür</th>
      <th>Açıklama</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Checked exception</td>
      <td>Derleyicinin yönetilmesini zorunlu tuttuğu istisnalardır</td>
      <td><code class="language-plaintext highlighter-rouge">IOException</code>, <code class="language-plaintext highlighter-rouge">SQLException</code></td>
    </tr>
    <tr>
      <td>Unchecked exception</td>
      <td>Genellikle programlama hatalarından doğar</td>
      <td><code class="language-plaintext highlighter-rouge">NullPointerException</code>, <code class="language-plaintext highlighter-rouge">ArithmeticException</code></td>
    </tr>
    <tr>
      <td>Error</td>
      <td>Uygulamanın çoğunlukla düzeltemeyeceği ciddi JVM sorunlarıdır</td>
      <td><code class="language-plaintext highlighter-rouge">OutOfMemoryError</code></td>
    </tr>
  </tbody>
</table>

<p><img src="/img/java-istisna-yonetimi-75.svg" alt="java-istisna-yonetimi-75" /></p>

<h2 id="try-ve-catch-nasıl-çalışır">try ve catch nasıl çalışır?</h2>

<p>Risk oluşturabilecek kod <code class="language-plaintext highlighter-rouge">try</code> bloğuna yazılır. Bir istisna meydana gelirse Java, ilgili türü karşılayan <code class="language-plaintext highlighter-rouge">catch</code> bloğunu arar. Böylece uygulama tamamen sonlanmak yerine alternatif bir davranış gösterebilir.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">BolmeOrnegi</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">int</span> <span class="n">bolunen</span> <span class="o">=</span> <span class="mi">24</span><span class="o">;</span>
        <span class="kt">int</span> <span class="n">bolen</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>

        <span class="k">try</span> <span class="o">{</span>
            <span class="kt">int</span> <span class="n">sonuc</span> <span class="o">=</span> <span class="n">bolunen</span> <span class="o">/</span> <span class="n">bolen</span><span class="o">;</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Sonuç: "</span> <span class="o">+</span> <span class="n">sonuc</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">ArithmeticException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Bir sayı sıfıra bölünemez."</span><span class="o">);</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Teknik ayrıntı: "</span> <span class="o">+</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
        <span class="o">}</span>

        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Program çalışmaya devam ediyor."</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Burada sıfıra bölme işlemi <code class="language-plaintext highlighter-rouge">ArithmeticException</code> üretir. <code class="language-plaintext highlighter-rouge">catch</code> bloğu hatayı yakalar, kullanıcıya anlaşılır bir mesaj verir ve programın sonraki satırlara devam etmesini sağlar.</p>

<p>Birden fazla hata türü için birden fazla <code class="language-plaintext highlighter-rouge">catch</code> kullanılabilir. Ancak özel istisnalar önce, daha genel olanlar sonra yazılmalıdır. Aksi hâlde genel blok diğerlerini erişilemez yapabilir.</p>

<h2 id="finally-neden-kullanılır">finally neden kullanılır?</h2>

<p><code class="language-plaintext highlighter-rouge">finally</code> bloğu, istisna oluşsa da oluşmasa da çalıştırılması gereken işlemler içindir. Dosya kapatmak, bağlantıyı sonlandırmak veya geçici kaynakları temizlemek klasik kullanım örnekleridir.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Veritabanı işlemi başlatıldı."</span><span class="o">);</span>
    <span class="c1">// Riskli sorgular burada çalıştırılır.</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">RuntimeException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"İşlem başarısız: "</span> <span class="o">+</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Bağlantı ve kaynaklar temizleniyor."</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Blok</th>
      <th>Ne zaman çalışır?</th>
      <th>Temel görevi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">try</code></td>
      <td>Her zaman ilk olarak</td>
      <td>Riskli kodu çalıştırmak</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">catch</code></td>
      <td>Eşleşen istisna oluşursa</td>
      <td>Hatayı kontrollü biçimde ele almak</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">finally</code></td>
      <td>Normalde her durumda</td>
      <td>Kaynakları temizlemek</td>
    </tr>
  </tbody>
</table>

<p>Modern Java’da dosya ve benzeri <code class="language-plaintext highlighter-rouge">AutoCloseable</code> kaynaklar için <code class="language-plaintext highlighter-rouge">try-with-resources</code> daha güvenlidir:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">okuyucu</span> <span class="o">=</span> <span class="k">new</span> <span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">BufferedReader</span><span class="o">(</span>
        <span class="k">new</span> <span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">FileReader</span><span class="o">(</span><span class="s">"veriler.txt"</span><span class="o">)))</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">okuyucu</span><span class="o">.</span><span class="na">readLine</span><span class="o">());</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Dosya okunamadı: "</span> <span class="o">+</span> <span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">());</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Bu yapı, okuyucuyu otomatik kapatır ve unutulan kaynaklar yüzünden oluşabilecek sızıntıları azaltır.</p>

<h2 id="sağlam-istisna-yönetimi-için-ipuçları">Sağlam istisna yönetimi için ipuçları</h2>

<ul>
  <li>Boş bir <code class="language-plaintext highlighter-rouge">catch</code> bloğu kullanarak hatayı sessizce yutmayın.</li>
  <li>Kullanıcıya anlaşılır, geliştiriciye ayrıntılı günlük mesajları sağlayın.</li>
  <li>Yalnızca gerçekten yönetebileceğiniz istisnaları yakalayın.</li>
  <li><code class="language-plaintext highlighter-rouge">Exception</code> gibi aşırı genel türleri gereksiz yere kullanmayın.</li>
  <li>İstisnaları normal karar mekanizması yerine koymayın.</li>
</ul>

<p>İyi tasarlanmış istisna yönetimi, uygulamanın hiç hata vermemesi anlamına gelmez. Asıl başarı; hata geldiğinde paniklemeyen, kaynaklarını temizleyen, kullanıcıyı bilgilendiren ve mümkünse güvenli biçimde yoluna devam eden bir sistem kurmaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="java" /><category term="exception" /><category term="hata-yönetimi" /><category term="try-catch" /><category term="finally" /><category term="programlama" /><summary type="html"><![CDATA[Bir uygulamada her şey planlandığı gibi gitmez: Dosya bulunamaz, kullanıcı sayı yerine metin girer veya ağ bağlantısı aniden kesilir. Java istisna yönetimi, bu beklenmeyen durumları kontrollü biçimde karşılayarak programın dramatik bir şekilde sahneden düşmesini engeller. Amaç hataları gizlemek değil; onları anlamlı, izlenebilir ve güvenli bir akış içinde yönetmektir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/java-istisna-yonetimi-75.png" /><media:content medium="image" url="https://program.sonsuz.us/img/java-istisna-yonetimi-75.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotik PID Tuning: Aşırı Salınım ile Yavaş Tepki Arasındaki İnce Denge</title><link href="https://program.sonsuz.us/posts/robotik-pid-tuning-asiri-salinim-ile-yavas-tepki-arasindaki-ince-denge/" rel="alternate" type="text/html" title="Robotik PID Tuning: Aşırı Salınım ile Yavaş Tepki Arasındaki İnce Denge" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotik-pid-tuning-asiri-salinim-ile-yavas-tepki-arasindaki-ince-denge</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotik-pid-tuning-asiri-salinim-ile-yavas-tepki-arasindaki-ince-denge/"><![CDATA[<p>Bir robot kolunun hedef konuma yıldırım gibi ulaşıp birkaç kez ileri geri sallanması mı, yoksa ağır çekimde ilerleyerek hedefi şaşmadan bulması mı daha iyidir? PID kontrolcü ayarlarken karşılaşılan temel ikilem tam olarak budur: hızlı tepki ile düşük aşım arasında dengeli bir nokta bulmak.</p>

<p>``</p>

<p>PID kontrolcü, ölçülen durum ile hedef arasındaki hatayı kullanarak eyleyiciye uygulanacak komutu hesaplar. Temel denklem şöyledir:</p>

\[u(t)=K_p e(t)+K_i ∫_0^t e(τ)dτ+K_d\frac{de(t)}{dt}\]

<p>Burada $e(t)$ hedef ile ölçüm arasındaki farktır. $K_p$ anlık hataya, $K_i$ geçmişte biriken hataya, $K_d$ ise hatanın değişim hızına tepki verir. Üç kazanç birlikte çalışır; fakat her biri robotun davranışını farklı yönde iter.</p>

<table>
  <thead>
    <tr>
      <th>Kazanç</th>
      <th>Artırıldığında genel etki</th>
      <th>Olası yan etki</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$K_p$</td>
      <td>Yükselme süresi kısalır</td>
      <td>Aşım ve salınım artabilir</td>
    </tr>
    <tr>
      <td>$K_i$</td>
      <td>Kalıcı durum hatası azalır</td>
      <td>Aşım, integral yığılması ve oturma süresi artabilir</td>
    </tr>
    <tr>
      <td>$K_d$</td>
      <td>Salınım sönümlenir</td>
      <td>Sensör gürültüsü büyütülebilir</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/robotik-pid-tuning-34.svg" alt="robotik-pid-tuning-34" /></p>

<h2 id="aşırı-salınım-neden-oluşur">Aşırı salınım neden oluşur?</h2>

<p>Yüksek $K_p$, robota “Hata büyük, daha sert hareket et!” der. Ancak motor ve mekanik sistem atalet taşır. Robot hedefe ulaştığında hareket enerjisi henüz kaybolmamıştır; bu nedenle hedefi geçer. Kontrolcü ters yönde komut verir ve süreç salınıma dönüşebilir. $K_i$ de geçmiş hataları toplamaya devam ederse hedefe varılmış olsa bile güçlü komut üretebilir. Buna <strong>integral windup</strong>, yani integral yığılması denir.</p>

<p>Yüzde aşım yaklaşık olarak şu şekilde ölçülür:</p>

\[M_p=\frac{y_{max}-y_{hedef}}{y_{hedef}}\times 100\]

<p>Örneğin hedef açı $90°$, görülen tepe değer $99°$ ise aşım yüzde 10’dur. Hassas bir kavrayıcı için bu oran tehlikeliyken, hızlı hareket eden basit bir mobil robot için kabul edilebilir olabilir.</p>

<h2 id="yavaş-tepki-neden-her-zaman-güvenli-değildir">Yavaş tepki neden her zaman güvenli değildir?</h2>

<p>Kazançları fazla düşük tutmak aşımı azaltabilir; ancak robot komutlara geç yanıt verir. Denge robotunda bu gecikme düşmeye, çizgi izleyen robotta parkurdan çıkmaya yol açabilir. Dolayısıyla yalnızca aşımı küçültmek yeterli değildir. Yükselme süresi, oturma süresi, kalıcı hata ve kontrol sinyalinin büyüklüğü birlikte değerlendirilmelidir.</p>

<table>
  <thead>
    <tr>
      <th>Öncelik</th>
      <th>Tercih edilen davranış</th>
      <th>Tipik yaklaşım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Hassas konumlama</td>
      <td>Düşük aşım</td>
      <td>Orta $K_p$, sınırlı $K_i$, yeterli $K_d$</td>
    </tr>
    <tr>
      <td>Hızlı takip</td>
      <td>Kısa yükselme süresi</td>
      <td>Daha yüksek $K_p$, kontrollü sönümleme</td>
    </tr>
    <tr>
      <td>Gürültülü sensör</td>
      <td>Kararlı kontrol sinyali</td>
      <td>Filtrelenmiş veya düşük $K_d$</td>
    </tr>
    <tr>
      <td>Sürekli yük hatası</td>
      <td>Sıfıra yakın kalıcı hata</td>
      <td>Anti-windup ile $K_i$ kullanımı</td>
    </tr>
  </tbody>
</table>

<h2 id="pratik-tuning-sırası">Pratik tuning sırası</h2>

<p>Önce $K_i$ ve $K_d$ sıfırlanır, ardından $K_p$ robot hızlı tepki verip salınım sınırına yaklaşana kadar artırılır. Sonra $K_d$ eklenerek hareket sönümlenir. En son küçük bir $K_i$, sürtünme veya yük nedeniyle kalan sabit hatayı temizlemek için kullanılır. Her değişiklikten sonra aynı hedef, yük ve başlangıç koşullarıyla test yapmak önemlidir.</p>

<p>Aşağıdaki Python kodu, ölçüm kayıtlarından aşım ve yaklaşık oturma süresini hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">def</span> <span class="nf">response_metrics</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">tolerance</span><span class="o">=</span><span class="mf">0.02</span><span class="p">):</span>
    <span class="n">output</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">asarray</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
    <span class="n">error</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">abs</span><span class="p">(</span><span class="n">output</span> <span class="o">-</span> <span class="n">target</span><span class="p">)</span>

    <span class="n">overshoot</span> <span class="o">=</span> <span class="nf">max</span><span class="p">(</span><span class="mf">0.0</span><span class="p">,</span> <span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="nf">max</span><span class="p">()</span> <span class="o">-</span> <span class="n">target</span><span class="p">)</span> <span class="o">/</span> <span class="nf">abs</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span>
    <span class="n">limit</span> <span class="o">=</span> <span class="n">tolerance</span> <span class="o">*</span> <span class="nf">abs</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>
    <span class="n">settling_time</span> <span class="o">=</span> <span class="bp">None</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">output</span><span class="p">)):</span>
        <span class="k">if</span> <span class="n">np</span><span class="p">.</span><span class="nf">all</span><span class="p">(</span><span class="n">error</span><span class="p">[</span><span class="n">i</span><span class="p">:]</span> <span class="o">&lt;=</span> <span class="n">limit</span><span class="p">):</span>
            <span class="n">settling_time</span> <span class="o">=</span> <span class="n">time</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
            <span class="k">break</span>

    <span class="k">return</span> <span class="p">{</span><span class="sh">'</span><span class="s">overshoot_percent</span><span class="sh">'</span><span class="p">:</span> <span class="n">overshoot</span><span class="p">,</span>
            <span class="sh">'</span><span class="s">settling_time</span><span class="sh">'</span><span class="p">:</span> <span class="n">settling_time</span><span class="p">}</span>
</code></pre></div></div>

<p>Kod, tepe değeri kullanarak yüzde aşımı bulur ve çıktının yüzde 2 tolerans bandında kalmaya başladığı zamanı oturma süresi kabul eder. Böylece tuning, “gözüme iyi göründü” yaklaşımından ölçülebilir bir optimizasyona dönüşür.</p>

<p>Sonuç olarak ideal PID ayarı evrensel değildir. Robotun kütlesi, motor gücü, sensör gürültüsü ve görevi denge noktasını belirler. İyi tuning, en hızlı veya en sakin hareketi değil; görevin izin verdiği aşım sınırında yeterince hızlı, kararlı ve güvenli tepkiyi hedefler.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="pid" /><category term="kontrol-sistemleri" /><category term="tuning" /><category term="otomasyon" /><category term="python" /><summary type="html"><![CDATA[Bir robot kolunun hedef konuma yıldırım gibi ulaşıp birkaç kez ileri geri sallanması mı, yoksa ağır çekimde ilerleyerek hedefi şaşmadan bulması mı daha iyidir? PID kontrolcü ayarlarken karşılaşılan temel ikilem tam olarak budur: hızlı tepki ile düşük aşım arasında dengeli bir nokta bulmak.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotik-pid-tuning-34.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotik-pid-tuning-34.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotlarda Holonomik ve Non-Holonomik Kısıtlar: Yol Planlamanın Görünmez Kuralları</title><link href="https://program.sonsuz.us/posts/robotlarda-holonomik-ve-non-holonomik-kisitlar-yol-planlamanin-gorunmez-kurallari/" rel="alternate" type="text/html" title="Robotlarda Holonomik ve Non-Holonomik Kısıtlar: Yol Planlamanın Görünmez Kuralları" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotlarda-holonomik-ve-non-holonomik-kisitlar-yol-planlamanin-gorunmez-kurallari</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotlarda-holonomik-ve-non-holonomik-kisitlar-yol-planlamanin-gorunmez-kurallari/"><![CDATA[<p>Bir robotun harita üzerinde boş bir nokta bulması, o noktaya gerçekten ulaşabileceği anlamına gelmez. Satranç taşları gibi robotların da hareket kuralları vardır: Holonomik robotlar yana kayabilirken non-holonomik robotlar çoğunlukla önce yönelmek, sonra ilerlemek zorundadır. Yol planlayıcı bu fiziksel gerçeği hesaba katmazsa kusursuz görünen rota, gerçek dünyada duvara sürtünen pahalı bir hayale dönüşebilir.</p>

<p>``</p>

<h2 id="hareket-kısıtı-ne-demektir">Hareket kısıtı ne demektir?</h2>

<p>Bir robotun konfigürasyonu genellikle</p>

\[q = (x, y, \theta)\]

<p>ile gösterilir. Burada $x$ ve $y$ konumu, $\theta$ ise yönelimi temsil eder. Robot üç boyutlu bir konfigürasyon uzayında bulunsa da her yönde anlık hız üretemeyebilir.</p>

<p>Bir kısıt yalnızca konfigürasyon değişkenleriyle</p>

\[f(q)=0\]

<p>şeklinde yazılabiliyorsa <strong>holonomik</strong> kabul edilir. Kısıt hızlara bağlıysa ve konum düzeyinde bütünleştirilemiyorsa non-holonomik davranış ortaya çıkar. Bu tür kısıtların yaygın gösterimi şöyledir:</p>

\[A(q)\dot{q}=0\]

<p>Örneğin diferansiyel sürüşlü bir robotun yana kaymama koşulu:</p>

\[-\sin(\theta)\dot{x}+\cos(\theta)\dot{y}=0\]

<p>biçimindedir. Denklem basitçe şunu söyler: Robotun tekerlek ekseni doğrultusunda yanal hızı yoktur. Yani robot araba park eder gibi birkaç manevra yapmak zorunda kalabilir.</p>

<h2 id="i̇ki-hareket-dünyasının-karşılaştırması">İki hareket dünyasının karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Holonomik robot</th>
      <th>Non-holonomik robot</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Anlık hareket</td>
      <td>Serbestlik derecelerinde bağımsız</td>
      <td>Belirli hız yönleriyle sınırlı</td>
    </tr>
    <tr>
      <td>Tipik örnek</td>
      <td>Omni veya mecanum tekerlekli platform</td>
      <td>Otomobil, bisiklet, diferansiyel robot</td>
    </tr>
    <tr>
      <td>Yana hareket</td>
      <td>Genellikle mümkün</td>
      <td>Doğrudan mümkün değil</td>
    </tr>
    <tr>
      <td>Planlama uzayı</td>
      <td>Çoğu zaman $(x,y)$ yeterli olabilir</td>
      <td>$(x,y,\theta)$ gerekir</td>
    </tr>
    <tr>
      <td>Rota biçimi</td>
      <td>Keskin dönüşler mümkün</td>
      <td>Eğrilik ve dönüş yarıçapı önemlidir</td>
    </tr>
    <tr>
      <td>Planlama maliyeti</td>
      <td>Görece düşük</td>
      <td>Daha yüksek</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/robotlarda-holonomik-ve-78.svg" alt="robotlarda-holonomik-ve-78" /></p>

<p>Holonomik bir platform için A* algoritması iki boyutlu ızgarada kısa bir yol bulabilir. Robot, gerektiğinde yönünü değiştirmeden yana kayabilir. Non-holonomik bir araçta ise aynı yol üzerindeki doksan derecelik köşe fiziksel olarak uygulanamayabilir.</p>

<h2 id="yol-planlamasına-etkisi">Yol planlamasına etkisi</h2>

<p>Non-holonomik planlamada yalnızca engellerden kaçmak yetmez. Planlayıcı; yönelim, minimum dönüş yarıçapı, geri hareket izni ve direksiyon sınırı gibi değişkenleri de değerlendirmelidir. Bu nedenle klasik A* yerine <strong>Hybrid A</strong>*, <strong>state lattice</strong>, <strong>RRT</strong>, <strong>RRT*</strong> veya Dubins ve Reeds–Shepp eğrileri kullanılabilir.</p>

<p>Dubins aracı yalnızca ileri hareket eder ve eğriliği sınırlıdır. Reeds–Shepp modeli ise geri vitese de izin verir. Böylece iki durum arasındaki mesafe, Öklid uzaklığından daha gerçekçi hesaplanır:</p>

\[d_{gerçek}(q_1,q_2) \geq d_{Öklid}(q_1,q_2)\]

<p>Çünkü kuş uçuşu en kısa çizgi, otomobil sürüşü açısından her zaman uygulanabilir değildir.</p>

<h2 id="basit-bir-kısıt-kontrolü">Basit bir kısıt kontrolü</h2>

<p>Aşağıdaki Python fonksiyonu, diferansiyel robotun verilen dünya hızlarında yanal kayma üretip üretmediğini denetler:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">math</span>

<span class="k">def</span> <span class="nf">hareket_gecerli_mi</span><span class="p">(</span><span class="n">theta</span><span class="p">,</span> <span class="n">vx</span><span class="p">,</span> <span class="n">vy</span><span class="p">,</span> <span class="n">tolerans</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">):</span>
    <span class="c1"># Robot gövdesine göre yanal hız bileşenini hesaplar.
</span>    <span class="n">yanal_hiz</span> <span class="o">=</span> <span class="o">-</span><span class="n">math</span><span class="p">.</span><span class="nf">sin</span><span class="p">(</span><span class="n">theta</span><span class="p">)</span> <span class="o">*</span> <span class="n">vx</span> <span class="o">+</span> <span class="n">math</span><span class="p">.</span><span class="nf">cos</span><span class="p">(</span><span class="n">theta</span><span class="p">)</span> <span class="o">*</span> <span class="n">vy</span>
    <span class="k">return</span> <span class="nf">abs</span><span class="p">(</span><span class="n">yanal_hiz</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">tolerans</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">hareket_gecerli_mi</span><span class="p">(</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">))</span>  <span class="c1"># True: ileri hareket
</span><span class="nf">print</span><span class="p">(</span><span class="nf">hareket_gecerli_mi</span><span class="p">(</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">))</span>  <span class="c1"># False: doğrudan yana kayma
</span></code></pre></div></div>

<p>Gerçek bir planlayıcı, komşu durum üretirken yalnızca bu koşulu test etmekle kalmaz; robotun hareket modelini kısa bir süre boyunca simüle eder. Örneğin</p>

\[\dot{x}=v\cos\theta,\qquad \dot{y}=v\sin\theta,\qquad \dot{\theta}=\omega\]

<p>modeliyle farklı $v$ ve $\omega$ komutları denenerek erişilebilir yeni düğümler oluşturulur. Böylece arama ağacındaki her bağlantı gerçekten uygulanabilir olur.</p>

<h2 id="sonuç">Sonuç</h2>

<p>Holonomik planlama geometrik olarak “Nereden geçebilirim?” sorusuna odaklanırken non-holonomik planlama buna “Oraya hangi yönelim ve manevrayla ulaşabilirim?” sorusunu ekler. Daha gerçekçi kısıtlar daha fazla hesaplama gerektirir; ancak uygulanamayan kısa bir yol yerine güvenli, pürüzsüz ve sürülebilir bir rota üretir. Robotik dünyasında en kısa yol bazen düz çizgi değil, doğru kıvrımdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="yol planlama" /><category term="holonomik" /><category term="non-holonomik" /><category term="kinematik" /><category term="otonom robotlar" /><summary type="html"><![CDATA[Bir robotun harita üzerinde boş bir nokta bulması, o noktaya gerçekten ulaşabileceği anlamına gelmez. Satranç taşları gibi robotların da hareket kuralları vardır: Holonomik robotlar yana kayabilirken non-holonomik robotlar çoğunlukla önce yönelmek, sonra ilerlemek zorundadır. Yol planlayıcı bu fiziksel gerçeği hesaba katmazsa kusursuz görünen rota, gerçek dünyada duvara sürtünen pahalı bir hayale dönüşebilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotlarda-holonomik-ve-78.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotlarda-holonomik-ve-78.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Shell Betiklerinde Sürpriz Ünlem: History Expansion Tuzağı</title><link href="https://program.sonsuz.us/posts/shell-betiklerinde-surpriz-unlem-history-expansion-tuzagi/" rel="alternate" type="text/html" title="Shell Betiklerinde Sürpriz Ünlem: History Expansion Tuzağı" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/shell-betiklerinde-surpriz-unlem-history-expansion-tuzagi</id><content type="html" xml:base="https://program.sonsuz.us/posts/shell-betiklerinde-surpriz-unlem-history-expansion-tuzagi/"><![CDATA[<p>Bir betik çalıştırıyorsunuz; parola, URL veya mesaj içinde sıradan bir <code class="language-plaintext highlighter-rouge">!</code> karakteri var. Birden terminal <code class="language-plaintext highlighter-rouge">event not found</code> diye bağırıyor ya da komutunuz beklenmedik biçimde değişiyor. Suçlu çoğu zaman Bash’in <strong>history expansion</strong> özelliğidir. Ünlem işareti kabuk için yalnızca heyecan belirtmez; geçmiş komutlara açılan gizli bir kapı da olabilir.</p>

<p><img src="/img/shell-betiklerinde-surpriz-33.svg" alt="shell-betiklerinde-surpriz-33" /></p>

<p>``</p>

<h2 id="history-expansion-nedir">History expansion nedir?</h2>

<p>Bash, etkileşimli kullanımda önceki komutları hızlıca çağırmak için <code class="language-plaintext highlighter-rouge">!</code> ile başlayan ifadeleri yorumlayabilir. Örneğin <code class="language-plaintext highlighter-rouge">!!</code> son komutu, <code class="language-plaintext highlighter-rouge">!42</code> geçmişteki 42 numaralı komutu, <code class="language-plaintext highlighter-rouge">!git</code> ise <code class="language-plaintext highlighter-rouge">git</code> ile başlayan son komutu temsil eder.</p>

<p>Bunu basitçe şu dönüşümle düşünebiliriz:</p>

\[\text{çalıştırılan komut} = H(\text{yazılan metin})\]

<p>Buradaki $H$, history expansion etkinse ünlem ifadelerini geçmişteki komutlarla değiştiren fonksiyondur. Özellik kapalıysa $H(x)=x$ olur; yani metin değişmeden kalır.</p>

<table>
  <thead>
    <tr>
      <th>Yazılan ifade</th>
      <th>Özellik açıkken olası anlamı</th>
      <th>Özellik kapalıyken</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">!!</code></td>
      <td>Son komut</td>
      <td>İki ünlem karakteri</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">!42</code></td>
      <td>42 numaralı geçmiş girdisi</td>
      <td>Değişmeden kalır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">!echo</code></td>
      <td>Son <code class="language-plaintext highlighter-rouge">echo</code> komutu</td>
      <td>Değişmeden kalır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">merhaba!</code></td>
      <td>Genellikle aynı kalır</td>
      <td>Aynı kalır</td>
    </tr>
  </tbody>
</table>

<p>Bash’in <strong>etkileşimli olmayan</strong> betiklerinde history expansion normalde kapalıdır. Ancak betik <code class="language-plaintext highlighter-rouge">source</code> ile etkileşimli bir kabuğa yüklenirse, <code class="language-plaintext highlighter-rouge">bash -H</code> ile başlatılırsa veya kod içinde <code class="language-plaintext highlighter-rouge">set -H</code> çalıştırılırsa özellik devreye girebilir. Bu yüzden “Betikte asla olmaz” varsayımı güvenli değildir.</p>

<h2 id="çifte-tırnak-her-zaman-korumaz">Çifte tırnak her zaman korumaz</h2>

<p>Shell programlamasında çifte tırnağın özel karakterleri tamamen etkisizleştirdiği sanılır. Oysa history expansion etkin olduğunda <code class="language-plaintext highlighter-rouge">!</code>, çifte tırnak içinde de yorumlanabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="nb">set</span> <span class="nt">-H</span>

<span class="nv">password</span><span class="o">=</span><span class="s2">"Guclu!Parola"</span>
<span class="nb">echo</span> <span class="s2">"</span><span class="nv">$password</span><span class="s2">"</span>
</code></pre></div></div>

<p>Bash, <code class="language-plaintext highlighter-rouge">!Parola</code> için uygun bir geçmiş olayı arayabilir ve <code class="language-plaintext highlighter-rouge">event not found</code> hatası üretebilir. Üstelik expansion, değişkenin değerinden çok kaynak satırı okunurken önem kazanır. Bu nedenle davranış kabuk sürümüne, çalışma biçimine ve bağlama göre şaşırtıcı görünebilir.</p>

<h2 id="en-güvenli-çözüm-özelliği-kapatmak">En güvenli çözüm: Özelliği kapatmak</h2>

<p>History expansion gerekmeyen bir betiğin başında özelliği açıkça kapatabilirsiniz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="nb">set</span> +H
<span class="c"># Aynı işlemin daha açıklayıcı karşılığı:</span>
<span class="nb">set</span> +o histexpand

<span class="nv">message</span><span class="o">=</span><span class="s2">"Dağıtım tamamlandı!"</span>
<span class="nb">printf</span> <span class="s1">'%s\n'</span> <span class="s2">"</span><span class="nv">$message</span><span class="s2">"</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">set +H</code>, <code class="language-plaintext highlighter-rouge">histexpand</code> seçeneğini kapatır. Buradaki artı işaretinin seçeneği kapatması ilk bakışta ters gelebilir: Bash’te <code class="language-plaintext highlighter-rouge">set -H</code> açar, <code class="language-plaintext highlighter-rouge">set +H</code> kapatır.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th style="text-align: right">Güvenilirlik</th>
      <th>Kullanım amacı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">set +H</code></td>
      <td style="text-align: right">Yüksek</td>
      <td>Betik genelinde expansion’ı kapatır</td>
    </tr>
    <tr>
      <td>Tek tırnak kullanmak</td>
      <td style="text-align: right">Yüksek</td>
      <td>Sabit metni korur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">\!</code> ile kaçırmak</td>
      <td style="text-align: right">Orta</td>
      <td>Belirli bir ünlemi korur</td>
    </tr>
    <tr>
      <td>Çifte tırnağa güvenmek</td>
      <td style="text-align: right">Düşük</td>
      <td>History expansion için yeterli olmayabilir</td>
    </tr>
  </tbody>
</table>

<p>Sabit bir değer söz konusuysa tek tırnak da kullanılabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">printf</span> <span class="s1">'%s\n'</span> <span class="s1">'İşlem başarılı!'</span>
<span class="nb">printf</span> <span class="s1">'%s\n'</span> <span class="s1">'api-token: abc!123'</span>
</code></pre></div></div>

<p>Ancak tek tırnak içinde değişken genişletmesi yapılmaz. Örneğin <code class="language-plaintext highlighter-rouge">'Merhaba $USER!'</code>, kullanıcı adını değil, doğrudan <code class="language-plaintext highlighter-rouge">$USER</code> metnini yazdırır.</p>

<h2 id="durumu-teşhis-etmek">Durumu teşhis etmek</h2>

<p>Seçeneğin mevcut durumunu aşağıdaki komutla görebilirsiniz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">set</span> <span class="nt">-o</span> | <span class="nb">grep </span>histexpand
</code></pre></div></div>

<p>Çıktıda <code class="language-plaintext highlighter-rouge">histexpand on</code> görülüyorsa ünlem genişletmesi açıktır. Betik <code class="language-plaintext highlighter-rouge">source script.sh</code> biçiminde çalıştırılıyorsa aynı kabuğun seçeneklerini miras alabileceğini unutmayın. Bağımsız çalıştırma için yürütme izni verip <code class="language-plaintext highlighter-rouge">./script.sh</code> kullanmak daha öngörülebilir olabilir.</p>

<p>Özetle ünlem kaynaklı hatalarda yalnızca kaçış karakterleriyle boğuşmayın. Önce kabuğun türünü, betiğin nasıl çalıştırıldığını ve <code class="language-plaintext highlighter-rouge">histexpand</code> durumunu kontrol edin. Otomasyon kodunda geçmiş komut sihrine ihtiyaç yoksa <code class="language-plaintext highlighter-rouge">set +H</code> diyerek sürprizi daha perde açılmadan bitirin.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="shell" /><category term="bash" /><category term="history-expansion" /><category term="betik" /><category term="linux" /><category term="hata-ayiklama" /><summary type="html"><![CDATA[Bir betik çalıştırıyorsunuz; parola, URL veya mesaj içinde sıradan bir ! karakteri var. Birden terminal event not found diye bağırıyor ya da komutunuz beklenmedik biçimde değişiyor. Suçlu çoğu zaman Bash’in history expansion özelliğidir. Ünlem işareti kabuk için yalnızca heyecan belirtmez; geçmiş komutlara açılan gizli bir kapı da olabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/shell-betiklerinde-surpriz-33.png" /><media:content medium="image" url="https://program.sonsuz.us/img/shell-betiklerinde-surpriz-33.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Yapay Potansiyel Alanlarda Yerel Minimum Tuzağı: Robot Neden Olduğu Yerde Kalır?</title><link href="https://program.sonsuz.us/posts/yapay-potansiyel-alanlarda-yerel-minimum-tuzagi-robot-neden-oldugu-yerde-kalir/" rel="alternate" type="text/html" title="Yapay Potansiyel Alanlarda Yerel Minimum Tuzağı: Robot Neden Olduğu Yerde Kalır?" /><published>2026-10-20T00:00:00+00:00</published><updated>2026-10-20T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/yapay-potansiyel-alanlarda-yerel-minimum-tuzagi-robot-neden-oldugu-yerde-kalir</id><content type="html" xml:base="https://program.sonsuz.us/posts/yapay-potansiyel-alanlarda-yerel-minimum-tuzagi-robot-neden-oldugu-yerde-kalir/"><![CDATA[<p>Yapay potansiyel alan yöntemi, mobil robotların hedefe ilerlerken engellerden kaçınmasını sağlayan zarif ve hesaplama açısından hafif bir yaklaşımdır. Hedef robotu çeken bir mıknatıs, engeller ise onu iten görünmez kuvvet kaynakları gibi modellenir. Ne var ki bu sade fikir, robotun hedefe ulaşmadan durduğu meşhur <strong>yerel minimum</strong> problemiyle karşılaşabilir.
``</p>
<h2 id="potansiyel-alanın-temel-mantığı">Potansiyel alanın temel mantığı</h2>

<p>Robotun konumu $q$, hedef konumu ise $q_g$ olsun. Sistemdeki toplam potansiyel enerji, çekici ve itici bileşenlerin toplamıdır:</p>

\[U(q)=U_{att}(q)+U_{rep}(q)\]

<p>Hedefin oluşturduğu çekici potansiyel çoğunlukla şöyle tanımlanır:</p>

\[U_{att}(q)=\frac{1}{2}k_{att}\lVert q-q_g\rVert^2\]

<p>Burada $k_{att}$ çekim katsayısıdır. Engellere ait itici potansiyel ise robot engele belirli bir mesafeden daha yakın olduğunda etkinleşir:</p>

\[U_{rep}(q)=\frac{1}{2}k_{rep}\left(\frac{1}{\rho(q)}-\frac{1}{\rho_0}\right)^2\]

<p>$\rho(q)$ en yakın engele olan mesafeyi, $\rho_0$ ise engelin etki mesafesini temsil eder. Robotun hareket yönü, toplam potansiyelin negatif gradyanından elde edilir:</p>

\[F(q)=-\nabla U(q)=F_{att}(q)+F_{rep}(q)\]

<p>Başka bir deyişle robot, enerji yüzeyinde aşağı doğru yuvarlanan bir bilye gibidir. Sorun, yüzeydeki her çukurun gerçek hedef olmamasıdır.</p>

<h2 id="yerel-minimum-nasıl-oluşur">Yerel minimum nasıl oluşur?</h2>

<p>Yerel minimumda çekici ve itici kuvvetler birbirini dengeler:</p>

\[F_{att}(q)+F_{rep}(q)=0\]

<p>Robot hedefte olmadığı hâlde bileşke kuvvet sıfır olduğu için hareket komutu üretemez. Özellikle U biçimli engeller, birbirine yakın engeller ve hedefin bir engelin hemen arkasında bulunması bu riski artırır. Dar geçitlerde görülen sağa-sola salınım ise tam anlamıyla yerel minimum değildir; fakat yöntemin yalnızca anlık geometrik bilgiye dayanmasından kaynaklanan benzer bir başarısızlıktır.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th>Robotun davranışı</th>
      <th>Temel neden</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Serbest alan</td>
      <td>Doğrudan hedefe ilerler</td>
      <td>Çekici kuvvet baskındır</td>
    </tr>
    <tr>
      <td>Tek engel</td>
      <td>Engelin çevresinden sapar</td>
      <td>İtici kuvvet geçici olarak yön değiştirir</td>
    </tr>
    <tr>
      <td>U biçimli engel</td>
      <td>Girintinin içinde kalabilir</td>
      <td>Çıkış yönü önce hedeften uzaklaşmayı gerektirir</td>
    </tr>
    <tr>
      <td>Simetrik dar koridor</td>
      <td>Salınım yapabilir</td>
      <td>Karşılıklı itici kuvvetler hızla yön değiştirir</td>
    </tr>
    <tr>
      <td>Engel arkasındaki hedef</td>
      <td>Hedefe yakınken durabilir</td>
      <td>Çekim ve itme dengelenir</td>
    </tr>
  </tbody>
</table>

<h2 id="basit-bir-kuvvet-hesabı">Basit bir kuvvet hesabı</h2>

<p>Aşağıdaki Python fonksiyonu, iki boyutlu ortamda hedef çekimini ve engel itmesini hesaplar. Kod, yöntemin yerel ve tepkisel yapısını görünür kılar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">def</span> <span class="nf">potential_force</span><span class="p">(</span><span class="n">position</span><span class="p">,</span> <span class="n">goal</span><span class="p">,</span> <span class="n">obstacles</span><span class="p">,</span>
                    <span class="n">k_att</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">k_rep</span><span class="o">=</span><span class="mf">0.8</span><span class="p">,</span> <span class="n">influence</span><span class="o">=</span><span class="mf">2.0</span><span class="p">):</span>
    <span class="n">position</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">asarray</span><span class="p">(</span><span class="n">position</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
    <span class="n">goal</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">asarray</span><span class="p">(</span><span class="n">goal</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>

    <span class="n">force</span> <span class="o">=</span> <span class="n">k_att</span> <span class="o">*</span> <span class="p">(</span><span class="n">goal</span> <span class="o">-</span> <span class="n">position</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">obstacle</span> <span class="ow">in</span> <span class="n">obstacles</span><span class="p">:</span>
        <span class="n">delta</span> <span class="o">=</span> <span class="n">position</span> <span class="o">-</span> <span class="n">np</span><span class="p">.</span><span class="nf">asarray</span><span class="p">(</span><span class="n">obstacle</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
        <span class="n">distance</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">norm</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span>

        <span class="k">if</span> <span class="mf">1e-6</span> <span class="o">&lt;</span> <span class="n">distance</span> <span class="o">&lt;</span> <span class="n">influence</span><span class="p">:</span>
            <span class="n">direction</span> <span class="o">=</span> <span class="n">delta</span> <span class="o">/</span> <span class="n">distance</span>
            <span class="n">magnitude</span> <span class="o">=</span> <span class="n">k_rep</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">/</span> <span class="n">distance</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">influence</span><span class="p">)</span> <span class="o">/</span> <span class="n">distance</span><span class="o">**</span><span class="mi">2</span>
            <span class="n">force</span> <span class="o">+=</span> <span class="n">magnitude</span> <span class="o">*</span> <span class="n">direction</span>

    <span class="k">return</span> <span class="n">force</span>
</code></pre></div></div>

<p>Robot her çevrimde bu kuvvetin yönünde küçük bir adım atabilir. Ancak fonksiyon geçmiş hareketleri veya engelin genel şeklini bilmez. Hesaplanan kuvvet sıfıra yaklaşırsa robot, önünde geçerli bir çıkış olsa bile onu keşfedemeyebilir.</p>

<h2 id="tuzaktan-kurtulma-yöntemleri">Tuzaktan kurtulma yöntemleri</h2>

<p>Yerel minimum riskini azaltmak için birkaç yaklaşım kullanılabilir:</p>

<ul>
  <li><strong>Rastgele kaçış kuvveti:</strong> Robot uzun süre ilerleyemezse geçici bir rastgele yön eklenir.</li>
  <li><strong>Teğetsel kuvvet:</strong> Engeli yalnızca itmek yerine çevresinden dolaşmayı teşvik eden bir bileşen uygulanır.</li>
  <li><strong>Ara hedefler:</strong> Global planlayıcının ürettiği yol üzerindeki noktalar sırayla hedef seçilir.</li>
  <li><strong>Harmonik potansiyeller:</strong> Laplace tabanlı alanlarla hedef dışındaki minimumların oluşması sınırlandırılır.</li>
  <li><strong>Hibrit planlama:</strong> A*, Dijkstra veya RRT global rota için; potansiyel alan ise anlık kaçınma için kullanılır.</li>
</ul>

<p>Pratikte en güvenilir çözüm hibrit yaklaşımdır. Yapay potansiyel alan hızlı refleksler sağlarken global planlayıcı, robotun bazen hedefe yaklaşmak için önce hedeften uzaklaşması gerektiğini anlayabilir. Böylece robot görünmez bir çukurda düşüncelere dalmak yerine yoluna devam eder.</p>

<p><img src="/img/yapay-potansiyel-alanlarda-84.svg" alt="yapay-potansiyel-alanlarda-84" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="yapay potansiyel alan" /><category term="engelden kaçınma" /><category term="yerel minimum" /><category term="otonom robotlar" /><category term="yol planlama" /><summary type="html"><![CDATA[Yapay potansiyel alan yöntemi, mobil robotların hedefe ilerlerken engellerden kaçınmasını sağlayan zarif ve hesaplama açısından hafif bir yaklaşımdır. Hedef robotu çeken bir mıknatıs, engeller ise onu iten görünmez kuvvet kaynakları gibi modellenir. Ne var ki bu sade fikir, robotun hedefe ulaşmadan durduğu meşhur yerel minimum problemiyle karşılaşabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/yapay-potansiyel-alanlarda-84.png" /><media:content medium="image" url="https://program.sonsuz.us/img/yapay-potansiyel-alanlarda-84.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>