2009-08-29 27 views
31

Tengo una estructura de la siguiente manera, con un puntero a una función llamada "longitud" que devolverá la longitud del miembro de caracteres.Puntero de función como miembro de una estructura C

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

Tengo una función para devolver el número de caracteres de un puntero a una PString:

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

Tengo un initializeString función() que devuelve un puntero a una PString:

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

Está claro que estoy haciendo algo muy mal con mis punteros aquí, porque la línea str->length = &length causa una señal EXC_BAD_ACCESS en mi depurador, al igual que `return strlen (self-> char s). ¿Alguien tiene alguna idea sobre este problema?

Específicamente, quiero poder hacer que la función initializeString() devuelva un puntero a una PString, y la función de longitud para usar un puntero a una PString como entrada. Esto es solo un experimento en la implementación de un sistema rudimentario orientado a objetos en C, pero no tengo mucha experiencia lidiando con punteros de frente. Gracias por cualquier ayuda que me puedan dar.

+2

Aunque usted dice que quiere específicamente para devolver un puntero. En este caso, devolver una estructura en sí es mucho mejor. Es una copia barata de estructura, y no hay necesidad de una asignación de montón de gran peso. Los objetos de cadena están basados ​​en valores: no tienen identidad (dirección), pero su igualdad se basa en su contenido. También podría tener este sentido de distinción en su sistema OOP de alguna manera. –

Respuesta

48

Asigna memoria para mantener los caracteres.

#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

¡Gran respuesta! Pregunta: Necesito llamar gratis (p), pero ¿también necesito liberar los caracteres? –

+0

Supongo que necesito escribir un destructor. –

+12

No es necesario convertir el valor de retorno de 'malloc' en C. Además, debe inicializar' str-> chars' después de asignarlo (es decir, 'str-> chars [0] = '\ 0';') . – caf

4

El puntero str nunca se asigna. Debe ser malloc 'd antes de su uso.

+0

Reemplace 'PString * str;' con 'PString * str = (PString *) malloc (sizeof (PString));' E idealmente, llame a 'free' con el puntero cuando termine de usarlo para evitar pérdidas de memoria. – jgottula

6

Supongo que parte de su problema es que las listas de parámetros no coinciden.

int (* length)(); 

y

int length(PString * self) 

no son lo mismo. Debe ser int (* length)(PString *);.

... woah, es Jon!

Editar: y, como se menciona a continuación, su puntero de estructura nunca se establece para apuntar a nada. La forma en que lo hagas solo funcionaría si estuvieras declarando una estructura simple, no un puntero.

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

Muchas gracias, Jacob. Voy a seguir adelante y probar eso. –

+0

OK, 'strlen (self-> chars)' todavía me da 'EXC_BAD_ACCESS'. –

4

Tal vez me estoy perdiendo algo aquí, pero ¿asigna memoria para que PString antes de que accedió a ella?

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

También puede usar "void *" (puntero de vacío) para enviar una dirección a la función.

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; 
} 

Salida:

Length: 5 
Cuestiones relacionadas