cuốn sách gpt4 ai đã làm

c – Quy ước con trỏ và: Mảng con trỏ tới phần tử nhất định

In lại Tác giả: Vũ trụ không gian Thời gian cập nhật: 2023-11-04 03:01:04 28 4
mua khóa gpt4 Nike

Câu hỏi này là về các phương pháp hay nhất để giải quyết vấn đề con trỏ mà tôi đang tự nghiên cứu.

Tôi có một mảng cấu trúc được tạo động trong hàm đọc csv.

int init_from_csv(instance **instances,char *path) {
... mở tập tin, lấy số dòng
*instances = (instance*) malloc( (size_t) sizeof(instance) * line_count );
... phân tích và đặt giá trị của tất cả các phiên bản
trả về số lượng_of_valid_instances_read;
}
// trong chính()
ví dụ * trường hợp;
int ins_len = init_from_csv(&instances, "some/path/file.csv");

Bây giờ tôi phải thực thi một hàm trên dữ liệu thô này, phân tách nó và sau đó thực hiện lại nó trên phần táchnhư nhau chức năng. Tập dữ liệu này có lẽ khá lớn nên tôi không muốn sao chép các thể hiện, tôi chỉ muốn một mảng con trỏ tới các cấu trúc trong phần tách.

dụ **split = (dụ**) malloc (sizeof(instance*) * Split_len_max);
int Split_function(instance *instances, ins_len, instance **split){
int tôi, c;
c = 0;
for (i = 0; i < ins_len; i++) {
nếu (some_criteria_is_true) {
Split[c++] = &instances[i];
}
trả lại c;
}

Bây giờ câu hỏi của tôi là, cách thực hành tốt nhất hoặc cách dễ đọc nhất để thực hiện các hàm trên một mảng cấu trúc và một mảng con trỏ là gì? Đưa ra một ví dụ đơn giảnđếm_data().

int count_data (instance **ins, ins_len, float crit) {
int i,c;
c = 0;
for (i = 0; i < ins_len; i++) {
if ins[i]->data > crit) {
++c;
}
}
trả lại c;
}

// mã mùi-o-vision sắp tắt
int c1 = count_data (split, ins_len, 0,05);
int c2 = count_data (&instances, ins_len, 0.05);

Tôi có thể yêu cầu init_from_csv malloc một mảng con trỏ tới các phiên bản và sau đó malloc mảng phiên bản của tôi. Trước khi bắt đầu thay đổi một loạt mã, tôi muốn hiểu cách một lập trình viên C có kinh nghiệm sẽ xử lý loại việc này.

câu trả lời hay nhất

Điều này có vẻ hơi khập khiễng, nhưng nếu bạn thực sự muốn chuyển con trỏ instance** đó và muốn nó hoạt động cho cả tập dữ liệu chính và phần tách, bạn thực sự cần phải tạo một mảng con trỏ cho tập dữ liệu chính. Đây là một cách bạn có thể làm điều đó...

size_t tôi, mem_reqd;
ví dụ **list_seg, *data_seg;

/* Phân bổ danh sách và phân đoạn dữ liệu trong một khối lớn */
mem_reqd = (sizeof(instance*) + sizeof(instance)) * line_count;
list_seg = (dụ**) malloc( mem_reqd );
data_seg = (ví dụ*) &list_seg[line_count];

/* Lập chỉ mục vào phân đoạn dữ liệu */
for( i = 0; i < line_count; i++ ) {
list_seg[i] = &data_seg[i];
}

*phiên bản = list_seg;

Bây giờ bạn luôn có thể ví dụ* Hoạt động trên mảng con trỏ, cho dù đó là danh sách chính hay danh sách chia. Tôi biết bạn không muốn sử dụng thêm bộ nhớ, nhưng nếu ví dụ Cấu trúc không nhỏ lắm, do đó, nên phân bổ thêm một con trỏ cho mỗi phiên bản để tránh trùng lặp mã gây nhầm lẫn.

Sau khi hoàn thành danh sách phiên bản chính, bạn có thể thực hiện việc này:

void free_instances( instance** instance )
{
miễn phí(trường hợp);
}

Tôi muốn thực hiện điều này như một cấu trúc:

cấu trúc instance_list {
ví dụ ** dữ liệu;
chiều dài size_t;
chủ sở hữu int;
};

Bằng cách này, bạn có thể quay lại từ chức năng của mình theo cách tốt hơn:

instance_list* alloc_list(size_t length, int owner)
{
size_t tôi, mem_reqd;
instance_list *list;
ví dụ *data_seg;

/* Phân bổ danh sách và phân đoạn dữ liệu trong một khối lớn */
mem_reqd = sizeof(instance_list) + sizeof(instance*) * chiều dài;
if( owner ) mem_reqd += sizeof(instance) * length;
list = (instance_list*) malloc( mem_reqd );
danh sách->dữ liệu = (dụ**) &list[1];
danh sách-> chiều dài = chiều dài;
danh sách-> chủ sở hữu = chủ sở hữu;

/* Lập chỉ mục danh sách */
nếu( chủ sở hữu ) {
data_seg = (instance*) &list->data[line_count];
for( i = 0; i < line_count; i++ ) {
danh sách->dữ liệu[i] = &data_seg[i];
}
}

danh sách trả lại;
}

void free_list( instance_list * list )
{
miễn phí(danh sách);
}

void eras_list( instance_list * list )
{
if(list->owner) return;
memset((void*)list->data, 0, sizeof(instance*) * list->length);
}

Giờ đây, chức năng được tải từ CSV không phải lo lắng về các chi tiết tạo ra con quái vật này, vì vậy nó có thể chỉ cần làm những gì nó phải làm. Bây giờ bạn có thể bắt đầu từkhácHàm trả về danh sách, cho dù chúng chứa dữ liệu hay chỉ trỏ đến các danh sách khác.

instance_list* Load_from_csv( char *path )
{
/* lấy số dòng... */
instance_list *list = alloc_list(line_count, 1);
/* phân tích cú pháp csv ... */
danh sách trả lại;
}

Đợi đã... được rồi, bạn hiểu rồi. Không có gì đảm bảo rằng mã này sẽ biên dịch hoặc hoạt động, nhưng nó sẽ bị tắt. Tôi nghĩ điều này rất quan trọng, bất cứ khi nào bạn làm điều gì đó với một mảng phức tạp hơn một chút so với một mảng đơn giản, sẽ rất hữu ích nếu bạn nỗ lực thêm một chút để gói gọn nó. Đây là cấu trúc dữ liệu chính mà bạn sẽ sử dụng để phân tích hoặc bất kỳ mục đích nào khác, do đó, sẽ hợp lý hơn khi cung cấp cho nó một chút trạng thái vì nó có kiểu dữ liệu riêng.

Tôi không biết, như thế có quá đáng không? =)

Về c - quy ước con trỏ và: Mảng con trỏ tới các phần tử nhất định, chúng tôi tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/11770645/

28 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress