Thread overview
Çember çizme programının D sürümü
Aug 08, 2012
erdem
Aug 08, 2012
erdem
August 08, 2012
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

typedef struct {
 size_t         width;
 size_t         height;
 unsigned char *data;
} Image;

static Image * image_new (size_t width,
          size_t height)
{
 Image *image;

 image = malloc (sizeof *image);
 image->width = width;
 image->height = height;
 image->data = malloc (width * height);

 return image;
}

static void image_free (Image *image)
{
 free (image->data);
 free (image);
}

static void image_fill (Image *image,
           unsigned char  value)
{
 memset (image->data, value, image->width * image->height);
}

/**
* image_set_pixel:
*
* Sets a pixel passed in signed (x, y) coordinates, where (0,0) is at
* the center of the image.
**/
static void image_set_pixel (Image *image,
                ssize_t        x,
                ssize_t        y,
                unsigned char  value)
{
 size_t tx, ty;
 unsigned char *p;

 tx = (image->width / 2) + x;
 ty = (image->height / 2) + y;

 p = image->data + (ty * image->width) + tx;

 *p = value;
}

static void image_save (const Image *image,
           const char  *filename)
{
 FILE *out;

 out = fopen (filename, "wb");
 if (!out)
   return;

 fprintf (out, "P5\n");
 fprintf (out, "%zu %zu\n", image->width, image->height);
 fprintf (out, "255\n");

 fwrite (image->data, 1, image->width * image->height, out);

 fclose (out);
}

static void draw_circle (Image         *image,
            int            radius,
            unsigned char  value)
{
 int x, y;

 for (x = -radius; x <= radius; x++) {
   y = (int) sqrt ((double) (radius * radius) - (x * x));

   image_set_pixel (image, x, y, value);
   image_set_pixel (image, x, -y, value);
 }
}

int main (int argc, char *argv[])
{
 Image *image;

 image = image_new (600, 600);

 image_fill (image, 0xff);
 draw_circle (image, 200, 0);
 image_save (image, "circle.pgm");

 image_free (image);

 return 0;
}

Bu çember çizen kodun D sürümünü nasıl yazabilirdik. Anladığım kadarıyla burada 'malloc' kullanarak dinamik olarak bellekten yer ayırmış. Ama D sürümünde buna ihtiyacımız var mı. 'unsigned char *' yerine ne kullanabiliriz.

'malloc''u şu şekilde kullanıyoruz diye hatırlıyorum. Örneğin tamsayılardan oluşan bir dizimiz var.

   int dizi[10];

Sonra dinamik olarak 10 tane tamsayının kapladığı kadar bellek alanı ayırıyoruz.

  int *p = malloc(10 * sizeof(int));

Ama açıkçası neden bu kadar çok 'malloc 'kullandığını anlamadım.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 08, 2012

Çok teşekkürler. Bazen böyle anlamadığım C programları çıkıyor.

Aslında gene C ilintileri konusunda bir soruyla ilgili sanırım daha önce de bu listedeki C kitaplarından (http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) birisini gösterip okumama gerek var mı diye sormuştum. Siz de gerek yok çünkü o konular bu kitaplarda yoktur demiştiniz.

 unsigned char *data;

Buradaki gösterge kullanımı göstergeleri bir dizinin ilk elemanına eşitleyip kullanabiliyorduk. Sanırım bu şekilde bir kullanım.

Peki aşağıda:

 image = image_new (600, 600);

işlevini çağırdığımız zaman

 image = malloc (sizeof *image);

Bu sizeof * image'in sayısal bir karşılığı var mı yoksa C++'daki

image = new Image(600, 600);

ün karşılığı mı yani sadece 'image*' türünde bir değişken için dinamik olarak bellek mi ayırıyoruz.

Alıntı:

>

image->data = malloc (width * height);

Burası da biraz kafa karıştırıcı. O zaman şöyle mi diyoruz. Bellekten 600 * 600 boyutunda tek boyutlu bir char dizisi için yer ayır. Benim data isimli char* türünde göstergem bu dizinin ilk elemanını göstersin.

memset (image->data, value, image->width * image->height);

Bir de tabi bu kısmın ne yaptığını anlamadım.

Aslında ben yapmak istediğimi öğrendim. Asıl amacım bu işin D ile nasıl yapılacağını öğrenmek ve ilginç bir kaç çember çizme algoritmasını test etmekti. Ama C kültürümüzün artmasının da bir sakıncası yoktur herhalde :-p

Sonuçta Andrei ve Walter da canavar gibi C biliyorlar bildiğim kadarıyla.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 08, 2012

Aşağıdaki program çalışıyor.

import std.stdio;
import std.algorithm;
import std.math;

struct Image {
   size_t         width;
   size_t         height;
   ubyte[]        data;

   this(size_t width, size_t height)
   {
       this.width = width;
       this.height = height;
       data.length = width * height;
   }

   void fill(ubyte value)
   {
       std.algorithm.fill(data, value);
   }

   /**
    * image_set_pixel:
    *
    * Sets a pixel passed in signed (x, y) coordinates, where (0,0) is at the
    * center of the image.
    **/
   void set_pixel(sizediff_t     x,
                  sizediff_t     y,
                  ubyte          value)
   {
       size_t tx = (width / 2) + x;
       size_t ty = (height / 2) + y;

       data[(ty * width) + tx] = value;
   }

   void save(string filename)
   {
       auto file = File(filename, "wb");

       file.writeln("P5");
       file.writefln("%s %s", width, height);
       file.writefln("255");

       file.rawWrite(data);
   }
}

void draw_circle (ref Image      image,
                 int            radius,
                 ubyte          value)
{
   foreach (x; -radius .. radius + 1) {
       int y = cast(int)sqrt(cast(double)(radius * radius) - (x * x));

       image.set_pixel(x, y, value);
       image.set_pixel(x, -y, value);
   }
}

void main()
{
   auto image = Image(600, 600);

   image.fill(0xff);
   draw_circle(image, 200, 0);
   image.save("circle.pgm");
}

C programında malloc iki yerde geçiyor:

  • Image yapısı oluşturulurken: Dinamik nesneler geleneksel olarak malloc() (veya calloc()) ile oluşturulurlar.

Teknik olarak, aslında image_new() içinde yerel de oluşturulabilir ve işlevden döndürülebilir de ama bildiğimiz gibi C'de dönüş değeri hata koduna ayrılmalıdır. Bu açıdan bakıldığında image_new'ün iyi bir işlev olmadığını söyleyebiliriz: İlk malloc() başarılı olsa ama ikincisi başarısız olsa çağıranın bundan haberi olmuyor.

  • image->data oluşturulurken: Bu şart çünkü data'nın uzunluğu derleme zamanında bilinmiyor; ancak dinamik olarak oluşturulabilir.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 08, 2012

Alıntı (erdem):

>

Siz de gerek yok çünkü o konular bu kitaplarda yoktur demiştiniz.

Tam olarak hangi konu olduğunu hatırlamıyorum ama kitap okumak iyidir. :)

Alıntı:

>
>   unsigned char *data;
> ```

>
> Buradaki gösterge kullanımı göstergeleri bir dizinin ilk elemanına eşitleyip kullanabiliyorduk. Sanırım bu şekilde bir kullanım.

Evet.

Alıntı:
>
>
>

image = image_new (600, 600);

>

işlevini çağırdığımız zaman

>   image = malloc (sizeof *image);
> ```

>
> Bu sizeof * image'in sayısal bir karşılığı var mı

*image, "image'in gösterdiği nesne" anlamına geliyor. sizeof da onun büyüklüğü. Yani sonuçta 'struct Image'in kaç bayttan oluştuğunu veriyor. Yukarıdaki malloc() tek bir 'struct Image'in sığacağı kadar yer ayırır.

Alıntı:
> 'image*' türünde bir değişken için dinamik olarak bellek mi ayırıyoruz.

'image*' türünde değişken için değil, 'struct Image' için yer ayırıyoruz. Onun adresini 'image*' türünde yerel bir değişkende tutuyoruz. O değişkenin değerini (yani adresi) return ile döndüreceğiz.

Alıntı:
>
> Alıntı:
> >
> >   image->data = malloc (width * height);
> >
>
> Burası da biraz kafa karıştırıcı. O zaman şöyle mi diyoruz. Bellekten 600 * 600 boyutunda tek boyutlu bir char dizisi için yer ayır. Benim data isimli char* türünde göstergem bu dizinin ilk elemanını göstersin.

Evet.

Alıntı:
>
>
>

memset (image->data, value, image->width * image->height);

>

Bir de tabi bu kısmın ne yaptığını anlamadım.

'man memset' marifetiyle belgesine bakıyoruz. :) Ona bakılırsa 'image->data' adresinden başlayan 'image->width * image->height' adet bellek bölgesine 'value' değerini yazarmış.

Alıntı:

>

Ama C kültürümüzün artmasının da bir sakıncası yoktur herhalde :-p

Çok haklısın. Sistem programcılığında C'nin bilinmesi çok yararlıdır. C++, D, vs. gibi dillerin üst düzey olanaklarının nasıl gerçekleştirilmiş oldukları hem daha kolay anlaşılır hem de daha çok müteşekkir olunur. :-p

Alıntı:

>

Sonuçta Andrei ve Walter da canavar gibi C biliyorlar bildiğim kadarıyla.

Kesinlikle! :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]