Picproje Elektronik Sitesi

SERBEST BÖLGE => Programlama ve Algoritma => Konuyu başlatan: baran123 - 25 Ağustos 2015, 21:04:38

Başlık: Switch Case sorusu
Gönderen: baran123 - 25 Ağustos 2015, 21:04:38

main
{
init();

while(1)
{
}

}

init()
{
state = 0;

swtich(state)
{
case 0 : state = 1; break;
case 1 : state = 2; break;
...
}
}


Case 1 işlenir mi ? yoksa 0 işlenip state 1 yapılsa bile break olduğu için döngü biter mi ?
Başlık: Ynt: Switch Case sorusu
Gönderen: Tagli - 25 Ağustos 2015, 21:08:00
İşlenmez. Yani kod case 1: içine girmez, init'ten çıkıp yoluna devam eder.
Başlık: Ynt: Switch Case sorusu
Gönderen: muhittin_kaplan - 25 Ağustos 2015, 21:11:39
fonksiyondan çıkarsın. 1 işletilmez
Başlık: Ynt: Switch Case sorusu
Gönderen: baran123 - 25 Ağustos 2015, 21:26:20
Denedim işlenmiyormuş.Teşekkürler.
Başlık: Ynt: Switch Case sorusu
Gönderen: magnetron - 25 Ağustos 2015, 22:30:14
bu yapının aynısı VB de de var
orda "select case" şeklinde

yalnız bende case ler çok fazla yaklaşık 50 tane

benim merak ettiğim acaba uygun yani o an aranan case 'i bulana kadar
mesela ben o anda diyelim case "z" arıyorum

"z" yi bulana kadar "a" "b" "c" ..... hepsini tarıyor mu ?
çünkü benim programda bir interpreter çalışıyor yani sürekli komut satırlarını tarayıp uygun case i çalıştırıyor
ve bilgisayar çok yavaşlıyor
bu arada bendeki sürüm VB 6.0
Başlık: Ynt: Switch Case sorusu
Gönderen: baran123 - 25 Ağustos 2015, 23:21:42
@magnetron
Evet tahminimce tarıyordur.Çünkü yazılım akışı yukarıdan aşağıya doğru olduğundan sizin z yi bulabilmesi için hepsine sıra ile bakması lazım.Daha performanslı bir kullanım için değerlerinizin ayır edici bir özelliği olması gerekir.Belki farklı algoritmalar vardır.
Mesela

void yiyecekBul(yiyecek)
{
    switch(yiyecekler)
    {
        case meyveler:
            switch(meyve)
            {
                case elma:  break;
                case armut: break;
            }
        break;

        case sebzeler:
            switch(sebze)
            {
                case domat:  break;
                case pattes: break;
            }
        break;
    }
}

void yiyecekBul(yiyecek)
{
   switch(yiyecekler)
   {
       case elma:   break;
       case armut:  break;
       case domat:  break;
       case pattes: break;
   }
}

Komik bir örnek oldu :D
Başlık: Ynt: Switch Case sorusu
Gönderen: MrDarK - 25 Ağustos 2015, 23:22:12
Büyük olasılıkla case sıralaman nereden başlıyorsa en üstte ondan itibaren bakıyor. Fakat şöyle bir not ekleyeyim bende buraya;

kod alanı az kaldığı için case mantığının fazla kod alanı yediğini düşünerek aynı şeyleri if else if lerle yazdığımda daha fazla kod alanı tuttuğunu bildireyim :) Yani switch case kullanımı daha az yer kapladı. Derleyici ARM GCC
Başlık: Ynt: Switch Case sorusu
Gönderen: sadogan - 25 Ağustos 2015, 23:25:22
Emin deyilim ama ilgili case adresini hesaplayıp direk oraya gider diye düşünüyorum.
8051 de bile dptr+a komutu vardı.
Hatta 16f819 için bir zamanlar asm yazdığım case yapısı söyle

CALL CEKBUTON
MOVF TEMP,W
ADDWF PCL,F
GOTO NORMAL_MOD ;0
GOTO AYAR_MOD ;1
GOTO EKSILT ;2
GOTO AYAR_DEGERI_GOSTER ;3
GOTO ARTIR ;4
GOTO TABLA_GOSTER ;5
GOTO AYAR_MOD_GOSTER ;6
GOTO NORMAL_MOD ;7

NORMAL_MOD ;0
CALL NORMAL_MOD_RUTINI
GOTO    LOOP

AYAR_MOD ;1
CALL AYAR_MOD_GOSTER_RUTINI ;*
GOTO    LOOP

EKSILT ;2
CALL EKSILT_RUTINI
GOTO    LOOP

AYAR_DEGERI_GOSTER ;3
CALL AYAR_DEGERI_GOSTER_RUTINI
GOTO    LOOP
ARTIR ;4
CALL ARTIR_RUTINI
GOTO    LOOP

TABLA_GOSTER ;5
CALL TABLA_GOSTER_RUTINI
GOTO    LOOP
AYAR_MOD_GOSTER
CALL AYAR_MOD_GOSTER_RUTINI ;6
GOTO LOOP
;7
Başlık: Ynt: Switch Case sorusu
Gönderen: Gökhan BEKEN - 25 Ağustos 2015, 23:52:31
@magnetron hocam bunun için farklı bir yöntem önereyim, fonksiyon gösterici denen bir olay var.
Bu konuda bir yazı yazmıştım: http://gokhanbeken.com/cc-fonksiyon-gostericilerifonksiyonu-adresi-ile-cagirmak (http://gokhanbeken.com/cc-fonksiyon-gostericilerifonksiyonu-adresi-ile-cagirmak)

mesela sizin case'inize 0 ila 255 arasında toplam 256 çeşit veri giriyor, bunların her birinde farklı bir fonksiyon var.
Yani şöyle:
state = 255;
swtich(state)
{
   case 0 : islem0(); break;
   case 1 : islem1(); break;
   ...

   case 254 : islem254(); break;
   case 255 : islem255(); break;

   ...
}

Yukarıdaki örnekte 255'inciyi bulana kadar bütün hepsini taramak zorunda kalacak.

Oysa aşağıdaki yapıda böyle birşeye gerek yok:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void islem0(void);
void islem1(void);
void islem2(void);
void islem3(void);
void islem4(void);
void islem5(void);
void islem6(void);
void islem7(void);
void islem8(void);
void islem9(void);

void (*fonksiyon_cagir)(void);

void* fonksiyonAdresleri[10]; //fonksiyonlarin pointer adreslerini tutan dizi
unsigned char state = 8;

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

//fonksiyonlarin adreslerini bir kereye mahsus diziye atiyoruz:
fonksiyonAdresleri[0]=&islem0;
fonksiyonAdresleri[1]=&islem1;
fonksiyonAdresleri[2]=&islem2;
fonksiyonAdresleri[3]=&islem3;
fonksiyonAdresleri[4]=&islem4;
fonksiyonAdresleri[5]=&islem5;
fonksiyonAdresleri[6]=&islem6;
fonksiyonAdresleri[7]=&islem7;
fonksiyonAdresleri[8]=&islem8;
fonksiyonAdresleri[9]=&islem9;




fonksiyon_cagir=fonksiyonAdresleri[state];


for(state=0;state<10;state++){
fonksiyon_cagir=fonksiyonAdresleri[state];
fonksiyon_cagir();
}


printf("\r\n");
  return 0;
}

void islem0(void){printf("fonksiyon 0 \r\n");}
void islem1(void){printf("fonksiyon 1 \r\n");}
void islem2(void){printf("fonksiyon 2 \r\n");}
void islem3(void){printf("fonksiyon 3 \r\n");}
void islem4(void){printf("fonksiyon 4 \r\n");}
void islem5(void){printf("fonksiyon 5 \r\n");}
void islem6(void){printf("fonksiyon 6 \r\n");}
void islem7(void){printf("fonksiyon 7 \r\n");}
void islem8(void){printf("fonksiyon 8 \r\n");}
void islem9(void){printf("fonksiyon 9 \r\n");}



mesaj birleştirme:: 25 Ağustos 2015, 23:54:27

Bu da ekran görüntüsü
(http://s3.postimg.cc/41dwwu89v/ekran_g_r_nt_s.png)
Başlık: Ynt: Switch Case sorusu
Gönderen: Tagli - 26 Ağustos 2015, 09:28:01
Konu hakkında pek bilgim yok ama bana da mantıklı gelen sadogan'ın anlattığı gibi olması. Yoksa zaten switch-case kullanmak için bir neden kalmazdı, çünkü if-else daha esnek bir yapı. "Computed Goto" yöntemiyle karşılaştırma ile zaman kaybetmeden doğrudan atlama yapılabilir. Ancak, süreksiz girdilerde bu iş nasıl yapılıyor onu aklımda canlandıramadım. Mesela case'ler 1, 2, 3 değil de 23, 45, 100 olsa acaba tablo boş mu bırakılıyor yoksa başka bir yöntem mi var? Boş tablo bilgisayarda sorun olmaz ama belleği sınırlı gömülü sistemler için iyi bir yaklaşım olmaz.
Başlık: Ynt: Switch Case sorusu
Gönderen: z - 26 Ağustos 2015, 09:40:15
ASM yazımda bu işlemi JMP tabloları ile yapıyoruz ve bu tablolarda Jump adresini seçen girdiler birbirini takip edecek veriler olmak zorunda.
Biz sadece en son adresin ötesinde değer gelip gelmediğini test ediyoruz. Değer bu değerden küçükse jmp tablsundan sıçramaya izin veriyoruz.

Programı yazarken buna dikkat ediyoruz. Eğer dinamik bir tablo olmayacaksa yani jmp adresleri program içinde değiştirilmeyecekse tabloları ramda değil romda tutuyoruz.
Başlık: Ynt: Switch Case sorusu
Gönderen: magnetron - 26 Ağustos 2015, 14:10:08
@Gökhan hocam

C 'de function pointer var - kullanıyorum da

ama ilk mesajda belirttiğim gibi bana VB 6.0 da lazım
Başlık: Ynt: Switch Case sorusu
Gönderen: muhittin_kaplan - 26 Ağustos 2015, 18:07:42
hocam ben kavrayamadım tam istediğinizi, biraz daha açık yazarmısınız ?
(select case in daha efektif bir halini mi arıyorsunuz vb de ? )
Başlık: Ynt: Switch Case sorusu
Gönderen: magnetron - 26 Ağustos 2015, 18:42:52
@muhittin hocam

diyelim VB 6.0 'da şöyle bir kodumuz  var

    Select Case var
    Case "A"
    -----------------
    Case "B"
    ------------------
    Case "C"
    -----------------
    -----------------
    -----------------
    -----------------
   Case "Z"
   ------------------
  End Select

bu select case kodunu kısaltmalardan oluşan
bir text dosyası çalıştırıyor

mesela şöyle

A   ... buraya bir parametre giriyor ve "A" case'i bu parametreyi alıp onunla bişey yapıyor
C   ...
Z   ...
Y   ...
G   ...
J    ...
M   ...
END

PLC 'lerin STL dilini biliyorsanız onun gibi bişey

bu text dosyası sürekli bir şekilde baştan sona işleniyor

işte problem burda başlıyor

benim tahminin VB 6.0 text dosyasından her satırı alıp
select case kodunun içinde o satırdaki emir "A" veya "H" veya "Y" neyse
onu arıyor

işte benim tahminim "A" emrini hemen buluyor "Y" emrini bulmak için
bütün select case kodunu sonuna kadar tarıyor

bu da bilgisayarı çok yavaşlatıyor

250 - 300 satırlık bu text dosyasını işlerken en baba Intel core işlemci bayılıyor
saniyede 20 scan 'e düşüyor

ben de bu tartışmayı görünce bu problemi sormak istedim

VB 6.0 da buna bir çare var mı diye
yani C dilindeki @Gökhan hocamın bahsettiği function pointer gibi
Başlık: Ynt: Switch Case sorusu
Gönderen: Gökhan BEKEN - 26 Ağustos 2015, 18:50:56
Doğrudan çözüm olmasa bile C dilinde yazılmış bir DLL işinizi görecektir.
Ben işlemciyi yoracak her işi C dilinde yazdığım DLL ile yaparım. Pointer ihtiyacı olan projelerde de aynısını yaparım.
Başlık: Ynt: Switch Case sorusu
Gönderen: yldzelektronik - 26 Ağustos 2015, 19:29:32
Düzeltme: Her ne kadar debug yaparken aşağıdaki cümleyi doğrulayacak şeylerle karşılaşsam da;
c de switch case her case değeri için tarama yapmıyor.Switch içine girdikten sonra ilgili case değerine zıplıyor.

Şimdi baktığımda söylediğimin aksiymiş;
http://www.cagataycebi.com/programming/c_programming/c_programming_4.html (http://www.cagataycebi.com/programming/c_programming/c_programming_4.html)
Başlık: Ynt: Switch Case sorusu
Gönderen: muhittin_kaplan - 26 Ağustos 2015, 23:08:59
şimdi switch yada select çalışmasında bir farklılık yok,

aranan değer bulunduğunda yapılması istenen yapılır ve ve select yada switch den çıkılır. ama bu arama işlemi 300 çeşitşe ve en sondaysa en sona kadar gitmek zorundadır. hiç bukadar uzun selectlerim olmadı (zaten pekde kullanmam açıkcası) ama olsa ne yapardım, düşünelim.

mesaj birleştirme:: 26 Ağustos 2015, 23:13:21

sql ve veritabanı biliyormusunuz hocam ?
300 kayıtlı basit bir veritabanı hazırlarım, doğrudan çekerim
aslında vb.net kullansanız veritabanını ram de de oluşturabilirsiniz (dataset,XML)
Başlık: Ynt: Switch Case sorusu
Gönderen: z - 26 Ağustos 2015, 23:25:39
Successful Approximation Register yapısına bir göz at.

256 seçenek olsun. En fazla 8... bilemedin 12 karşılaştırma ile şak diye ilgili hedefe gidebilirsin.


Başlık: Ynt: Switch Case sorusu
Gönderen: Burak B - 27 Ağustos 2015, 01:32:36
Derleyiciler genelde siwtch/case için jump table oluşturmayı tercih eder. Böylece verilen parametre ile index hesaplayarak direkt offsete sıçrar. Yani oturup acaba gelen a mı B mi diye bakmaz. Çünkü switch yapısındaki durum programcı açısından görecelidir. İşlemci açısından kıyaslama ihtiyacı doğuran bir yapısı yoktur.
Başlık: Ynt: Switch Case sorusu
Gönderen: pea - 27 Ağustos 2015, 09:11:31
Renesas HEW'ın derleyicisi tek tek karşılaştırmayı tercih ediyor:
  29 switch(command){
     FE2516 39FC                          MOV.W       -4H[FB],R0
     FE2518 DA24                          JEQ         FE253DH
     FE251A E991                          CMP.W       #1H,R0
     FE251C DA64                          JEQ         FE2581H
     FE251E E992                          CMP.W       #2H,R0
     FE2520 9A04                          JNE         FE2525H
     FE2522 CEA700                        JMP.W       FE25CAH
     FE2525 E993                          CMP.W       #3H,R0
     FE2527 9A04                          JNE         FE252CH
     FE2529 CEB800                        JMP.W       FE25E2H
     FE252C E994                          CMP.W       #4H,R0
     FE252E 9A04                          JNE         FE2533H
     FE2530 CE0701                        JMP.W       FE2638H
     FE2533 E995                          CMP.W       #5H,R0
     FE2535 9A04                          JNE         FE253AH
     FE2537 CE2501                        JMP.W       FE265DH
     FE253A CE5701                        JMP.W       FE2692H

Optimizasyon en yüksek seviyedeyken de durum aynı.
Başlık: Ynt: Switch Case sorusu
Gönderen: Burak B - 27 Ağustos 2015, 12:28:34
@pea olabilir vardır bir bildikleri demek ki. Diğer derleyiciler nasıl yapıyor birkaç örnek ile bakalım

x86 - Derleyici Bilinmiyor

jmp     ds:off_10071F28[eax*4] ; switch jump
...
...
                align 4
off_10071F28    dd offset loc_10071D4A ; jump table for switch statement
                 dd offset loc_10071D5B 
                 dd offset loc_10071D67
                 dd offset loc_10071D89
                 dd offset loc_10071D95
                 dd offset loc_10071DA6
                 dd offset loc_10071DB7
                dd offset loc_10071DC3
                 dd offset loc_10071DD4
                dd offset loc_10071DE5
                 dd offset loc_10071E1F
...
...
...



ARMCC -O3

ER_IROM1:08009890                 PUSH            {R4,LR}
ER_IROM1:08009892                 CMP             R1, #5  ; switch 5 cases
ER_IROM1:08009894                 BCS             def_8009896 ; jumptable 08009896 default case
ER_IROM1:08009896                 TBB.W           [PC,R1] ; switch jump
ER_IROM1:08009896 ; ---------------------------------------------------------------------------
ER_IROM1:0800989A jpt_8009896     DCB 3                   ; jump table for switch statement
ER_IROM1:0800989B                 DCB 0x10
ER_IROM1:0800989C                 DCB 0x13
ER_IROM1:0800989D                 DCB 0x16
ER_IROM1:0800989E                 DCB 0x19
ER_IROM1:0800989F                 ALIGN 2


ARMCC -O0

ER_IROM1:0800A510                 PUSH            {R4-R6,LR}
ER_IROM1:0800A512                 MOV             R6, R0
ER_IROM1:0800A514                 MOV             R4, R1
ER_IROM1:0800A516                 MOV             R5, R2
ER_IROM1:0800A518 pconn = R6                              ; netconn *
ER_IROM1:0800A518 event = R4                              ; netconn_evt
ER_IROM1:0800A518 len = R5                                ; u16_t
ER_IROM1:0800A518                 CMP             event, #5 ; switch 5 cases
ER_IROM1:0800A51A                 BCS             def_800A51C ; jumptable 0800A51C default case
ER_IROM1:0800A51C                 TBB.W           [PC,event] ; switch jump
ER_IROM1:0800A51C ; ---------------------------------------------------------------------------
ER_IROM1:0800A520 jpt_800A51C     DCB 3                   ; jump table for switch statement
ER_IROM1:0800A521                 DCB 0xF
ER_IROM1:0800A522                 DCB 0x14
ER_IROM1:0800A523                 DCB 0x19
ER_IROM1:0800A524                 DCB 0x1E
ER_IROM1:0800A525                 ALIGN 2


ARMv7 (Bilinmeyen Derleyici)

MCU_FLASH:08002570 028 18 F8 01 4B                             LDRB.W  R4, [R8],#1     ; Load from Memory
MCU_FLASH:08002574 028 5B F8 04 7B                             LDR.W   R7, [R11],#4    ; Load from Memory
MCU_FLASH:08002578 028 24 2C                                   CMP     R4, #0x24       ; switch 37 cases
MCU_FLASH:0800257A 028 00 F2 72 80                             BHI.W   def_800257E     ; jumptable 0800257E default case
MCU_FLASH:0800257A
MCU_FLASH:0800257E 028 DF E8 04 F0                             TBB.W   [PC,R4]         ; switch jump
MCU_FLASH:0800257E
MCU_FLASH:0800257E                             ; ---------------------------------------------------------------------------
MCU_FLASH:08002582 028 13                      jpt_800257E     DCB 0x13                ; jump table for switch statement
MCU_FLASH:08002583 028 1E                                      DCB 0x1E
MCU_FLASH:08002584 028 1E                                      DCB 0x1E
MCU_FLASH:08002585 028 1E                                      DCB 0x1E
MCU_FLASH:08002586 028 1E                                      DCB 0x1E
MCU_FLASH:08002587 028 1E                                      DCB 0x1E
MCU_FLASH:08002588 028 1E                                      DCB 0x1E
MCU_FLASH:08002589 028 1E                                      DCB 0x1E


C18  (PIC18F2550)

740:               switch (g_lcdinfo.index) {
19C8  0105     MOVLB 0x5
19CA  51C0     MOVF 0xC0, W, BANKED
19CC  0A05     XORLW 0x5
19CE  E014     BZ 0x19F8
19D0  0A06     XORLW 0x6
19D2  E017     BZ 0x1A02
19D4  0A07     XORLW 0x7
19D6  E00B     BZ 0x19EE
19D8  0A04     XORLW 0x4
19DA  E004     BZ 0x19E4
19DC  0A01     XORLW 0x1
19DE  E002     BZ 0x19E4
19E0  0A03     XORLW 0x3
19E2  E10F     BNZ 0x1A02



XC8 (PIC18F4520)

0712  6E1F     MOVWF data, ACCESS
317:           {
318:               switch (data)
0714  D00B     BRA 0x72C
072C  501F     MOVF data, W, ACCESS
072E  0AC7     XORLW 0xC7
0730  B4D8     BTFSC STATUS, 2, ACCESS
0732  D7F3     BRA 0x71A
0734  0A17     XORLW 0x17
0736  B4D8     BTFSC STATUS, 2, ACCESS
0738  D7F6     BRA 0x726
073A  0A06     XORLW 0x6
073C  B4D8     BTFSC STATUS, 2, ACCESS
073E  D7EB     BRA 0x716
0740  0A0A     XORLW 0xA
0742  B4D8     BTFSC STATUS, 2, ACCESS
0744  D7EE     BRA 0x722
0746  0A01     XORLW 0x1
0748  B4D8     BTFSC STATUS, 2, ACCESS
074A  D7E5     BRA 0x716
074C  0A03     XORLW 0x3
074E  B4D8     BTFSC STATUS, 2, ACCESS
0750  D7E6     BRA 0x71E
0752  0A39     XORLW 0x39
0754  B4D8     BTFSC STATUS, 2, ACCESS
0756  D7E7     BRA 0x726
0758  0A17     XORLW 0x17
075A  B4D8     BTFSC STATUS, 2, ACCESS
075C  D7E2     BRA 0x722
075E  0A06     XORLW 0x6
0760  B4D8     BTFSC STATUS, 2, ACCESS
0762  D7DD     BRA 0x71E
0764  0A0A     XORLW 0xA
0766  B4D8     BTFSC STATUS, 2, ACCESS
0768  D7DC     BRA 0x722
076A  0A01     XORLW 0x1
076C  B4D8     BTFSC STATUS, 2, ACCESS
076E  D7D5     BRA 0x71A
0770  0A03     XORLW 0x3
0772  B4D8     BTFSC STATUS, 2, ACCESS



ARM EABIv5 (Derleyici muhtemelen RVCT )

ROM1:10021A26                 MOVS            R3, R1  ; Rd = Op2
ROM1:10021A28                 BLX             $Ven$AA$L$$__ARM_switch8 ; switch 8 cases
ROM1:10021A28 ; ---------------------------------------------------------------------------
ROM1:10021A2C                 DCB 7
ROM1:10021A2D                 DCB 5, 0xA, 0xE, 0x11, 0x15, 0x1A, 0x20, 0x23 ; jump table for switch statement
ROM1:10021A35                 ALIGN 2
ROM1:10021A36
ROM1:10021A36 loc_10021A36                           
ROM1:10021A36                 MOVS            R4, R2  ; jumptable 10021A28 case 0
....

Başlık: Ynt: Switch Case sorusu
Gönderen: z - 27 Ağustos 2015, 12:35:37
Case ile ele alınacak durumlarda hız uğruna romdan çok kaybedilebilir.

0,1,2,5,10 için ya da 50 51 52 55 gibi durumlar için tablo çok mantıklı fakat

0,1,2,5,10, 60, 100, 250 için tablo çok büyür.