Computing Fundamentals & C Programming _ Chapter-3 C’ye Genel Bakış

3.1 GİRİŞ

C, structured (yapısal), high-level (yüksek seviyeli), machine independent (makineden bağımsız) bir dil olduğu için günümüzün en popüler bilgisayar dillerinden biridir. Yazılım geliştiricilerin, uygulanacakları donanım platformları hakkında endişelenmeden programlar geliştirmelerine olanak tanır.

Tüm modern dillerin kökü, 1960'ların başında tanıtılan ALGOL’dur. ALGOL, blok yapısını kullanan ilk bilgisayar diliydi. ALGOL, yapısal programlama (structured programming) kavramını verdi. Corrado Bohm, Guiseppe Jacopini ve Edsger Dijkstra gibi bilgisayar bilimcileri bu kavramı 1960'larda popüler hale getirdi.

1967'de Martin Richards, öncelikle sistem yazılımı yazmak için BCPL (Basic Combined Programming Language) adlı bir dil geliştirdi. 1970 yılında Ken Thompson, BCPL’nin birçok özelliğini kullanarak bir dil geliştirdi ve buna kısaca B adını verdi. B, Bell Laboratuvarlarında UNIX işletim sisteminin ilk sürümlerini oluşturmak için kullanıldı. Hem BCPL hem de B, “typeless” sistem programlama dilleriydi.

C, 1972'de Bell Laboratuvarlarında Dennis Ritchie tarafından ALGOL, BCPL ve B’den geliştirilmiştir. C, bu dillerden birçok kavram kullanır ve data types kavramını ve diğer güçlü özellikleri ekler. Yine Bell Laboratuarlarında geliştirilen UNIX işletim sistemi, neredeyse tamamen C ile kodlanmıştır.

1970'lerde C, şimdi “traditional C” olarak bilinen şeye dönüştü. Brian Kerningham ve Dennis Ritchie’nin 1978'de* ‘The C Programming Language’* kitabının yayınlanmasından sonra C, programlama topluluğu arasında “K&R C” olarak bilinmeye başlandı.

C dilinin standart olarak kalmasını sağlamak için 1983'te Amerikan Ulusal Standartlar Enstitüsü (ANSI), C için bir standart tanımlamak üzere bir teknik komite atadı ve bu komite Aralık 1989'da C’nin şimdi ANSI C olarak bilinen sürümünü onayladı. daha sonra 1990 yılında Uluslararası Standartlar Organizasyonu (ISO) tarafından onaylanmıştır. C’nin bu versiyonu aynı zamanda C89 olarak da anılır.

1990'larda tamamen C tabanlı bir dil olan C++, bir dizi iyileştirme ve değişikliğe uğradı ve Kasım 1977'de ANSI/ISO onaylı bir dil oldu. C++, onu yalnızca gerçek bir object-oriented (nesne yönelimli) dil değil, aynı zamanda daha çok yönlü bir dil yapmak için C’ye birkaç yeni özellik ekledi. Aynı dönemde ABD’li Sun Microsystems, C ve C++ üzerinde modellenmiş yeni bir Java dili geliştirdi.

C++ ve Java, C’den geliştirilmiş olsa da, C standardizasyon komitesi, C++/Java’nın birkaç özelliğinin C’ye eklenmesi durumunda dilin kullanışlılığını artıracağını düşündü. Sonuç, C için 1999 standardıydı. Bu sürüme genellikle C99 denir. C’nin tarihi ve gelişimi aşağıdaki şekilde gösterilmektedir.

3.2 C’NİN ÖNEMİ

C’nin artan popülaritesi, muhtemelen birçok arzu edilen niteliğinden kaynaklanmaktadır. Herhangi bir karmaşık program yazmak için kullanılabilen zengin yerleşik fonksiyonlar ve operator’ler içeren robust language’dir. C compiler, bir assembly dilinin yeteneklerini high-level bir dilin özellikleriyle birleştirir ve bu nedenle hem sistem yazılımı hem de iş paketleri yazmak için çok uygundur. Aslında, piyasada bulunan C compiler’ların çoğu C dilinde yazılmıştır.

C ile yazılmış programlar verimli ve hızlıdır. Bunun nedeni, veri türlerinin çeşitliliği ve güçlü operatörleridir. BASIC’ten çok daha hızlıdır. Örneğin, bir değişkeni 0'dan 15000'e artıran bir program C’de yaklaşık bir saniye sürerken BASIC yorumlayıcısında 50 saniyeden fazla sürer.ANSI C’de yalnızca 32 anahtar kelime vardır ve gücü yerleşik fonksiyonlarında yatmaktadır. Program geliştirmek için kullanılabilecek çeşitli standart fonksiyonlar mevcuttur.

C oldukça taşınabilirdir (portable). Bu, bir bilgisayar için yazılan C programlarının başka bir bilgisayarda çok az değişiklikle veya hiç değişiklik yapılmadan çalıştırılabileceği anlamına gelir. Farklı bir işletim sistemine sahip yeni bir bilgisayar kullanmayı planlıyorsak taşınabilirlik önemlidir.

C dili, yapısal programlama (structured programming) için çok uygundur, dolayısıyla kullanıcının bir problemi fonksiyon modülleri veya bloklar açısından düşünmesini gerektirir. Bu modüllerin uygun şekilde toplanması eksiksiz bir program oluşturur. Bu modüler yapı, programın hata ayıklamasını, test edilmesini ve bakımını kolaylaştırır.

C’nin bir diğer önemli özelliği de kendini genişletebilmesidir. C programı temel olarak C library tarafından desteklenen bir fonksiyonlar koleksiyonudur. Kendi fonksiyonlarımızı sürekli olarak C kütüphanesine ekleyebiliriz. Çok sayıda fonksiyonun kullanılabilirliği ile programlama görevi basitleşir.C’nin belirli özelliklerini tartışmadan önce, bazı örnek C programlarına bakacağız ve nasıl çalıştıklarını analiz edip anlayacağız.

post image

3.3 ÖRNEK PROGRAM 1: MESAJ YAZDIRMA

Aşağıdaki şekilde verilen çok basit bir programı ele alalım.

main( )
{
/*…………printing begins………………*/
printf("I see, I remember");
/*………………printing ends…………………*/
}

Bu program yürütüldüğünde aşağıdaki çıktıyı üretecektir:“I see, I remember”

Programı yakından inceleyelim. İlk satır programın adının main olduğunu sisteme bildirir ve bu satırda çalıştırma başlar. main( ), C sistemi tarafından bilgisayara programın nerede başladığını söylemek için kullanılan özel bir fonksiyondur. Her programın tam olarak bir main fonksiyonu olmalıdır. Birden fazla main fonksiyon kullanırsak, compiler hangisinin programın başlangıcı olduğunu anlayamaz.

main’in hemen ardından gelen boş parantez çifti, main fonksiyonunun hiçbir argümanı (veya parametresi) olmadığını gösterir. İkinci satırdaki açılış ayracı “{” main fonksiyonunun başlangıcını, son satırdaki kapanış parantezi “}” ise fonksiyonun sonunu gösterir. Bu durumda, kapatma ayracı aynı zamanda programın sonunu da belirtir. Bu iki ayraç arasındaki tüm ifadeler, fonksiyon gövdesini oluşturur. Fonksiyon gövdesi, verilen görevi gerçekleştirmek için bir dizi instruction içerir. Bu durumda, fonksiyon gövdesi, yalnızca printf satırının yürütülebilir bir ifade olduğu üç ifade içerir. /* ile başlayan ve */ ile biten satırlar yorum satırları olarak bilinir. Bunlar, okunabilirliğini ve anlaşılmasını artırmak için bir programda kullanılır. Yorum satırları yürütülebilir ifadeler değildir ve bu nedenle /* ile */ arasındaki herhangi bir şey compiler tarafından dikkate alınmaz. Genel olarak, bir satırın başında, ortasında veya sonunda boşluk olabilecek her yere yorum eklenebilir, “ancak asla bir kelimenin ortasına eklenemez”.Yorumlar herhangi bir yerde görünebilse de, C’de iç içe olamazlar. Bu, yorumların içinde yorum yapamayacağımız anlamına gelir. Compiler bir açılış tokeni bulduğunda, bir kapanış tokeni bulana kadar her şeyi yok sayar. yorum satırı geçerli değildir ve bu nedenle bir hatayla sonuçlanır.

/* = = = =/* = = = = */ = = = = */

Yorumlar, derlenmiş bir programın yürütme hızını ve boyutunu etkilemediği için, bunları programlarımızda serbestçe kullanmalıyız. Programcıların ve diğer kullanıcıların bir programın çeşitli fonksiyonlarını ve işlemlerini anlamalarına yardımcı olurlar ve hata ayıklama ve test etmede yardımcı olurlar. Aşağıdaki örneklerde yorum satırlarının kullanımını daha fazla göreceğiz.

Şimdi programın çalıştırılabilir tek ifadesi olan printf( ) fonksiyonuna bakalım.

printf("I see, I remember");

printf, yazdırma çıktısı için Predefined (önceden tanımlanmış) bir standart C fonksiyonudur. Predefined (Önceden tanımlanmış), zaten yazılmış ve derlenmiş bir fonksiyon olduğu ve linking anında programımızla linked olduğu anlamına gelir. Compilation (Derleme) ve linking (Bağlama) kavramları bu bölümde daha sonra açıklanacaktır. printf fonksiyonu, başlangıç ve bitiş tırnak işaretleri arasındaki her şeyin yazdırılmasına neden olur. Bu durumda, çıktı şöyle olacaktır:“I see, I remember”

Yazdırma satırının noktalı virgülle bittiğine dikkat edin. C’deki her ifade noktalı virgül (;) işaretiyle bitmelidir.Yukarıdaki mesajı şu şekilde iki satır halinde yazdırmak istediğimizi varsayalım:

printf("I see, \n"); 
printf("I remember !");

Parantezler arasında yer alan bilgilere fonksiyonun *argümanı *denir. Birinci printf fonksiyonunun bu argümanı “I see, \n” ve ikincisi “I remember!” şeklindedir. Bu bağımsız değişkenler, yalnızca yazdırılacak karakter stringleridir.İlk printf argümanının string’inin sonunda \ ve n olmak üzere iki karakterden oluşan bir \n biçiminde olan kombinasyon içerdiğine dikkat edin. Bu kombinasyon topluca yeni satır (newline) karakteri olarak adlandırılır. Yeni satır karakteri, bilgisayara sonraki (yeni) satıra gitmesi talimatını verir. Konsept olarak bir daktilodaki satır başı tuşuna benzer. Virgül (,) karakterini yazdırdıktan sonra yeni satır karakterinin varlığı \n “I remember !” sonraki satıra yazdırılacaktır. \ ve n arasında boşluğa izin verilmez.

İlk printf ifadesinden yeni satır karakterini (“\n”)çıkarırsak, çıktı yine aşağıda gösterildiği gibi tek satır olacaktır.I see, I remember !

Bu, Aşağıdaki programın çıktısına benzer. Ancak, I’lar arasında boşluk olmadığına dikkat edin. Uygun yerlerde yeni satır karakteri kullanılarak tek bir printf deyimiyle iki veya daha fazla satırlık çıktı üretmek de mümkündür. Örneğin;

printf("I see,\n I remember !");

çıktısını verecek: I see,I remember !

#include <stdio.h> herhangi bir input/output library fonksiyonunu kullanan tüm programların başında bulunur. Ancak C dilinin bir parçası olarak tanımlanan printf ve scanf fonksiyonları için bu gerekli değildir.

Diğer örnekleri tartışmaya geçmeden önce, önemli bir noktayı not etmeliyiz. C, büyük ve küçük harfler arasında bir ayrım yapar. Örneğin, printf ve PRINTF aynı değildir. C’de her şey küçük harflerle yazılır. Ancak, sabitleri temsil eden sembolik isimler için büyük harfler kullanılır. “I SEE” ve “I REMEMBER” gibi çıktı dizilerinde de büyük harfler kullanabiliriz.

Yukarıdaki yazdırılan I see, I remember örneği en basit programlardan biri. Aşağıdaki şekil, bu tür basit programların genel formatını vurgulamaktadır. Tüm C programlarının bir main fonksiyonuna ihtiyacı vardır.

3.3.1 main Fonksiyonu

C dili programları genellikle bir “main” fonksiyonu içerir. Bu fonksiyon, programın çalışmaya başladığı ve bitirdiği noktayı belirler. Örneğin, main fonksiyonu içinde diğer fonksiyonların çağrılması ve programda kullanılan verilerin işlenmesi gerçekleştirilir. Main fonksiyonu, programın çalışması için gerekli olan tüm bilgileri içerebilir ve genellikle int tipinde bir return değeri döndürür.

main, her C programının bir parçasıdır. C, farklı main ifade biçimlerine izin verir. Aşağıdaki formlara izin verilir.

- main() - int main() - void main() - main(void) - void main(void) - int main(void)

Boş parantez çifti, fonksiyonun bağımsız değişkeni olmadığını gösterir. Bu, parantez içinde boş anahtar kelime kullanılarak açıkça belirtilebilir. main kelimesinden önce int veya void keyword de belirtebiliriz. Void keyword sözcüğü, fonksiyonun işletim sistemine herhangi bir bilgi döndürmediği ve int, fonksiyonun işletim sistemine bir tamsayı değeri döndürmesi anlamına gelir. **int **belirtildiğinde, programdaki son ifade “return 0” olmalıdır. Basitlik adına, programlarımızda ilk formu kullanıyoruz.

3.4 ÖRNEK PROGRAM 2: İKİ SAYIYI TOPLAMA

İki sayı üzerinde toplama yapan ve sonucu görüntüleyen başka bir programı ele alalım. Programın tamamı aşağıdaki şekilde gösterilmiştir.

/* Programm ADDITION */                       /* line-1 */
                                              /* line-2 */
main() {                                      /* line-3 */
 int number;                                  /* line-4 */
 float amount;                                /* line-5 */
 number = 100;                                /* line-6 */
 amount = 30.75 + 75.35;                      /* line-7 */
 printf("%d\n",number);                       /* line-8 */
 printf("%5.2f",amount);                      /* line-9 */
}                                             /* line-10 */

Bu program yürütüldüğünde aşağıdaki çıktıyı üretecektir:

Programın ilk satırı yorum satırıdır. Programın adı, yazarı, tarihi vb. bilgileri vermek için başlangıçta yorum satırları kullanmak iyi bir uygulamadır.

number ve amount sözcükleri, sayısal verileri depolamak için kullanılan değişken adlarıdır (variable names). Sayısal veriler, integer (tam sayı) biçiminde veya gerçek (real) biçimde olabilir. C’de, compiler’a değişken adlarının ne olduğunu ve ne tür veriler tuttuklarını söylemek için tüm değişkenler ifade edilmelidir. Değişkenler kullanılmadan önce ifade edilmelidir. 5. ve 6. satırlardaki ifadeler (int number; float amount;) compiler’a number’ın bir integer (int) ve amount’un floating (float) bir sayı olduğunu ifade edin. ifadeler, aşağıdaki şekilde gösterildiği gibi fonksiyonların başında yer almalıdır. Tüm ifadeler noktalı virgülle biter; C, diğer birçok veri türünü destekler ve bunlar Chapter 4'te ayrıntılı olarak ele alınacak.

Data, ona bir veri değeri atanarak bir değişkende saklanır. Bu, 6. ve 7. satırlarda yapılır. 6. satırda, number integer değişkenine 100 değeri atanır ve 7. satırda, amount float değişkenine iki reel sayı 30.75 ve 75.35'in toplanmasının sonucu atanır.number = 100;amount = 30.75 + 75.35; ifadeleri atama (assignment) ifadeleri olarak adlandırılır. Her atama ifadesinin sonunda bir noktalı virgül olmalıdır. Bir sonraki ifade, number değerini yazdıran bir çıktı ifadesidir.

print ifadesi printf(“%d\n”, number); iki argüman içerir. İlk bağımsız değişken “%d”, compiler’a ikinci bağımsız değişken number değerinin ondalık bir tamsayı (decimal integer) olarak yazdırılması gerektiğini söyler. Bu bağımsız değişkenlerin virgülle ayrıldığına dikkat edin. Yeni satır karakteri \n, bir sonraki çıktının yeni bir satırda görünmesine neden olur.

Programın son ifadesi printf(“%5.2f”, amount); amount değerini float biçiminde yazdırır. Biçim belirtimi %5.2f, compiler’a çıktının 5 basamıklı en az yer kaplamasını eğer kaplamazsa o kısımlara soldan itibaren boşluk bırakmaya yarar ve .2 ifadesi ise ondalıktan sonra iki basamak olacak şekilde float çıktısı olması gerektiğini söyler.

3.5 ÖRNEK PROGRAM 3: FAİZ HESAPLAMASI

Aşağıdaki program, yüzde 11'lik bir faiz oranı varsayarak, her yatırım yılı sonunda paranın değerini hesaplar ve yılı ve karşılık gelen tutarı iki sütun halinde yazdırır. Çıktı, Aşağıdaki şekilde 5000,00 başlangıç yatırımı ile 10 yıllık bir süre için gösterilmektedir. Program aşağıdaki formülü kullanır:Yıl sonu değeri = Yıl başı değeri (1 + faiz oranı) Programda value değeri paranın yıl sonundaki değerini, amount ise paranın yıl başındaki değerini temsil etmektedir. Açıklama: mevcut yılın sonundaki değeri ***amount = value ;***bir sonraki yılın başındaki değer olarak yapar.

/*—————————— INVESTMENT PROBLEM ——————————*/
#define PERIOD 10
#define PRINCIPAL 5000.00
/*—————————— MAIN PROGRAM BEGINS ——————————*/
main()
{ /*————————— DECLARATION STATEMENTS ————————*/
int year;
  float amount, value, inrate;
/*————————— ASSIGNMENT STATEMENTS —————————*/

amount = PRINCIPAL; 
inrate = 0.11; 
year = 0;

/*————————— COMPUTATION STATEMENTS —————————*/ 
/*——————— COMPUTATION USING While LOOP ————————*/
while(year <= PERIOD)
{ printf("%2d %8.2f\n",year, amount);
  value = amount + inrate * amount; 
  year = year + 1;
  amount = value; 
}
/*——————————— while LOOP ENDS ——————————*/ 
}
/*———————————— PROGRAM ENDS ——————————*/

Bu programda tanıtılan yeni özellikleri ele alalım. İkinci ve üçüncü satırlar #define yönergeleriyle başlar. Bir #define komutu, programda kullanılmak üzere sembolik bir sabitin (a symbolic constant) değerini tanımlar. Sembolik bir adla karşılaşıldığında, compiler adla ilişkili değeri otomatik olarak değiştirir. Değeri değiştirmek için tanımı değiştirmemiz yeterlidir. Bu örnekte, PERIOD ve PRINCIPAL olmak üzere iki sembolik sabit tanımladık ve sırasıyla 10 ve 5000.00 değerleri atadık. Bu değerler, programın yürütülmesi boyunca sabit kalır.

Burada %2d kısmında year değerini yani yıllarımızı yazdırıyoruz. %2d formatında olması eğerki 1 karakter çıktımız varsa onu başına bir boşluk ekleyerek 2 karaktere çıkartmamıza yarıyor. %8.2f kısmında ise ilk 8 karakter dolu değilse kalan kısımları boşlıkla dolduruyoruz ve .2 kısmıyla ise float sayımızın noktadan sonraki ilk 2 basamağını yazdırıyoruz.

3.5.1 #define Direktifi

#define, bir önişlemci compiler direktifidir (preprocessor compiler directive), bir ifade (statement) değildir. Bu nedenle #define satırları noktalı virgülle bitmemelidir. Sembolik sabitler, küçük harfli değişken adlarından kolayca ayırt edilebilmeleri için genellikle büyük harfle yazılır. #define instructionları genellikle başta main() fonkisyonundan önce gelir. Sembolik sabitler bildirim bölümünde bildirilmez.

Tanımlanan sabitlerin değişken olmadığına dikkat etmeliyiz. Bir atama ifadesi kullanarak program içindeki değerlerini değiştiremeyiz. Örneğin, PRINCIPAL = 10000.00; ifadesi yasa dışıdır.

Değişken tanımlama bölümü, year integer olarak ve amount, value ve inrate floating point sayılar olarak tanımlar. Tüm floating-point değişkenlerin yukarıdaki kodda tek bir ifadede tanımlandığına dikkat edin. Ayrıca şu şekilde tanımlanabilirler:

float amount; 
float value; 
float inrate;

Bir ifadede iki veya daha fazla değişken tanımlandığında, bunlar virgülle ayrılır.Tüm hesaplamalar ve yazdırma bir süre döngüsünde gerçekleştirilir. while, bir ifadeyi veya bir ifade grubunu tekrar tekrar değerlendirmek için bir mekanizmadır. Bu durumda, year değeri PERIOD değerinden küçük veya ona eşit olduğu sürece, while’ı takip eden dört ifade yürütülür. Bu dört ifadenin parantez içinde gruplandırıldığına dikkat edin. year, PERIOD’dan büyük olduğunda döngüden çıkarız.

C, temel dört aritmetik operatorü (–, +, *, /) ve diğer birkaç işleci destekler. Chapter 5'te detaylıca göreceğiz.

3.6 ÖRNEK PROGRAM 4: ALT PROGRAMLARIN KULLANIMI

Şimdiye kadar sadece C sisteminin bize sağladığı printf fonksiyonunu kullandık. Aşağıdaki şekilde gösterilen program, kullanıcı tanımlı (user-defined) bir fonksiyon kullanır. Kullanıcı tarafından tanımlanan bir fonksiyon, FORTRAN’daki bir alt programa veya BASIC’teki bir alt programa eşdeğerdir.

Aşağıdaki şekilde, mul( ) fonksiyonunu kullanan çok basit bir program sunmaktadır. Program aşağıdaki çıktıyı yazdıracaktır.

/*————————— PROGRAM USING FUNCTION —————————*/
int mul (int a, int b); 
/*——— DECLARATION ——————*/ 
/*—————————— MAIN PROGRAM BEGINS ——————————*/
main (){
 int a, b, c;
 a = 5;
 b = 10; 
 c = mul (a,b); 
 printf ("multiplication of %d and %d is %d" ,a,b,c);
}
/* ——————————  MAIN PROGRAM ENDS MUL() FUNCTION STARTS —————————————*/
 int mul (int x, int y){ 
  int p;
  p = x*y;
  return(p);
 }
/* —————————————— MUL () FUNCTION ENDS ————————————*/

mul() fonksiyonu x ve y’nin değerlerini çarpar ve ifadede return edildiğinde sonuç main( ) fonksiyona döner.

c = mul (a, b);

mul( ), integer olarak tanımlanan x ve y olmak üzere iki bağımsız değişkene sahiptir. a ve b’nin değerleri, mul( ) fonksiyonu çağrıldığında sırasıyla x ve y’ye aktarılır.

3.7 ÖRNEK PROGRAM 5: MATEMATİK FONKSİYONLARININ KULLANIMI

Sıklıkla cos, sin, exp, vb. gibi standart matematiksel fonksiyonları kullanırız. Şimdi bir programda matematiksel fonksiyonun kullanımını göreceğiz. Standart matematiksel fonksiyonlar, C math library’nin bir parçası olarak tanımlanır ve tutulur. Bu matematiksel fonksiyonlardan herhangi birini kullanmak istiyorsak programa bir #include komutu eklemeliyiz. #define gibi, compiler’a kitaplıktan belirtilen matematiksel fonksiyonları linkleme talimatı veren bir compiler direktifidir. Instruction #include <math.h> biçimindedir. math.h gerekli fonksiyonu içeren dosya adıdır.

Aşağıdaki şekil, kosinüs fonksiyonunun kullanımını göstermektedir. Program 0, 10, 20………….180 açıları için kosinüs değerlerini hesaplar ve sonuçları başlıklarla birlikte yazdırır.

/*——————— PROGRAM USING COSINE FUNCTION ——————— */
#include <math.h>
#define PI 3.1416
#define MAX 180

main ( ){ 
 int angle;
 float x,y;
 angle = 0; 
 printf("Angle Cos(angle)\n\n"); 
 while(angle <= MAX) {
  x = (PI/MAX)*angle;
  y = cos(x);
  printf(“%15d %13.4f\n”, angle, y); 
  angle = angle + 10;
 }
}

Sıklıkla gerekli olan başka bir #include instruction’ı da #include <stdio.h> stdio.h, standart standard I/O fonksiyonlarını içeren standart I/O header dosyasına atıfta bulunur.

3.7.1 #include Direktifi

Daha önce de belirtildiği gibi, C programları modüllere veya fonksiyonlara bölünmüştür. Bazı fonksiyonlar bizim gibi kullanıcılar tarafından yazılır ve birçoğu C library’de depolanır. Library fonksiyonları kategori bazında gruplanır ve header dosyaları olarak bilinen farklı dosyalarda saklanır. Library’de saklanan fonksiyonlara erişmek istiyorsak, compiler’a erişilecek dosyalardan bahsetmek gerekir. Bu, önişlemci direktifi #include kullanılarak aşağıdaki gibi elde edilir: #include filename, gerekli fonksiyon tanımını içeren library dosyasının adıdır. Önişlemci yönergeleri bir programın başına yerleştirilir. Library fonksiyonları ve bunları içeren header dosyalarının bir listesi ilerde Appendix III’te anlatılacaktır. https://www.geeksforgeeks.org/cc-preprocessors/ 3.8 C PROGRAMLARININ TEMEL YAPISI Şimdiye kadar tartışılan örnekler, bir C programının fonksiyonlar adı verilen bir yapı taşları grubu olarak görülebileceğini göstermektedir. Fonksiyon, belirli bir görevi gerçekleştirmek için tasarlanmış bir veya daha fazla ifadeyi içerebilen bir alt programdır. Bir C programı yazmak için önce fonksiyonlar oluşturur, sonra onları bir araya getiririz. C programı, aşağıdaki şekilde gösterildiği gibi bir veya daha fazla bölüm içerebilir. Documentation bölümü, programın adını, yazarını ve programcının daha sonra kullanmak isteyeceği diğer ayrıntıları veren bir dizi yorum satırından oluşur. Link bölümü, sistem library’den fonksiyonların linklenmesi için derleyiciye instructionlar sağlar. **Definition **bölümü tüm sembolik sabitleri tanımlar. Global declaration bölümü, Birden fazla fonksiyonda kullanılan bazı değişkenler vardır. Bu tür değişkenlere *global *değişkenler denir ve tüm fonksiyonların dışında kalan global declaration bölümünde tanımalnır. Bu bölüm aynı zamanda tüm kullanıcı tanımlı fonksiyonları tanımlar. Main fonkiyonu bölümü, Her C programında bir main() işlev bölümü olmalıdır. Bu declaration ifade kısmı ve executable kısım olmak üzere iki kısımdan oluşmaktadır. Declaration kısmı, executable kısımda kullanılan tüm değişkenleri bildirir. Executable kısımda en az bir ifade vardır. Bu iki kısım, açılış ve kapanış parantezleri arasında görünmelidir. Programın yürütülmesi açılış ayracı ile başlar ve kapanış ayracı ile biter. main fonksiyonunun kapanış ayracı, programın mantıksal sonudur. Declaration ve executable bölümlerdeki tüm ifadeler noktalı virgülle (;) biter. Subprogram bölümü, main fonksiyonu tarafından çağrılan tüm kullanıcı tanımlı fonksiyonları içerir. Kullanıcı tanımlı fonksiyonlar, herhangi bir sırayla görünseler de, genellikle main fonksiyonun hemen sonrasına yerleştirilir. Main fonksiyonu bölümü dışındaki tüm bölümler, gerekli olmadığında dahil olmayabilir. https://data-flair.training/blogs/basic-structure-of-c-program/ 3.9 PROGRAMLAMA STİLİ Diğer bazı programlama dillerinin (COBOL, FORTRAN, vb.) aksine, C serbest biçimli (free-form_language) bir dildir. Yani, C compiler satırın neresinde yazmaya başladığımızı umursamıyor. Bu, kötü programlama için bir lisans olsa da, okunabilir programlar geliştirirken bu gerçeği kendi avantajımıza kullanmaya çalışmalıyız. Birkaç alternatif stil mümkün olsa da, bir stil seçmeli ve onu tam bir tutarlılıkla kullanmalıyız. Öncelikle küçük harflerle program yazma alışkanlığını geliştirmeliyiz. C programı ifadeleri küçük harflerle yazılır. Büyük harfler sadece sembolik sabitler için kullanılır. Ayraçlar, program ifadelerini birlikte gruplayın ve fonksiyonların başlangıcını ve sonunu işaretleyin. Parantezlerin ve ifadelerin uygun girintileri, bir programın okunmasını ve hata ayıklamasını kolaylaştıracaktır. Parantezlerin nasıl hizalandığına ve ifadelerin aşağıdaki şekildeki programda girintili olduğuna dikkat edin. C serbest biçimli bir dil olduğundan; 1. ifadeleri tek bir satırda gruplandırabiliriz. a = b; x = y + 1; z = a + x; ---------------- main( ){ printf(“hello C”); } 2. İfadeleri tek satır olarak yazabiliriz. a = b; x = y+1; z = a+x; ------------ main( ) {printf("Hello C")}; Ancak bu üslup programın anlaşılmasını zorlaştırır ve kullanılmamalıdır. Bu yazılar serisinde her ifade ayrı bir satıra yazılacaktır. Bir program içindeki yorumların cömertçe kullanılması ne kadar vurgulansa azdır. Akıllıca eklenen yorumlar yalnızca okunabilirliği artırmakla kalmaz, aynı zamanda program mantığını anlamaya da yardımcı olur. Bu, programda hata ayıklamak ve test etmek için çok önemlidir. 3.10 BİR ‘C’ PROGRAMININ YÜRÜTÜLMESİ C ile yazılmış bir programı yürütmek bir dizi adım içerir. Bunlar: 1. Programın oluşturulması; 2. Programı compile edilmesi; 3. Programı C kütüphanesinden ihtiyaç duyulan fonksiyonlarla linklenmesi; 4. Programın yürütülmesi. Aşağıdaki şekil, bir C programı oluşturma, compile etme ve çalıştırma sürecini göstermektedir. Bu adımlar işletim sisteminden bağımsız olarak aynı kalsa da, adımları uygulamaya yönelik sistem komutları ve dosyaları adlandırma kuralları farklı sistemlerde farklılık gösterebilir. İşletim sistemi, bir bilgisayar sisteminin tüm işleyişini kontrol eden bir programdır. Tüm input/output işlemleri işletim sistemi aracılığıyla kanalize edilir. Donanım ile kullanıcı arasında bir arayüz olan işletim sistemi, kullanıcı programlarının yürütülmesini sağlar. Günümüzün en popüler iki işletim sistemi UNIX (mini bilgisayarlar için) ve MS-DOS’tur (mikro bilgisayarlar için). C programlarının bu iki işletim sisteminde çalıştırılmasında izlenecek prosedüre aşağıdaki bölümlerde kısaca değineceğiz. 3.11 UNIX SİSTEMİ 3.11.1 Programın Oluşturulması UNIX işletim sistemini memory’e yükledikten sonra, Bilgisayar, programı almaya hazırdır. Program bir dosyaya girilmelidir. Dosya adı harflerden, rakamlardan ve özel karakterlerden, ardından bir nokta ve bir c harfinden oluşabilir. Geçerli dosya adlarına örnekler:hello.c program.c ebg1.c Dosya, ed veya vi gibi bir metin düzenleyicinin yardımıyla oluşturulur. Düzenleyiciyi çağırmak ve dosyayı oluşturmak için komut şu şekildedir:vi filename Dosya daha önce mevcutsa yüklenir. Henüz mevcut değilse, yeni programı almaya hazır olması için dosyanın oluşturulması gerekir. Programdaki herhangi bir düzeltme editör altında yapılır. (Sistem düzenleyicinizin adı farklı olabilir. Sistem kılavuzunuzu kontrol edin.) Düzenleme bittiğinde, dosya diske kaydedilir. Daha sonra herhangi bir zamanda dosya adıyla referans alınabilir. Dosyaya girilen program, programın orijinal halini temsil ettiği için kaynak program olarak bilinir. 3.11.2 Compiling ve Linking Kaynak programın ebg1.c adlı bir dosyada oluşturulduğunu varsayalım. Artık program compile edilmeye hazır. UNIX altında bu görevi gerçekleştirmek için derleme komutu cc ebg1.c ile Kaynak program instructionlarını artık bilgisayar tarafından yürütülmeye uygun bir forma çevrilmiştir. Çeviri, her instruction doğruluğu incelendikten sonra yapılır. Her şey yolundaysa compiling sessizce devam eder ve compile edilen program ebg1.o adlı başka bir dosyada depolanır. Bu program object kodu olarak bilinir.Linking, programın gerektirdiği diğer program dosyalarını ve işlevleri bir araya getirme işlemidir. Örneğin program exp() fonksiyonunu kullanıyorsa bu fonksiyonun object kodu sistemin math library’den getirilmeli ve main programa bağlanmalıdır. UNIX altında, cc komutu kullanıldığında linking olarak yapılır (hata algılanmazsa).Dilin syntax ve semantic’te herhangi bir hata keşfedilirse, bunlar listelenir ve compile işlemi burada sona erer. Kaynak programdaki hatalar editör yardımıyla düzeltilmeli ve tekrar compile edilmelidir.Compile edilmiş ve link edilmiş program yürütülebilir object kodu olarak adlandırılır ve otomatik olarak a.out adlı başka bir dosyada saklanır. 3.11.3 Programı Yürütme Yürütme basit bir iştir. a.out komutu yürütülebilir object kodunu bilgisayarın memory’sine yükler ve instructionları yürütür. Yürütme sırasında, program klavyeden bazı verilerin girilmesini isteyebilir. Bazen program istenen sonuçları vermeyebilir. Belki de program mantığında veya verilerinde bir sorun vardır. Daha sonra kaynak programı veya verileri düzeltmek gerekli olacaktır. Kaynak programın değiştirilmesi durumunda, programın derlenmesi, bağlanması ve çalıştırılması sürecinin tamamı tekrarlanmalıdır. 3.11.4 Kendi Yürütülebilir Dosyanızı Oluşturma Linker’ın her zaman aynı a.out adını atadığına dikkat edin. Başka bir programı compile ettiğimizde, yeni programın yürütülebilir nesne kodu bu dosyanın üzerine yazılacaktır. Olmasını önlemek istiyorsak, mv a.out name komutunu kullanarak dosyayı hemen yeniden adlandırmalıyız. Bunu cc komutunda cc –o name source-file gibi bir seçenek belirterek de başarabiliriz. Bu, yürütülebilir object kodunu dosya adında saklayacak ve eski a.out dosyasının yok edilmesini önleyecektir. 3.11.5 Çoklu Kaynak Dosyaları Birden çok kaynak program dosyasını compile etmek ve linklemek için, tüm dosya adlarını cc fi lename-1.c …. fi lename-n.c biçiminde cc komutuna eklemeliyiz. Bu dosyalar ayrı ayrı object dosyaları olarak derlenecektir. filename-i.o ve ardından aşağıdaki şekilde gösterildiği gibi çalıştırılabilir bir program dosyası a.out oluşturmak için bağlanır. Her dosyayı ayrı ayrı derlemek ve daha sonra bağlamak da mümkündür. Örneğin, cc –c mod1.c, cc –c mod2.c komutları kaynak dosyalarını mod1.o ve mod2.o object dosyalarında derleyecektir. ayrıca kaynak dosyaları ve object dosyalarını cc mod1.c mod2.o şeklinde birleştirebiliriz: Yalnızca mod1.c derlenir ve ardından mod2.o object dosyasıyla linklenir. Bu yaklaşım, çoklu kaynak dosyalardan birinin değiştirilmesi ve yeniden derlenmesi gerektiğinde veya önceden var olan bir object dosyasının derlenecek programla birlikte kullanılması gerektiğinde yararlıdır. 3.12 MS-DOS SİSTEMİ Program, belge dışı modda herhangi bir kelime işlemci yazılımı kullanılarak oluşturulabilir. Dosya adı program.c, pay.c vb. gibi “.c” karakterleri ile bitmelidir. Daha sonra MS-DOS işletim sistemi altında MSC pay.c komutu pay.c dosyasındaki programı yükler ve object kodunu oluşturur. Bu kod, pay.obj adı altında başka bir dosyada saklanır. Herhangi bir dil hatası bulunması durumunda derleme tamamlanmaz. Program daha sonra düzeltilmeli ve yeniden derlenmelidir. Bağlantı, pay.exe dosya adına sahip yürütülebilir kodu oluşturan LINK pay.obj komutuyla yapılır. Şimdi pay komutu programı çalıştıracak ve sonuçları verecektir.