2010-09-25 57 views
53

Sự khác biệt giữa atol() & strtol() là gì?atol() v/s. strtol()

Theo trang người đàn ông của họ, họ dường như có tác dụng tương tự cũng như phù hợp với lập luận:

long atol(const char *nptr); 

long int strtol(const char *nptr, char **endptr, int base); 

Trong trường hợp tổng quát, khi tôi không muốn sử dụng đối số base (tôi chỉ có số thập phân), tôi nên sử dụng chức năng nào?

Trả lời

77

strtol cung cấp cho bạn sự linh hoạt hơn, vì nó thực sự có thể cho bạn biết nếu toàn bộ chuỗi được chuyển thành số nguyên hay không. atol, khi không có khả năng chuyển đổi chuỗi thành một số (như trong atol("help")), trả về 0, đó là không thể phân biệt từ atol("0"):

int main() 
{ 
    int res_help = atol("help"); 
    int res_zero = atol("0"); 

    printf("Got from help: %d, from zero: %d\n", res_help, res_zero); 
    return 0; 
} 

Đầu ra:

Got from help: 0, from zero: 0 

strtol sẽ chỉ định, sử dụng endptr đối số của nó , nơi chuyển đổi không thành công.

int main() 
{ 
    char* end; 
    int res_help = strtol("help", &end, 10); 

    if (!*end) 
    printf("Converted successfully\n"); 
    else 
    printf("Conversion error, non-convertible part: %s", end); 

    return 0; 
} 

Đầu ra:

Conversion error, non-convertible part: help 

Vì vậy, đối với bất kỳ chương trình nghiêm túc, chắc chắn tôi khuyên bạn sử dụng strtol. Đó là một chút khó khăn hơn để sử dụng nhưng điều này có một lý do chính đáng, như tôi đã giải thích ở trên.

atol có thể chỉ phù hợp cho các trường hợp rất đơn giản và được kiểm soát.

+3

Tôi tin rằng trong ví dụ của bạn, điều kiện nên là 'if (! * End)'. Nó sẽ trỏ đến null-terminator của chuỗi (nếu nó đã được chuyển đổi tất cả) nhưng sẽ không được thiết lập để NULL chính nó. –

+0

@ Jeff M: bạn nói đúng, xin lỗi typo –

+0

Liệu logic này có áp dụng cho hàm kernel linux 'simple_strtol'? Tôi không thể nhận được điều kiện 'if (! * End)' để đánh giá đúng, sử dụng mô hình chính xác của bạn. –

4

Trong mã mới, tôi sẽ luôn sử dụng strtol. Nó có xử lý lỗi và đối số endptr cho phép bạn xem phần nào của chuỗi đã được sử dụng.

Các C99 tiêu chuẩn quốc gia về ato* chức năng:

Ngoại trừ các hành vi về lỗi, chúng tương đương với

atoi: (int)strtol(nptr,(char **)NULL, 10)
atol: strtol(nptr,(char **)NULL, 10)
atoll: strtoll(nptr, (char **)NULL, 10)

4

atol(str) tương đương với

strtol(str, (char **)NULL, 10); 

Sử dụng strtol nếu bạn muốn con trỏ cuối (để kiểm tra xem có nhiều ký tự để đọc hoặc nếu thực tế bạn đã đọc bất kỳ) hoặc cơ sở khác hơn 10. Nếu không, atol là tốt.

2

Nếu bộ nhớ phục vụ, strtol() có lợi ích bổ sung để đặt (tùy chọn) endptr để trỏ đến ký tự đầu tiên không thể chuyển đổi. Nếu NULL, nó sẽ bị bỏ qua. Bằng cách đó, nếu bạn đang xử lý một chuỗi chứa các số và ký tự, bạn có thể tiếp tục.

ví dụ:,

char buf[] = "213982 and the rest"; 
char *theRest; 
long int num = strtol(buf, &theRest, 10); 
printf("%ld\n", num); /* 213982 */ 
printf("%s\n", theRest); /* " and the rest" */ 
20

atol chức năng là một tập hợp con của strtol chức năng, ngoại trừ việc atol cung cấp cho bạn không có khả năng xử lý lỗi sử dụng được. Vấn đề nổi bật nhất với các hàm ato... là chúng dẫn đến hành vi không xác định trong trường hợp tràn. Lưu ý: đây không chỉ là thiếu phản hồi mang tính thông tin trong trường hợp lỗi, đây là hành vi không xác định, tức là một lỗi không thể khôi phục.

Điều này có nghĩa là chức năng atol (cũng như tất cả các chức năng khác ato..) là vô dụng đối với mọi mục đích thực tế nghiêm trọng. Đó là một sai lầm thiết kế và vị trí của nó là trên các junkyard của lịch sử C. Bạn nên sử dụng các hàm từ nhóm strto... để thực hiện các chuyển đổi. Họ đã được giới thiệu, trong số những thứ khác, để sửa chữa các vấn đề vốn có trong các chức năng của nhóm ato....

18

Theo trang atoi người đàn ông, nó đã không được chấp nhận bởi strtol.

IMPLEMENTATION NOTES 
The atoi() and atoi_l() functions have been deprecated by strtol() and strtol_l() 
and should not be used in new code. 
1

Các trang người đàn ông của strtol đưa ra sau đây:

ERRORS 
    EINVAL (not in C99) The given base contains an unsupported value. 
    ERANGE The resulting value was out of range. 
    The implementation may also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned). 

sẽ kiểm tra mã sau đây cho lỗi phạm vi. (Đã sửa đổi mã của Eli một chút)

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

int main() 
{ 
    errno = 0; 
    char* end = 0; 
    long res = strtol("83459299999999999K997", &end, 10); 

    if(errno != 0) 
    { 
     printf("Conversion error, %s\n", strerror(errno)); 
    } 
    else if (*end) 
    { 
     printf("Converted partially: %i, non-convertible part: %s\n", res, end); 
    } 
    else 
    { 
     printf("Converted successfully: %i\n", res); 
    } 

    return 0; 
} 
Các vấn đề liên quan