PDA

Tam Sürümünü Görmek İçin : kodlarda iyileştirme -C-


LEthaL
19/11/2003, 22:52
Gerekli açıklamaları kodun satır aralarında yaptım.
Girilen karakter dizisini onluk sayısal sisteme çeviren bir kod dizemiz var.
Programın daha hızlı çalışması, kodlamadaki fazlalıklar...
Yapabileceğimiz iyileştirmeleri yazarsanız -gerek bana gerekse ilgilenenlere- yararı olacağına inanıyorum.
#include <stdio.h>
#include <string.h>

/* Bu kisim kullanilmiyor. #define kullanip yapmayi dusunmustum ama
vazgectim :)
/*
#define M 1000
#define C 100
#define L 50
#define X 10
#define V 5
#define I 1
*/

/* Global Roma rakamlarinin tutulacagi dizi
Baslangicta hepsinin degeri 0 (neden 0 oldugunu ilerki kisimda anlayacagiz)
*/
int rom[]={0,0,0,0,0,0,0,0,0,0};

/* rom dizisi sayi tipinde oldugu icin icindekiler aslinda harlerin
sayisal karsiliklari C icin 88 gibi asagidaki islev string.h
baslik kutuphanesinde yoktu ben de yazayim dedim.
Bir dizi icinde aranan harfi istenilen sayi ile degistirme gorevini
goruyor. rom dizimizin icindeki harfleri teker teker degistirmek icin
*/
char *cevir(char aranan,int degistirilecek,int *str){
int i=0;
while(str[i]) {
if( (int) aranan == str[i] )
str[i] = degistirilecek;
++i;
}
return str;
}

// Kullanicinin girdigi "CCCXIV" gibi seti rom dizimize yerlestiriyor.
void rome2dig(char *rkm){
int i;
for(i=0;i<strlen(rkm);++i) {
rom[i]=rkm[i];
// printf("%d\n",rom[i]); Kontrol amacli yazdirma islemi
}
}

// Isi goren Islev (fonksiyon)
int main() {
int i,j,vr=0;
int sayi,toplam=0;
char *girilen;
clrscr();

printf("Roma Rakimini Giriniz: ");
gets(girilen);

// Kullanicidan gelen karakter dizisini diziye oldugu gibi yerlestiriyoruz
rome2dig(strupr(girilen));
// strupr kullanicidan gelen xi gibi kucuk harfler icin.

// Teker teker tum roma rakamlari sayisal degerlerine cevrilip
// diziye yerlestiriliyor. cevir islevimizi cagiriyoruz
cevir('C',100,rom);
cevir('M',1000,rom);
cevir('L',50,rom);
cevir('X',10,rom);
cevir('V',5,rom);
cevir('I',1,rom);

/* Diziye yerlestirdik, sayisal degerlerine cevirip c->100, l->50 gibi
tekrar rom isimli dizimizi duzenledikten sonra asil sayisal cevrim isi
basliyor.
*/
for(i=9;i>=0;--i) {
j=i-1;
sayi=rom[i];
while(rom[i]>rom[j]) {
if(j<0)
break;
sayi -= rom[j];
--j;
vr=1;
}
toplam += sayi;
if(vr) {
i=j+1;
vr=0;
}
}

printf("Sayisal Cevrim: %d\n\n\tCikmak icin herhangi bir tusa basin...",toplam);
getch();
return 0;
}


acehreli
21/11/2003, 19:32
Selam LEthaL,

Gorebildigim hatalar/gelistirmeler sunlar:

1) rom dizgisinin global olmasina gerek yok. Onu global olarak kullanan tek islev olan rome2dig'i hedef dizgiyi alacak sekilde degistirirsen rom'u ornegin main icinde tanimlayabilirsin.

Boylece programda birden fazla sayi kullanabilirsin. Yoksa rome2dig her seferinde tek dizginin icine yazar. Aslinda rome2dig'e de gerek yok. (bkz. 3)

2) cevir islevi derleme hatasina yol aciyordu. 'char *' yerine 'int *' donduruyordu. Donus turu bu programda kullanilmadigi icin 'char *'i void yaptim.

3) rome2dig icinde strlen islevi for dongusu her isletildiginde gereksizce tekrar tekrar cagrilir. Dizginin boyunu bir kere ogrenip kullanmak isteyebilirsin:


void rome2dig(char *rkm){
int i;
size_t const uzunluk = strlen(rkm);
for(i=0;i<uzunluk;++i) {
rom[i]=rkm[i];
}
}


Ama tabii daha da iyisi; rome2dig'i bosverip, onun isini olabilecek en hizli sekilde yapan standart strcpy'yi kullanabilirsin ;)

4) gets(girilen); satirinda iki tane hatan var:

4a) girilen'in gosterdigi yer sana ait degil; oraya okuma yapamazsin.

4b) gets hedefin ne kadar buyuk oldugunu bilmedigi icin hic kullanilmamalidir; onun yerine fgets'i kullan. ('gets'in belgelerinde aynen soyle yazar: "Never use gets()." (gets'i hicbir zaman kullanmayin.))

Ben soyle bir yontem uyguladim:


#include <stdlib.h>

/* ... */

/* 100 yeterli mi? :) */
size_t const uzunluk = 100;

/* ... */

girilen = malloc(uzunluk);
fgets(girilen, uzunluk, stdin);


5) Bu degisiklikleri yaptigimda program bana su karsiliklari verdi:

i -> 9
C -> 110

Galiba hatali calisiyor :) Ama hatanin nerede olduguna bakmadim. Belki de programi kendi ortamimda calistirmak icin yaptigim kucuk degisikler yuzundendir. Ornegin strupr'i benim ortamimda olmadigi icin soyle yazmak zorunda kaldim:


#include <ctype.h>

/* ... */

char * strupr(char * dizgi)
{
char * p;
for (p = dizgi; (*p = toupper(*p)); ++p)
;
return dizgi;
}


Ali