EK F: SEÇİLMİŞ PROBLEMLERE YANITLAR
Bu ekte, her bölümün sonunda verilen problemlerden bazıları için yanıtlar verilmiştir. Bazı problemler için değişik çözümler de söz konusu olabilir. Burada ilk sayı bölümü, ikinci sayı ise problemi belirtir.
1.1. Şunu deneyin:
int main (void) { int entry = 0; return entry; }
1.4. Evet, x=5;
deyimine eşdeğerdir.
1.5. Evet, boş bir blok deyimidir.
1.6.
… scanf("%f", &x); printf("%d", (int)x); …
2.2.
switch (yas)
case 16 : printf("…");
2.4.
#include <stdio.h> int main (void) { unsigned i, n; scanf("%u", &n); for (i=1; i<=n; i++) printf("%u\t%g\n", i*i, 1.0/i); return 0; }
2.6.
#include <stdio.h> int main (void) { int p, c, i; c = p = getchar(); i = 1; while (c!=EOF) { c = getchar(); if (c==p) i++; else { if (i==3) printf("%c ", p); p = c; i = 1; } /* else */ } /* while */ return 0; }
2.8. Satır 32’deki
do
’yu
uygun bir şekilde while
’a çevirin.
2.9.
#include <stdio.h> #include <float.h> #define b 10.0 int main (void) { double x, d, log; int i, di, xi, xj; /* başlıklar */ printf(" "); for (xj=0; xj<10; xj++) printf("%+9.2lf", xj/100.0); printf("\n +"); for (xj=0; xj<10; xj++) printf(" -------"); printf("\n"); for (xi=10; xi<100; xi++) { printf ("%5.2lf |", xi/10.0); for (xj=0; xj<10; xj++) { x = xi/10.0 + xj/100.0; /* log_b(x) hesaplama */ d = 1.0; log = 0.0; for (i=1; i<=DBL_DIG; i++) { x = x*x*x*x*x; x *= x; for (di=0; x>b; x/=b, di++) ; d *= 10.0; log += di/d; } /* for i */ printf ("%9.5lf", log); } /* for xj */ printf ("\n"); } /* for xi */ }
3.1. Gösterge aritmetiğine karşılık tamsayı
aritmetiği. Bu sistemde short
’un iki bayt
uzunluğunda olduğunu anlarız.
3.2.
#include <stdio.h> int main (void) { printf("%s-doldurma\n", (-10>>1<0)?"isaret":"sifir"); return 0; }
3.3.
#include <stdio.h> int main (void) { unsigned n, b; scanf("%u", &n); for (b=0; n!=0; n>>=1) b += n&1; printf("%d bit\n", b); return 0; }
3.4. Eğer a
ve b
aynı tipten ise içeriklerini değiştirir.
3.7. (a) değişkenlerin boş küme olarak ilklenmesi;
(b) n
sayısının kume1
’e eklenmesi;
(c) n
sayısının kume2
’den çıkarılması;
(d) iki kümenin aynı içerikte olup olmadığının denetlenmesi;
(e) iki kümenin bileşimi;
(f) küme farkı;
(g) kume2
veya kume3
’te olup da her
iki kümede olmayan sayıların kume1
’e konması.
4.1. Hayır! Bundan emin olamayız. Çünkü bu,
printf
fonksiyonu çağrısındaki argümanların hesaplanma sıralarına
bağlıdır.
4.2.
int maks (int x, ...) { int maks, *xg; for (maks = *(xg=&x); *xg != 0; xg++) if (maks < *xg) maks = *xg; return maks; }
Tanımda
(üç nokta) geri kalan parametrelerin sayılarının (ve tiplerinin)
belirlenmediği anlamına gelir. Ancak, böyle değişken sayıda argümanlı
fonksiyon yazmanın taşınabilir yolu bu değildir. Bunun yerine,
aşağıda gösterildiği gibi, ...
stdarg.h
standart başlık
dosyasında tanımlanmış bulunan va_start
,
va_arg
ve va_end
makroları
kullanılmalıdır.
#include <stdarg.h> int maks (int x, ...) { int maks; va_list xg; /* geri kalan argümanlara gösterge */ va_start(xg, x); /* ilk isimlendirilmemiş argümana * işaret et */ for (maks = x; x != 0; x = va_arg(xg,int)) if (x > maks) maks = x; /* yeni enbüyük */ va_end(xg); /* dönmeden önce temizlik yap */ return maks; }
4.3. İlklenmemiş otomatik değişkenler belirsiz değerler taşır. Bu, daha önce aynı adreste saklanmış olan bir otomatik değişkenin değeri olabilir.
4.4. Sadece ilk iki register
bildirimi dikkate alınır, geri kalanlar auto
gibi
işlem görürler. Aynı zamanda bir önceki alıştırmaya bakın.
4.5. Girilen satırdaki karakterleri tersten basar.
4.9. Sudoku bulmacalarını çözen program aşağıda verilmektedir:
#include <stdio.h> int sayi = 0; int tahta [9][9]; int tahtaTamam (int r, int c, int d) { int rr, cc; for (cc = 0; cc < 9; cc++) if (tahta[r][cc] == d) return 0; for (rr = 0; rr < 9; rr++) if (tahta[rr][c] == d) return 0; for (rr = r/3*3; rr < r/3*3+3; rr++) for (cc = c/3*3; cc < c/3*3+3; cc++) if (tahta[rr][cc] == d) return 0; tahta[r][c] = d; return 1; } void cozumyaz (void) { int r, c; printf("\n\n\tCOZUM %d\n\n", ++sayi); for (r = 0; r < 9; r++) { for (c = 0; c < 9; c++) printf("%2d", tahta[r][c]); printf("\n"); } } void yerlestir (int pozisyon) { int deger, r, c; if (pozisyon == 9*9) cozumyaz(); else { r = pozisyon / 9; c = pozisyon % 9; if (tahta[r][c] == 0) { for (deger = 1; deger <= 9; deger++) if (tahtaTamam(r,c,deger)) yerlestir(pozisyon+1); tahta[r][c] = 0; } else yerlestir(pozisyon+1); } } int main (void) { int r, c; char t; for (r=0; r<9; r++) for (c=0; c<9; c++) { do scanf("%c", &t); while (t=='\n' || t==' '); tahta[r][c] = (t>='1' && t<='9') ? (t-'0') : 0; } yerlestir(0); printf("\n\n%d adet cozum bulundu.\n", sayi); return 0; }
4.10. envp
dizisinin sonunu boş gösterge
kontrolü yaparak bulabiliriz:
#include <stdio.h> int main (int argc, char *argv[], char *envp[]) { int i; printf("Merhaba, benim ismim %s.\n", argv[0]); printf("Argumanlarim sunlar"); for (i=1; i<argc; i++) printf(", %s", argv[i]); printf(".\nOrtam degiskenlerim de sunlar:\n"); for (i=0; envp[i]!=NULL; i++) printf("%s\n", envp[i]); return 0; }
5.1. (a) sıfır, yani ilk sayıcı ve (b) belirsiz bir değer.
5.4.
int * | tamsayıya gösterge, |
int *[3] | tamsayıya 3 göstergeden oluşan dizi, |
int (*)[3] | 3 tamsayıdan oluşan diziye gösterge, |
int *(float) | argümanı
float olan ve int ’e
gösterge döndüren fonksiyon, |
int (*)(void) | argümanı olmayan ve
int döndüren fonksiyona gösterge. |
5.5. a[i,j]
ile a[(i,j)]
eşdeğerdir, bu da a[j]
’ye, yani bir göstergeye
eşdeğerdir.
5.6. x
dizi olmasına karşın,
a
bir göstergedir.
5.8. a
değişmez bir göstergedir; bundan
sonra hep &y
’yi göstermek zorundadır. Fakat
gösterdiği yer, yani y
içindeki bilgi değiştirilebilir.
b
de değişmez bir göstergedir, bunun
yanında gösterdiği yer, yani x
de program tarafından
değiştirilemez. Buna rağmen, bu yer program dışındaki bir süreç
tarafından değiştirilmektedir. Yani b
’nin gösterdiği
yeri program değiştiremez, sadece okuyabilir.
6.1.
typedef int * gosterge;
ile
#define gosterge int *
birbirine benzemektedir, ama
typedef int dizi[N];
#define
ile ifade edilemez, onun için
typedef
tercih edilir.
6.2.
#define dok(x) printf("x = %d\n", x)
Eğer Standarda uygun bir önişlemciniz varsa, o zaman aşağıdakini kullanın:
#define dok(x) printf(#x " = %d\n", x)
Makroyu, örneğin dok(2 * 3 + 4);
şeklinde çağırabilirsiniz.
7.9. Sistemimizde eğer unix-benzeri bir
ortamda derleme yapılıyorsa, __unix__
şeklinde bir makro
tanımlı gelir. Eğer bu makro tanımsızsa, başka bir işletim sistemi
(örneğin, Microsoft Windows) altında derleme yaptığımızı anlarız.
Aşağıdaki, fonksiyon, Linux dahil, unix-benzeri sistemlerde ve Windows
sistemlerinde doğru kodu çalıştıracaktır.
#include <stdlib.h> void temizle (void) { #ifdef __unix__ system("clear"); #else system("CLS"); #endif }
8.1.
#include <stdio.h> #include <time.h> #include <locale.h> int main (int argc, char *argv[]) { int ay, yil; struct tm yz; char cikti[20]; setlocale(LC_ALL, ""); if (argc!=3 || sscanf(argv[1], "%d", &ay)!=1 || sscanf(argv[2], "%d", &yil)!=1) { fprintf(stderr, "Kullanim: %s ay yil\n", argv[0]); return 1; } yz.tm_year = yil - 1900; yz.tm_mon = ay - 1; yz.tm_hour = 12; yz.tm_min = yz.tm_sec = 0; yz.tm_isdst = -1; for (yz.tm_mday=1; yz.tm_mday<=31; yz.tm_mday++) { if (mktime(&yz)==-1 || yz.tm_mon!=(ay-1)) break; if (strftime(cikti,sizeof cikti,"%a %d %b %Y",&yz)!=0) puts(cikti); } return 0; }