2011-11-29 35 views
5

Thực sự là một bài đăng cho một số lời khuyên về việc sử dụng realloc, cụ thể hơn, nếu tôi có thể sử dụng nó để đơn giản hóa mã hiện có của tôi. Về cơ bản, những gì dưới đây làm, nó tự động cấp phát một số bộ nhớ, nếu tôi đi qua 256, sau đó mảng cần phải được tăng kích thước, vì vậy tôi malloc một mảng temp, với 2x kích thước, memcpy vv (xem bên dưới).Sử dụng Realloc trong C

Tôi đã tự hỏi liệu realloc có thể được sử dụng trong mã dưới đây hay không, để đơn giản hóa nó, lời khuyên, mã mẫu hoặc thậm chí gợi ý về cách triển khai nó được đánh giá cao!

Chúc mừng.

void reverse(char *s) { 
char p; 

switch(toupper(s[0])) 
{ 
    case 'A': case 'E': case 'I': case 'O': case 'U': 
     p = s[strlen(s)-1]; 
     while(p >= s) 
      putchar(p--); 
     putchar('\n'); 
     break; 
    default: 
     printf("%s", s); 
     break; 
} 
printf("\n"); 
    } 

    int main(void) { 
char c; 
int buffer_size = 256; 
char *buffer, *temp; 
int i=0; 

buffer = (char*)malloc(buffer_size); 
while (c=getchar(), c!=' ' && c!='\n' && c !='\t') 
{ 
    buffer[i++] = c; 
    if (i >= buffer_size) 
    { 
     temp = (char*)malloc(buffer_size*2); 
     memcpy(temp, buffer, buffer_size); 
     free(buffer); 
     buffer_size *= 2; 
     buffer = temp; 
    } 
} 
buffer[i] = '\0'; 
reverse(buffer); 

return 0; 

}

+1

Lưu ý về kiểu: Bạn nên ** không ** để truyền giá trị trả lại của 'malloc'. –

+1

Và 'reverse' sẽ lấy đối số là' const char * '. –

Trả lời

11

là câu trả lời ngắn. Dưới đây là cách hiển thị:

if (i >= buffer_size) 
{ 
    temp = realloc(buffer, buffer_size*2); 
    if (!temp) 
     reportError(); 
    buffer_size *= 2; 
    buffer = temp; 
} 

Lưu ý rằng bạn vẫn cần sử dụng con trỏ tạm thời để giữ kết quả realloc(); nếu phân bổ không thành công, bạn vẫn có con trỏ buffer gốc tới bộ đệm hiện có vẫn còn hợp lệ.

1

realloc là khá nhiều chính xác những gì bạn đang tìm kiếm - bạn có thể thay thế mà toàn bộ khối bên trong if (i >= buffer_size) với một cái gì đó như:

buffer = (char*)realloc(buffer, buffer_size*2); 
buffer_size *= 2; 

Chú ý rằng đây bỏ qua lỗi điều kiện (nếu lợi nhuận từ reallocNULL); bắt tình trạng này là để lại cho người đọc.

1

Có, realloc có thể được sử dụng để đơn giản hóa mã của bạn. Nếu bạn không quan tâm đến lỗi xử lý, thì đây:

char *tmp = malloc(size*2); 
memcpy(temp, buffer, size); 
free(buffer); 
buffer = tmp; 

là về cơ bản tương đương như sau:

buffer = realloc(buffer, size*2); 

Nếu bạn quan tâm đến lỗi xử lý (và có lẽ bạn nên có), sau đó bạn sẽ cần phải kiểm tra các giá trị trả về NULL. Điều này cũng đúng với mã ban đầu của bạn.

+1

-1. nếu realloc thất bại (bằng cách trả về NULL), bạn đã mất tham chiếu đến khối ban đầu. –

+1

@Graham: Tôi đã nói rõ ràng "nếu bạn không quan tâm đến việc xử lý lỗi". OP cũng không có bất kỳ lỗi xử lý nào trong mã gốc của mình. –

+1

Điều này "xử lý lỗi" không chỉ là chơi của một số đứa trẻ như kiểm tra 'std :: cin >> n'; điều này ở đây có thể và sẽ gây ra UB gần như chắc chắn ... –

1

Vâng, để đơn giản hóa mã của bạn, bạn có thể thay

if (i >= buffer_size) 
{ 
    temp = (char*)malloc(buffer_size*2); 
    memcpy(temp, buffer, buffer_size); 
    free(buffer); 
    buffer_size *= 2; 
    buffer = temp; 
} 

với

if (i >= buffer_size) 
    buffer = realloc(buffer, buffer_size *= 2); 

này không đưa vào kiểm tra lỗi tài khoản, vì vậy bạn sẽ cần phải kiểm tra để đảm bảo realloc doesn' t trả lại NULL.

+1

'realloc' có thể trả về' NULL', cho bạn một sự rò rỉ ngay lập tức không thể khôi phục. –

+2

-1.nếu realloc thất bại (bằng cách trả về NULL), bạn đã mất tham chiếu đến khối ban đầu. –

+2

@GrahamBorland Tôi đã nói bạn có thể thay thế mã gốc của mình bằng mã đó. Anh ta không kiểm tra 'NULL' ở đó, do đó tôi cũng vậy. Nhưng tôi đã thêm một ghi chú để đề cập đến nó. –