2009-08-29 29 views
31

Aşağıdaki gibi bir yaprağım var: chars öğesinin uzunluğunu döndürecek "length" adlı bir işleve işaretçi.C struct öğesinin üyesi olarak işlev işaretçisi

: bir PString bir işaretçiyi geri döndürmektedir

int length(PString * self) { 
    return strlen(self->chars); 
} 

(a işlev initializeString bulunmakta)

typedef struct pstring_t { 
    char * chars; 
    int (* length)(); 
} PString; 

bir PString bir işaretçi karakteri uzunluğuna geri dönmesini bir işlevi vardır

PString * initializeString() { 
    PString *str; 
    str->length = &length; 
    return str; 
} 

Bu str->length = &length hat benim ayıklayıcısında bir EXC_BAD_ACCESS sinyalini neden olduğundan `yaptığı gibi ben, burada, benim işaretçiler ile çok yanlış bir şey yapıyorum açıktır dönüş strlen (self> Char s). Bu problemle ilgili herhangi bir kavrayış var mı?

Özellikle initializeString() işlevinin PString'e bir işaretçi döndürmesini ve uzunluk işlevinin giriş olarak PString'e işaretçi kullanmasını istiyorum. Bu sadece C'deki temel bir nesne yönelimli sistemin uygulanmasındaki bir deneydir, ancak işaretçilerle başa çıkmada çok fazla tecrübem yok. Bana verebileceğin herhangi bir yardım için teşekkürler.

+2

. Bu durumda, bir yapının kendisini geri döndürmek çok daha iyi. Yapıyı kopyalamak ucuz ve ağır bir yığın ayırmaya gerek yok. Dize nesneleri değer temellidir: Kimlik (adres) içermezler, ancak eşitlikleri içeriklerine dayanır. Bir şekilde OOP sisteminizde de bu anlamda bir ayrım olabilir. –

cevap

48

Bellek kartlarını tutmak için bellek ayırın.

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

typedef struct PString { 
     char *chars; 
     int (*length)(); 
} PString; 

int length(PString *self) { 
    return strlen(self->chars); 
} 

PString *initializeString(int n) { 
    PString *str = malloc(sizeof(PString)); 

    str->chars = malloc(sizeof(char) * n); 
    str->length = length; 

    str[0] = '\0'; //add a null terminator in case the string is used before any other initialization. 

    return str; 
} 

int main() { 
    PString *p = initializeString(30); 
    strcpy(p->chars, "Hello"); 
    printf("\n%d", p->length(p)); 
    return 0; 
} 
+0

Harika cevap! Soru: Ücretsiz (p) aramam gerek ama aynı zamanda karakterleri de serbest bırakmalı mıyım? –

+0

Sanırım bir yıkıcı yazmam gerek. –

+12

"malloc" öğesinin dönüş değerini C'ye çevirmeye gerek yoktur. Ayrıca, str-> chars'ı, ayırdıktan sonra başlatmalısınız (örneğin. Str-> chars [0] = '\ 0'; ') . – caf

4

str işaretçisi hiçbir zaman tahsis edilmez. Kullanmadan önce malloc 'd olmalıdır.

+0

'PString * str;' 'PString * str = (PString *) malloc (sizeof (PString));' ile değiştirin ve ideal olarak, bellek sızıntılarını önlemek için kullanıldığında imleci kullanarak 'free' işlevini çağırın. – jgottula

6

Tahminimce, sorunun bir kısmı, eşleşmeyen parametre listeleridir.

int (* length)(); 

ve

int length(PString * self) 

aynı değildir. int (* length)(PString *); olmalıdır.

... woah, ben Jon!

numarasını düzenleyin: ve aşağıda belirtildiği gibi, yapısal işaretçiniz hiçbir zaman bir şey gösterecek şekilde ayarlanmamıştır. Bunu yaptığınız gibi, sadece düz bir yapı, işaretçi değilken çalışıyor olursunuz.

str = (PString *)malloc(sizeof(PString)); 
+0

Çok sağol Jacob. Devam edip bunu deneyeceğim. –

+0

Tamam, strlen (self-> chars) 'bana hala EXC_BAD_ACCESS verir. –

4

Belki de burada bir şeyleri özlüyorum, ancak bu PString için ona erişmeden önce herhangi bir bellek ayırttınız mı?

PString * initializeString() { 
    PString *str; 
    str = (PString *) malloc(sizeof(PString)); 
    str->length = &length; 
    return str; 
} 
0

Ayrıca işleve bir adres göndermek için "void *" (void * işaretçisi) kullanabilirsiniz.

typedef struct pstring_t { 
    char * chars; 
    int(*length)(void*); 
} PString; 

int length(void* self) { 
    return strlen(((PString*)self)->chars); 
} 

PString initializeString() { 
    PString str; 
    str.length = &length; 
    return str; 
} 

int main() 
{ 
    PString p = initializeString(); 

    p.chars = "Hello"; 

    printf("Length: %i\n", p.length(&p)); 

    return 0; 
} 

Çıktı: Eğer özel olarak bir işaretçi dönmek istediğini söylediğini rağmen

Length: 5 
İlgili konular