基本上,我有一个全局定义的结构,该结构将保存某些事物的最佳评分元素:
int structlength = 0;
typedef char topscorer_t[MAX_INPUT + 1];
typedef struct {
topscorer_t name;
double score;
int ID;
} top_scores;
top_scores scores[HIGHEST_SCORES + 1];
不幸的是,我的程序可以运行,但是如果我这样递给我,它将不会获得满分,因为每次函数向
scores
添加新结构时,我也会执行structlength += 1
来跟踪其中现在有多少个元素,以及是全局变量;我的讲师绝对讨厌的东西。还有另一种方法可以跟踪将多少个结构添加到数组
structlength
的方法吗?另外,以这种方式定义的结构是否也像全局变量一样对待?我对此很陌生:/
最佳答案
将内容封装在另一个struct
中。注意我更喜欢calloc
而不是malloc
。
struct ScoreEntry {
wchar_t* name;
double score;
int id;
};
struct List {
struct ScoreEntry buffer[]; // Note this an array-of-struct rather than array-of-ptr-to-struct
size_t bufferLength;
size_t bufferIndex;
};
List* List_create(size_t initialLength) {
struct List* ret = calloc( 1, sizeof(struct List) );
if( ret == NULL ) exit(1);
ret->buffer = calloc( initialLength, sizeof(struct ScoreEntry) );
if( ret->buffer == NULL ) exit(1);
ret->bufferLength = initialLength;
return ret;
}
void List_delete(struct List* list) {
for(size_t i = 0; i < list->bufferIndex; i++ ) {
free( list->buffer[i].name );
}
free( list->buffer );
free( list );
}
void List_add(struct List* list, struct ScoreEntry entry) {
if( list->bufferIndex >= list->bufferLength ) {
// Reallocate buffer using `calloc`
if( true ) {
size_t newLength = 2 * list->bufferLength;
struct ScoreEntry* newBuffer = calloc( newLength , sizeof(struct ScoreEntry) );
if( newBuffer == NULL ) exit(1);
memcpy( newBuffer, list->buffer, list->bufferIndex );
free( list->buffer );
} else {
// Or reallocate with `realloc`
list->buffer = realloc( list->buffer, newLength );
if( list->buffer == NULL ) exit(1);
}
list->bufferLength = newLength;
}
list->buffer[ list->bufferIndex++ ] = entry; // note this is a copy operation
}
因此,在您的程序中:
int main(int argc, char* argv[]) {
struct List* scoresList = List_create( 10 );
List_add( scoresList, { .name = L"Person 1", .score = 123, .id = 1 } ); // C99 struct initialization syntax
List_add( scoresList, { .name = L"Person 2", .score = 456, .id = 2 } );
List_add( scoresList, { .name = L"Person 3", .score = 789, .id = 3 } );
List_delete( scoresList );
}
请注意,我的示例将失败,因为字符串是在编译时分配的,因此无法释放。解决方案是显式跟踪每个
name
是运行时字符串还是编译时字符串,然后相应地调用free( name )
。