2009-04-09 37 views
8

Thử nghiệm tôi hiện đang làm việc sử dụng cơ sở phần mềm với lịch sử nguồn phức tạp và không có giấy phép được xác định rõ ràng. Nó sẽ là một số lượng đáng kể công việc để hợp lý hoá mọi thứ và phát hành theo một giấy phép cố định.Có triển khai thay thế giao diện GNU getline không?

Nó cũng được dự định để chạy một nền tảng ngẫu nhiên không đồng nhất, và chỉ một số libc của chúng tôi hỗ trợ có GNU getline, nhưng ngay bây giờ mã mong đợi nó.

Có ai biết về việc triển khai lại các ngữ nghĩa GNU getline có sẵn theo giấy phép ít hạn chế không?

Chỉnh sửa :: Tôi hỏi vì Google không trợ giúp và tôi muốn tránh viết bài nếu có thể (có thể là một bài tập thú vị nhưng không thể sử dụng tốt nhất thời gian của tôi.)

Để cụ thể hơn, giao diện trong câu hỏi là:

ssize_t getline (char **lineptr, size_t *n, FILE *stream); 
+0

Được nhắc bởi [câu hỏi này] (http://stackoverflow.com/q/17407585/827263), tôi đã sửa lại tuyên bố; 'getline' trả về' ssize_t', không phải 'size_t'. –

+2

Việc triển khai miền công cộng của getline(): http://stackoverflow.com/a/12169132/12711 –

Trả lời

2

Hãy xem trang Paul Hsieh trên User Input. Bạn có thể gửi email cho tác giả nếu bạn muốn biết các điều khoản chính xác.

+0

Nếu tôi phải viết điều gì đó chắc chắn sẽ là một giàn giáo tốt. Cảm ơn. – dmckee

+0

Bạn đã xem ví dụ: 'size_t fgetstralloc (char ** p, FILE * fp)' trên trang tôi đã liên kết đến chưa? – dirkgently

+0

:: thở dài :: Tất nhiên là không. Tôi chỉ nhìn vào trang một vài lần. Và tôi cũng là một người quan sát được đào tạo. – dmckee

-1

Trong trường hợp bạn đang nói về readline, hãy kiểm tra: editline

+1

Rất hay, nhưng tôi e rằng tôi thực sự có ý nghĩa. – dmckee

+0

Eh, xin lỗi, nó chỉ là tôi thường tìm thấy yêu cầu thay thế readline :) – mitchnull

+0

Nó xảy ra. Điều FGITW làm cho nó xảy ra rất nhiều, nhưng nó không gây hại ... – dmckee

15

Tôi bối rối.

Tôi đã xem liên kết, đọc mô tả và đây là một tiện ích tốt.

Nhưng, bạn có nói rằng bạn chỉ đơn giản là không thể viết lại hàm này để chỉ định? Spec có vẻ khá rõ ràng,

đây:

/* This code is public domain -- Will Hartung 4/9/09 */ 
#include <stdio.h> 
#include <stdlib.h> 

size_t getline(char **lineptr, size_t *n, FILE *stream) { 
    char *bufptr = NULL; 
    char *p = bufptr; 
    size_t size; 
    int c; 

    if (lineptr == NULL) { 
     return -1; 
    } 
    if (stream == NULL) { 
     return -1; 
    } 
    if (n == NULL) { 
     return -1; 
    } 
    bufptr = *lineptr; 
    size = *n; 

    c = fgetc(stream); 
    if (c == EOF) { 
     return -1; 
    } 
    if (bufptr == NULL) { 
     bufptr = malloc(128); 
     if (bufptr == NULL) { 
      return -1; 
     } 
     size = 128; 
    } 
    p = bufptr; 
    while(c != EOF) { 
     if ((p - bufptr) > (size - 1)) { 
      size = size + 128; 
      bufptr = realloc(bufptr, size); 
      if (bufptr == NULL) { 
       return -1; 
      } 
     } 
     *p++ = c; 
     if (c == '\n') { 
      break; 
     } 
     c = fgetc(stream); 
    } 

    *p++ = '\0'; 
    *lineptr = bufptr; 
    *n = size; 

    return p - bufptr - 1; 
} 

int main(int argc, char** args) { 
    char *buf = NULL; /*malloc(10);*/ 
    int bufSize = 0; /*10;*/ 

    printf("%d\n", bufSize); 
    int charsRead = getline(&buf, &bufSize, stdin); 

    printf("'%s'", buf); 
    printf("%d\n", bufSize); 
    return 0; 
} 

15 phút, và tôi đã không viết C trong vòng 10 năm. Nó nhỏ phá vỡ hợp đồng getline ở chỗ nó chỉ kiểm tra nếu lineptr là NULL, thay vì NULL và n == 0. Bạn có thể sửa chữa nếu bạn muốn. (Trường hợp khác không có nhiều ý nghĩa với tôi, tôi đoán bạn có thể trả về -1 trong trường hợp đó.)

Thay thế '\ n' bằng biến để triển khai "getdelim".

Mọi người vẫn còn viết mã nữa không?

+6

Điều này làm việc tốt cho các chuỗi ngắn nhưng có thể thất bại sau khi tái phân bổ. bufptr có thể nhận được một địa chỉ mới và p cần được giữ ở cùng một độ tương đối bù đắp. Trong các thử nghiệm của tôi (với MinGW), realloc có thể trở lại nhiều lần với cùng một con trỏ (nếu có đủ bộ nhớ tại chỗ đó) hoặc có thể trả về một địa chỉ mới trên sự phân bổ lại đầu tiên. Địa chỉ mới có thể ở gần bộ nhớ hoặc cách xa, và cũng có thể ở trước địa chỉ đầu tiên cũng như sau. IE nó có thể làm cho p một số ngẫu nhiên. Để khắc phục, hãy đặt "offset = p - bufptr;" dưới dòng EOF và "p = bufptr + offset;" sau khối NULL. – Todd

+0

'((p - bufptr)> (size - 1))' là một vấn đề nếu 'size == 0' (và' * lineptr' là uncharacteristically không NULL) như 'size - 1' là một số _large_. Đề xuất kích thước '((p - bufptr + 1)>'. – chux

+0

lợi nhuận malloc và realloc trên con trỏ stdio.h mã void * của tôi. Vì vậy, tôi đã phải thêm các toán tử cast, cũng (char *) cho hai hàng. – jamk

2

Nếu bạn đang biên soạn để sử dụng BSD fgetln thay

1

Sử dụng các phiên bản di động từ NetBSD: getdelim()getline()

Những đến từ libnbcompat trong pkgsrc, và có một giấy phép BSD tại đầu mỗi tệp. Bạn cần cả hai vì getline() getline(). Tìm nạp phiên bản mới nhất của cả hai tệp. Xem giấy phép BSD ở đầu mỗi tệp. Sửa đổi các tệp để phù hợp với chương trình của bạn: bạn có thể cần khai báo getline() và getdelim() trong một trong các tệp tiêu đề của bạn và sửa đổi cả hai tệp để bao gồm tiêu đề của bạn thay vì tiêu đề nbcompat.

Phiên bản getdelim() này có thể di chuyển được vì nó gọi fgetc(). Ngược lại, một getdelim() từ một libc (như libc BSD hoặc libl musl) có lẽ sẽ sử dụng các tính năng riêng của libc đó, do đó nó sẽ không hoạt động trên các nền tảng.

Trong những năm kể từ POSIX 2008 specified getline(), nhiều nền tảng Unix đã thêm hàm getline(). Rất hiếm khi getline() bị thiếu, nhưng nó vẫn có thể xảy ra trên các nền tảng cũ. Một vài người cố gắng khởi động NetBSD pkgsrc trên các nền tảng cũ (như PowerPC Mac OS X), vì vậy họ muốn libnbcompat cung cấp các hàm POSIX bị thiếu như getline().

1

Mã của Will Hartung bị một vấn đề rất nghiêm trọng. realloc rất có thể sẽ miễn phí khối cũ và phân bổ một khối mới, nhưng con trỏ p trong mã sẽ tiếp tục trỏ đến bản gốc. Điều này cố gắng khắc phục điều đó bằng cách sử dụng lập chỉ mục mảng thay thế. Nó cũng cố gắng sao chép chặt chẽ hơn logic chuẩn POSIX.

/* The original code is public domain -- Will Hartung 4/9/09 */ 
/* Modifications, public domain as well, by Antti Haapala, 11/10/17 */ 

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

// if typedef doesn't exist (msvc, blah) 
typedef intptr_t ssize_t; 

ssize_t geetline(char **lineptr, size_t *n, FILE *stream) { 
    size_t pos; 
    int c; 

    if (lineptr == NULL || stream == NULL || n == NULL) { 
     errno = EINVAL; 
     return -1; 
    } 

    c = fgetc(stream); 
    if (c == EOF) { 
     return -1; 
    } 

    if (*lineptr == NULL) { 
     *lineptr = malloc(128); 
     if (*lineptr == NULL) { 
      return -1; 
     } 
     *n = 128; 
    } 

    pos = 0; 
    while(c != EOF) { 
     if (pos + 1 >= *n) { 
      size_t new_size = *n + (*n >> 2); 
      if (new_size < 128) { 
       new_size = 128; 
      } 
      char *new_ptr = realloc(*lineptr, new_size); 
      if (new_ptr == NULL) { 
       return -1; 
      } 
      *n = new_size; 
      *lineptr = new_ptr; 
     } 

     (*lineptr)[pos ++] = c; 
     if (c == '\n') { 
      break; 
     } 
     c = fgetc(stream); 
    } 

    (*lineptr)[pos] = '\0'; 
    return pos - 1; 
} 
Các vấn đề liên quan