代码之家  ›  专栏  ›  技术社区  ›  dmckee --- ex-moderator kitten

GNU GetLine接口是否有其他实现?

  •  9
  • dmckee --- ex-moderator kitten  · 技术社区  · 17 年前

    我目前正在进行的实验使用的是一个软件库,它具有复杂的源代码历史,并且没有定义明确的许可证。合理化事物并以固定的许可证发放是一项相当大的工作。

    它还打算运行一个随机的unixish平台,并且只有我们支持的libc中的一些具有gnu getline,但是现在代码期望它。

    是否有人知道 GNU getline 在限制较少的许可下可用的语义?

    编辑: 我问是因为谷歌没有帮助,如果可能的话,我想避免写一个(这可能是一个有趣的练习,但它不能是我最好的时间利用)。

    更具体地说,所讨论的接口是:

    ssize_t getline (char **lineptr, size_t *n, FILE *stream);
    
    5 回复  |  直到 17 年前
        1
  •  2
  •   dirkgently    17 年前

    看看谢天祥的网页 User Input . 如果你想知道确切的条款,可以给作者发电子邮件。

        2
  •  16
  •   Will Hartung    17 年前

    我很困惑。

    我查看了链接,阅读了描述,这是一个很好的实用程序。

    但是,您是说不能将这个函数重写为spec吗?规格似乎很清楚,

    在这里:

    /* 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分钟,我已经10年没写过C了。它稍微打破了getline协定,因为它只检查lineptr是否为空,而不是空,n==0。如果你愿意的话,你可以解决这个问题。(另一个案例对我来说没有什么意义,我想你可以退回-1个案例。)

    用变量替换'\n'以实现“getdelim”。

    人们还会写代码吗?

        3
  •  3
  •   Antti Haapala -- Слава Україні    7 年前

    WillHartung的代码有一个非常严重的问题。 realloc 很可能会释放旧块并分配新块,但是 p 代码中的指针将继续指向原始值。这一个试图通过使用数组索引来解决这个问题。它还试图更紧密地复制标准的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>
    #include <stdint.h>
    
    // if typedef doesn't exist (msvc, blah)
    typedef intptr_t ssize_t;
    
    ssize_t getline(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;
            }
    
            ((unsigned char *)(*lineptr))[pos ++] = c;
            if (c == '\n') {
                break;
            }
            c = fgetc(stream);
        }
    
        (*lineptr)[pos] = '\0';
        return pos;
    }
    
        4
  •  2
  •   Michael Andrews    14 年前

    如果您正在为BSD编译,请使用 fgetln 相反

        5
  •  2
  •   George Koehler    8 年前

    使用netbsd提供的这些可移植版本: getdelim() getline()

    这些来自pkgsrc中的libnbcompat,在每个文件的顶部都有一个bsd许可证。这两者都需要,因为getline()调用getdelim()。获取两个文件的最新版本。请参见每个文件顶部的BSD许可证。修改文件以适合您的程序:您可能需要在其中一个头文件中声明getline()和getdelim(),并修改这两个文件以包括头文件而不是nbcompat头文件。

    此版本的getdelim()可移植,因为它调用fgetc()。相反,来自libc(如bsd libc或musl libc)的getdelim()可能会使用该libc的私有特性,因此它不会跨平台工作。

    从那以后的几年里 POSIX 2008 specified getline() ,更多的Unixish平台添加了getline()函数。很少会缺少getline(),但它仍然可以在旧平台上发生。一些人尝试在旧平台(如PowerPC Mac OS X)上引导netbsd pkgsrc,因此他们希望libnbcompat提供缺少的posix函数,如getline()。

    推荐文章