Selam,
En son kaldığımız yerden devam edelim. Bu derste geçen derste öğrendiklerimi biraz daha detaylıca öğrenmeye çalışacağım.
Önemli bir konu daha var aslında: “Okunabilir Kod Yazmak“. Henüz yolun başındayken belirli standartları öğrenip, alışkanlık haline getirmek önemli. Bunu ayrı bir konu başlığı olarak ele almayı düşünüyorum.
IDE olarak Netbeans’e geçiş yaptım bu arada. Bu gereksiz bilgiden sonra devam ediyorum.
printf()
Buraya kadar printf()
ile hep düz metinler yazdım. Arada bir değişken de yazdırdım ama printf()
‘in hakkını tam vermedim. printf()
‘in sonundaki “f” formatlı çıktıyı belirtiyor. Bugün de biraz formatlı çıktılar yapalım.
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int x=3, y=5; printf("%d", x+y); // x ve y değişkenlerini toplayıp sonucu yazar. Yani 8 return 0; }
Yeni satıra geçmek için n kullanıyorduk. n aslında “kaçış karakter”lerinden (escape sequence) sadece birisi. “Ne kaçması ne karakteri?” dersen şöyle bir örnekle açıklayayım:
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { printf(" " "); return 0; }
Yukarıda ekrana “ yazdırmaya çalışıyorum. Bakalım kod çalışınca ne olacak?
main.c: In function 'main': main.c:7:16: warning: missing terminating " character [enabled by default] printf(" " "); ^ main.c:7:5: error: missing terminating " character printf(" " "); ^ main.c:8:5: error: expected ')' before 'return' return 0; ^ main.c:9:1: error: expected ';' before '}' token } ^
Neye niyet neye kısmet? Güzel bir hata mesajı aldık. Aslında her şeyi doğru yazmıştım. printf()
ile yazdırmak için ” “ arasında metni girmem yeterliydi.
printf(" " ")
yakından bakarsak, ilk 2 çift tırnak zaten metni almak için hazır. Sonradan gelen 3. çift tırnak ise programın kafasında deli sorular oluşmasına sebep oluyor. Bunu engellemek için programa ortadaki çift tırnağın, farklı olduğunu anlatmamız gerek. İşte şöyle:
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { printf(" " "); return 0; }
Çıktı:
"
Görüldüğü üzere görev başarıyla sonuçlandı. Aynı şekilde yazdırmak için \ yazmamız gerekirdi. gantep.edu‘dan aldığım tabloda diğer kaçış karakterli mevcut.
Karakter | Anlamı |
a | Ses üretir (alert) |
b | imleci bir sola kaydır (backspace) |
f | Sayfa atla. Bir sonraki sayfanın başına geç (formfeed) |
n | Bir alt satıra geç (newline) |
r | Satır başı yap (carriage return) |
t | Yatay TAB (horizontal TAB) |
v | Dikey TAB (vertical TAB) |
" | Çift tırnak karakterini ekrana yaz |
' | Tek tırnak karakterini ekrana yaz |
\ | karakterini ekrana yaz |
%% | % karakterini ekrana yaz |
printf()
‘in marifetleri bu kadar değil. Şimdi de biraz veri tiplerini formatlayalım.
İlk önce int, float ve double veri tipinde sayıları yazdırıyorum:
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int intSayi = 35; float floatSayi = 12; double doubleSayi = 1; printf("int: %dn", intSayi); printf("float: %fn", floatSayi); printf("double: %lfn", doubleSayi); return 0; }
Çıktı:
int: 35 float: 12.000000 double: 1.000000
float
ve double
tanımladığım sayılara otomatik olarak 6 basamak ondalık ekledi. Çünkü float
ve double
ondalıklı değerleri tutuyor. Peki, bana ondalıklı sayı lazım ama 6 tane ondalığa gerek yok. 2 tane ondalık yeter. Bu durumda ne öreceğiz?
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int intSayi = 35; float floatSayi = 12; double doubleSayi = 1; printf("float:%.2fn", floatSayi); //ondalık alan için 2 basamak göster printf("double:%.4lfn", doubleSayi); //ondalık alan için 4 basamak göster return 0; }
Çıktı:
float:12.00 double:1.0000
“.2” yazarak, floatSayi değişkeninin ondalık alanı için 2 değer gösterilmesini istediğimi söyledim. doubleSayi için ise “.4” diyerek ondalık alan için 4 değer göstermesini sağladım.
Biraz daha farklı durumlara bakalım.
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int intSayi = 35; float floatSayi = 12.53; double doubleSayi = 13.1789; printf("float:%5.2fn", floatSayi); printf("double:%8.5lfn", doubleSayi); return 0; }
Çıktı:
float:12.53 double:13.17890
floatSayi
için 5 basamaklı bir sayı olacağını ve ondalık alan için 2 basamak gösterilmesi gerektiğini belirttim. “.” yı saymayı ihmal etmiyoruz. Yani şöyle; 12 – . – 53 , toplamda 5 basamak sayılıyor.
doubleSayi
için ise, 8 basamaklı bir sayı dedim. Ondalık alan için de 5 basamak yer istedim. Lakin doubleSayi
‘nın değeri 13.1789 olduğu için ondalık alanda boş kalan değerleri 0 ile dolduruyor.
Yukarıda sayıları yazdırırken gerektiği kadar hatta fazla fazla yazdırdım. Peki 8 basamaklı sayıyı daha düşük basamaklı yazdırırsam ne olur? Test edip görelim.
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { printf("%5.2fn",12.346); printf("%5.3f",12.346); printf("%7.3f",12.346); return 0; }
İlk printf()
de 5 basamaklı bir sayı olacağını ve virgülden sonra 2 basamak yazmasını istedim.
İkinci printf()
de ise 5 basamaklı bir sayı olacağını ve virgülden sonra 3 basamak yazması gerektiğini belirttim. Ama 12.346 sayısı bizim için “.” da sayıldığı için 6 basamaklı.
Üçüncü printf()
ise ondalık alanı 3 basamak olacak şekilde 7 basamaklı bir sayı yazacak.
Bakalım çıktılar nasıl olacak?
12.35 12.346 12.346
İlk printf()
de virgülden sonra 3 basamak olmasına rağmen 2 basamak istediğim için sayıyı benim için yuvarladı. 12.346 sayısında olduğu gibi 0.5 ve üstü değerler bir üst değere yuvarlanıyor.
İkinci printf()
ise virgülden sonra 3 basamak yazıyor. Daha sonra bakıyor ki sayı 5 basamaklı olacak denilmiş ama yazması gereken 3 basamak daha var. Yani toplamda 6 basamak ediyor. Bu durumda otomatik olarak genişliyor ve sayıyı tam olarak yazıyor.
Üçüncü printf()
ise 6 basamaklı bir sayı yazacak olmasına rağmen bakıyor ki 7 basamaklıkmış gibi yazdırılması istenmiş. Virgülden sonra 3 basamak yazıyor ve geriye yazması gereken 4 basamak kalıyor. “12.” yazdıktan sonra hala yazması gereken bir basamak daha var. “Ne yapayım ne edeyim” deyip sayının önüne bir boşluk atarak uzaklaşıyor.
Geçtiğimiz derste değişkenlerin farklı veri tipleri tuttuğunu öğrenmiştim. Her değişken farklı aralıklarda değerleri tutabiliyordu. gantep.edu‘daki şu tabloya bir göz atalım:
Veri Tipi | Açıklama | Bellekte işgal ettiği boyut (bayt) | Alt sınır | Üst sınır |
char | Tek bir karakter veya küçük tamsayı için |
1 | -128 | 127 |
unsigned char | 0 | 255 | ||
short int | Kısa tamsayı için | 2 | -32,768 | 32,767 |
unsigned short int | 0 | 65,535 | ||
int | Tamsayı için | 4 | -2,147,483,648 | 2,147,483,647 |
unsigned int | 0 | 4,294,967,295 | ||
long int | Uzun tamsayı için | 8 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
unsigned long int | 0 | 18,446,744,073,709,551,615 | ||
float | Tek duyarlı gerçel sayı için (7 basamak) | 4 | -3.4e +/- 38 | +3.4e +/- 38 |
double | Çift duyarlı gerçel sayı için (15 basamak) | 8 | -1.7e +/- 308 | +1.7e +/- 308 |
Her değişkenin sınırları farklı olduğu gibi kapladıkları alanda farklı. “Beyin bedava, at beyine” demiştim ama değişkenlerin bilgiyi attığı ramler bedava değil. Ekonomik kullanmak zorundayız. Böylece yazdığımız programlar daha stabil ve performanslı çalışacaktır. “Hocam, bana 1 baytın hesabını mı yapıyorsun? Ram benim, değişken benim. double
basıp geçicem ben!” diye düşünebilirim. Üstelik günümüzdeki bilgisayarlarının ramlerinin de Maşallah’ı var hani. Ama hazırladağımız programı aynı anda binlerce, milyonlarca kişi kullanırsa ne olacak? 1 x 1.000.000 bayt ya da 8 x 1.000.000. Binlerce kişi kullanmasa bile 1 bayt alan için neden 8 bayt harcayıp israf yapalım? Neden bilgisayarı 8 kat hızlı çalıştıracakken yavaşlatalım? Son sözü halka bırakıyorum.
Şimdi gelelim kullandığımız veri tipine göre nasıl sonuçlar alıyoruz? Değişkenlerin sahip olduğu duyarlılığı daha iyi görebilmek için bazı matematiksel işlemler yapacağız. Daha duyarlı demek daha doğru sonuçlar demek.
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int intSonuc = 22 / 7; float floatSonuc = 22.0 / 7.0; double doubleSonuc = 22.0 / 7.0; long double longDoubleSonuc = 22.0 / 7.0; printf("Standart Duyarlılıkta Sonuçlarn"); printf("int: %dn", intSonuc); printf("float: %fn", floatSonuc); printf("double: %lfn", doubleSonuc); printf("longdouble: %Lfn", longDoubleSonuc); printf("Ondalık Alan için 10 basamaklı Sonuçlarn"); printf("int: %.10dn", intSonuc); printf("float: %.10fn", floatSonuc); printf("double: %.10lfn", doubleSonuc); printf("longdouble: %.10Lfn", longDoubleSonuc); printf("Ondalık Alan için 20 basamaklı Sonuçlarn"); printf("float: %.20fn", floatSonuc); printf("double: %.20lfn", doubleSonuc); printf("longdouble: %.20Lfn", longDoubleSonuc); printf("Ondalık Alan için 30 basamaklı Sonuçlarn"); printf("float: %.30fn", floatSonuc); printf("double: %.30lfn", doubleSonuc); printf("longdouble: %.30Lfn", longDoubleSonuc); printf("Ondalık Alan için 40 basamaklı Sonuçlarn"); printf("double: %.40lfn", doubleSonuc); printf("longdouble: %.40Lfn", longDoubleSonuc); }
Biraz uzun oldu ama değişkenlerin ne kadar duyarlı olduğunu şimdi çok daha iyi görebilirim. Çıktıyı alalım:
Standart Duyarlılıkta Sonuçlar int: 3 float: 3.142857 double: 3.142857 longdouble: 3.142857 Ondalık Alan için 10 basamaklı Sonuçlar int: 0000000003 float: 3.1428570747 double: 3.1428571429 longdouble: 3.1428571429 Ondalık Alan için 20 basamaklı Sonuçlar float: 3.14285707473754882812 double: 3.14285714285714279370 longdouble: 3.14285714285714279370 Ondalık Alan için 30 basamaklı Sonuçlar float: 3.142857074737548828125000000000 double: 3.142857142857142793701541449991 longdouble: 3.142857142857142793701541449991 Ondalık Alan için 40 basamaklı Sonuçlar double: 3.1428571428571427937015414499910548329353 longdouble: 3.1428571428571427937015414499910548329353
Varsayılan olarak değişkenleri yazdırdığımızda ilk olarak int
‘in sadece 3 yazdırdığını görüyoruz. E, çokta tabii değil mi Allah aşkına? Çünkü int
tam sayı değerleri tutmak için. Ondalık değerlerle işi yok.
Duyarlılığı 10 basamak arttırdığımızda, ayıp olmasın diye bir kez daha int’i de yazdırdım, float
‘ın diğerlerinden koptuğunu görüyoruz.
20 basamak olarak hesap yaptığımızda float
iyice kopmuş durumda fakat double
ve long double
aynı hassasiyette hesaba devam ediyorlar. Bakalım kim daha duyarlı? Çok heyecanlı. Gerçi sonucu biliyorum ama olsun 🙂
30 basamak olduğunda float
pes ediyor. double
ve long double
hala baş başa.
40 basamak için baktığımızda double
ve long double
arasında yine fark olmadığını görüyoruz.
Görüldüğü üzere double
veri tipi int
ve float
‘a göre daha fazla duyarlılığa sahip. Aradaki hesaplama farklılıkları nereden geliyor diyorsanız, veri tipinin algoritmasıyla alakalı bir durum. Detayları bende tam bilmiyorum ama aldığım istihbarata göre buradaki ve buradaki sayfalarda detaylı bilgi fazlasıyla mevcut. Gönül isterdi ki bunları çevirip şuraya bir özet çıkarayım ama şimdilik usulca diğer konuya geçiyorum.
Değişkenlerin tuttuğu verilerin program akışında değişebileceğini hatırlarsın. Ama değişkenlerin değişmesini engelleyebiliriz. Sabit bir değerde tanımlayabiliriz. Nasıl mı?
2 seçeneğimiz var: const
ve #define
İki komut sabit tanımlamaya yarasa da aralarında ciddi farklar bulunuyor öğrendiğim kadarıyla. Bu farklara az sonra değinirim. Şimdi nasıl sabit tanımlayacağımıza bakalım:
#include <stdio.h> #include <stdlib.h> const int HEDEF = 50; // const ile sabit tanımlama #define PI 3.14 // #define ile sabit tanımlama #define YAZDIR printf // #define'ın önemli farklarından biri int main(int argc, char** argv) { //#define ile sabit kullanımına örnek float alan, r=2.7; printf("#define ile sabit kullanımına örnekn"); alan = r*r*PI; YAZDIR("Alan: %.2fnn",alan); //const kullanımına örnek int simdi=13, kalan; printf("const kullanımına örnekn"); kalan = HEDEF - simdi; printf("Hedefe %d adım kaldı.", kalan); }
Yukarıda kodda ilk bakışta #define
ile const
arasındaki açık farklar belli oluyor. const
ile normal bir değişken tanımlarmış gibi davranıyorum. Tek yapmam gereken değişkenin sabit olduğu belirtmek için başına const
eklemek.
#define
ise tüm ezberleri bozuyor. const
ile sabit tanımlamaktan çok farklı. Ayrıca 6. satırdaki tanımlamanın 13. satırda nasıl kullanıldığına bakar mısınız efenim? Çok garip değil mi? “YAZDIR
” gördüğü zaman “printf
” yazması gerektiğini anlıyor.
#define
‘ın marifetleri bu kadar değil. Yeri gelince daha fazla değinirim ama şunu belirtmekte fayda var. #define ön işlemci komutlarından birisi ve bunları kullanırken oldukça dikkatli olmak gerekir. Birçok fayda sağlasada hata yapma ihtimalini de arttırır.
Mesela 13. satırdaki YAZDIR
tanımlaması kötü bir sabit tanımlamasıdır. C dilinde zaten standartı olan bu fonksiyonu kendimize göre tanımlayarak, bizden sonra gelen kişilerin kodu okumasını ve anlamasını zorlaştırırız.
Önemli bir diğer nokta ise sabitlere isim verirken büyük harf kullanmak. Böylece kodları okurken bunun sabit olduğunu anlayabiliriz. Program içinde sabit değerler değiştirilemeyeceği için, diğer değişkenlerle karışmaması adına böyle bir standart oluşmuş sanırım.
Yeri geldikçe bu konulara daha sık değinirim. Yukarıdaki kodun çıktısını vererek devam edelim:
#define ile sabit kullanımına örnek Alan: 22.89 const kullanımına örnek Hedefe 37 adım kaldı.
scanf()
Veri girişi için kullandığımız scanf()
ile ilgili birkaç önemli nokta var.
scanf()
, enter’a basılana kadar veri alır.scanf()
fonksiyonu ile birden fazla veri girişi yapılabilir. Ayrıca verilerin tipi farklı olabilir.#include <stdio.h> #include <stdlib.h> int main(){ int s1, s2; float s3; scanf("%d%d", &s1, &s2); printf("s1: %d, s2: %d", s1, s2); return 0; }
Yukarıdaki kod için şu değerleri giriyorum:
Hepsi için çıktı ortak:
s1: 1, s2: 7
Veri tipine uygun değer girmezsek sonuç ne olur?
#include <stdio.h> #include <stdlib.h> int main(){ int s1, s2; float s3; scanf("%f%d", &s3, &s1); printf("s1: %d, s3: %f", s1, s3); return 0; }
Yukarıdaki kod için 1 ve 7.3 değerlerini girersem çıktı:
s1: 7, s3: 1.000000
float
için girdiğim sayıya otomatik olarak ondalık ekledi ve int
için girdiğim ondalıklı sayının sadece tam kısmını aldı.
Önemli bir nokta ise placeholder’a uygun veri tipi yazılmazsa ne olur? Yani şöyle:
#include <stdio.h> #include <stdlib.h> int main(){ int s1, s2; float s3; scanf("%f%d", &s1, &s3); printf("s1: %d, s3: %f", s1, s3); return 0; }
s1 değişkeni int
veri tipinde ama scanf()
içindeki s1’in placeholder’ı %f
yani float
veri tipinde. s3 değişkeni de float
veri tipinde olmasına rağmen scanf()
içindeki placeholder’ı %d
yani int
veri tipinde.
Şimdi 7 ve 1.2 değerlerini giriyorum:
s1: 1088421888, s3: 0.000000
Böyle bir mantık hatasında düzgün bir sonuç beklemiyordun herhalde. lynda.com‘dan bir eğitim seti izlerken “garbage in, garbage out” demişti anlatan kişi. Bizdeki “ne ekersen onu biçersin” deyiminin karşılığı sanırım. Günümüzdeki birçok popüler dili yazarken anlık olarak hatalarımızı ide‘ler yakalıyor ama C’de bu durum söz konusu değil. O yüzden kodları yazarken dikkat etmek gerek.
Şimdi çok ilginç bir noktaya daha değinmek istiyorum. Bunu önce örnekle açıklamak daha iyi olur:
#include <stdio.h> #include <stdlib.h> int main(){ int s1; char karakter; scanf("%d%c", &s1, &karakter); printf("s1: %d, s3: %c", s1, karakter); return 0; }
Sırasıyla klavyeden şuları giriyorum: 9 ↵ y
Çıktı:
s1: 9, s3:
y karakteri kayıp! Nereye gitti, ne oldu? Aslında her şeyin çok basit bir açıklaması var. Biraz zamanı geriye sarıp, girdiğimiz verilere bakalım:
scanf("%d%c", &s1, &karakter);
%d
9 sayısını aldı.scanf()
benden bir karakter bekliyor. Ama o da ne? Zaten elimizde hazır bir karakter varmış: ↵%c
tarafından alınıyor ve scanf()
görevini yapmanın verdiği haklı gururla uzaklaşıyor. Ama orada “y” varmış yokmuş umrunda değil artık.Evet efenim, ↵ ‘da Allah’ın bir karakteri. 9 yazıp ↵’a bastığım zaman, girdi yolunda bekliyormuş bu ↵. Ne zaman ben bir karakter girmeye kalksam zaten ↵ hazırda beklediği için gelip benim değişkenime konuyor. Peki, yok mu bunun bir hal çaresi ya Rabbim?
İsviçreli bilim adamlarının kullandığı bir tekniği görüyoruz önce:
#include <stdio.h> #include <stdlib.h> int main(){ int s1; char karakter, enterYakala; scanf("%d", &s1); //int değerini alıyorum scanf("%c", &enterYakala); // hazırda bekleyen enter'ı bu değişkene aldım scanf("%c", &karakter); // şimdi yeni karakter alabilirim printf("%d %c", s1, karakter); return 0; }
Yine 9 ↵ y değerlerini giriyorum ve çıktıya bakıyorum:
9 y
İşte her şey olması gerektiği gibi. Neydi efenim: “garbage in, garbage out”
Bu konu biraz kafa karıştırıcı olabilir. Programlamaya yeni başlayan birisi bu kısmı atlayabilir.
Ve bugünlük değinmek istediğim son bir konu var. Kullanıcıdan bir sayı beklerken metin girerse ne olacak? Bunu engelleyebilir miyim?
#include <stdio.h> #include <stdlib.h> int main(){ int s1; scanf("%d", &s1); printf("%d", s1); return 0; }
Yukarıdaki kod bizden bir tam sayı bekliyor. Eğer “abc” yazarsam alacağım çıktı:
0
Görüldüğü üzere bu terslikte bir iş var. Ya da şöyle bir terslikte olabilir; her veri tipinin belirli aralıkta değerler tuttuğunu öğrenmiştim. Kullanıcıdan tam sayı beklerken ya tam sayı sınırının üstünde değer girerse? Yani int maksimum 2147483647 değerine kadar değer tutabiliyor. Kullanıcı 2147483647’den fazla bir değer girerse ne olacak?
Bu durumların çözümünü bulmak için biraz araştırma yaptım. Öncelikle anladığım, bu durumlar scanf()
‘in fıtratında var. scanf()
in günahını almışım efenim. Bu duruma “owerflow” deniliyor. Bu linkte benzer bir soruya verilen cevaplar mevcut. Anladığım kadarıyla çevirmeye çalışayım:
scanf("%d", &val);
Kullanıcıdan bir tam sayı girmesini bekliyoruz. Kullanıcı {‘n’, ‘t’, ‘ ‘, ‘1’, ‘2’, ‘3’, ‘n’} girerse scanf()
boşluk karakterlerini atlıyor ve enter’ı görene kadar veriyi alıyor. Değerimiz: 123
Kullanıcı “12w4” girerse, sen zannediyorsun ki scanf()
“bu sayı değil ki” deyip veriyi almayacak. Çok beklersin o zaman. Çünkü scanf()
12’yi alacak ve “w4″ü girişte bekletecek.
Son olarak, en son benimde bahsettiğim gibi kullanıcı çok pis uzunlukta bir sayı girdi: “1234567890123456789012345678901234567890” gibi. Eğer scanf()
‘in bu sayıyı red edeceğini düşünüyorsan yine çok beklersin. scanf()
ne yapıp ne edip o sayıyı alır, evirip çevirip ortaya bir sayı çıkarır. Bu durumunda basit bir izahı yazilimsozluk‘te 8. yorumda gizli.
Gelelim çözüme. Eğer bu tarz durumlarla adam akıllı baş etmek istiyorsan farklı bir araç kullanmak gerekecek: fgets()
ve strol()
. Bunların bize sağladığı avantajlar:
Minik bir de dezavantajı var: Birazcık daha fazla uğraşman gerekecek.
Bu konuyla ilgili olarak ekstra bir kaynak daha paylaşayım. Secure Coding Guide: Avoiding Integer Overflows and Underflows.Gerçi bu döküman biraz daha fazla teknik bilgi gerektiyor. yazilimsozluk‘te anlatılan durum da burada detaylıca anlatılmış.
Özet geçmem gerekirse, bilgisayar verileri 2lik sistemde (0 ve 1) saklıyor ve buna göre işlem yapıyor. int
olarak 2147483647 sayısının bir fazlası bilgisayar için 2lik sistemde – 2147483648 demek.
İşte böyle, öğrenilecek daha çok şey var. Henüz yolun başındayken oldukça ağır gelebilir bazı bilgiler. Şimdilik akışına bırakıp, zamanı gelince bu derin konulara yine el atarım. Buraya kadar belki bazı şeyleri yanlış öğrendim ve yanlış aktardım. Eğer yanlış ya da düzeltilmesi gereken bir nokta farkettiyseniz, lütfen bana bildirin.
Yalnız şunu da tekrar anlamış oldum ki, İngilizce şart!
printf()
ile formatlı çıktı almak için %f
yerine %x.yf
yazabilirim.int
yerine short
kullanabilirim mesela.#define
kullanırken ayrı ayrıca dikkat.scanf()
ile veri girilirken placeholer, veri tipi ve & önemli. Sık yapılan hatalar arasında.scanf()
için enter’da bir karakter. Dolayısıyla çoğu zaman veri giriş yolunda bir enter bekliyor olabilir. Yeni karakter girişi yapılmadan önce dikkat etmek lazım.Senaryo1: Kullanıcı gideceği mesafeyi ve ortalama hızını programa girecek. Program girilen verilere göre ortalama seyahat süresini hesaplayacak. Mesafe km, hız km/saat olduğunu varsayalım.
Senaryo2: 3 basamaklı bir sayının birler, onlar ve yüzler basamağını bulan program.
Eğitimim için kullandığım örnekleri bu adresteki github reposunda saklıyorum. Ders başlığıyla eşit olan klasörde kaynak kodları bulabilirsiniz.
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { double distance, speed, travelTime; puts("Please, input distance (km):"); //mesafeyi soruyoruz scanf("%lf", &distance); puts("Please, input your average speed (km/h):"); //ortalama hızını soruyoruz scanf("%lf", &speed); travelTime = distance / speed; //zaman = yol / hız formülüne göre hesap yapıyoruz printf("I think your travel may take %.2lf hour(s)", travelTime); return (EXIT_SUCCESS); }
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int number, hundred, ten, one; puts("Please, input 3-digit number:"); scanf("%d", &number); hundred = (number % 1000) / 100; ten = (number % 100) / 10; one = (number % 10); printf("%d, %d, %d", hundred, ten, one); return (EXIT_SUCCESS); }
Celery ile alakalı "best practice"leri ve faydalı araçları bir araya getiren güzel bir checklist'e denk…
Diziler en temel ve sık kullandığımız araçlardan... Kod yazarken işimizi kolaylaştıracak, daha temiz kod yazmamızı…
listve tuple bilginizi test etmek ister misiniz? realpython.com da keşfettiğim ve Türkçe'ye çevirdiğim mini teste…
Rehberlik sağlaması ve bilgi tazelemesi açısından faydalı olduğunu düşündüğüm bir Toptal blog paylaşımınıTürkçe'ye çevirdim.Devamını okuyunBilmeniz…
Angular componentlerine console üzerinden hızlıca erişmek için kullanılan bir teknik. Unutmamak için kendime not düşüyorum.Devamını…
Geçtiğimiz günlerde keşfettiğim ve oldukça da hoşuma giden repoyu paylaşmak istiyorum: lydiahallie/javascript-questions Genel olarak temel…