我目前正在进行的实验使用的软件库具有复杂的源历史记录,并且没有明确定义的许可证。在合理化事物和在固定许可下发布将是一项相当大的工作。
它还打算运行一个随机的unixish平台,我们支持的只有一些libc具有GNU getline,但现在代码期望它。
是否有人知道在限制较少的许可下可以重新实现GNU getline
语义?
编辑:: 我问,因为谷歌没有帮助,我想尽可能避免写一个(这可能是一个有趣的练习,但它不是最好用的我的时间。)
更具体地说,有问题的界面是:
ssize_t getline (char **lineptr, size_t *n, FILE *stream);
答案 0 :(得分:16)
我很困惑。
我查看了链接,阅读说明,这是一个很好的实用程序。
但是,你是说你根本无法将此功能重写为规范?规范似乎很清楚,
下面:
/* 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是否为NULL,而不是NULL和n == 0.如果你愿意,可以修复它。 (另一个案例对我来说没有多大意义,我猜你可以在这种情况下返回-1。)
用变量替换'\ n'以实现“getdelim”。
人们是否还在编写代码?
答案 1 :(得分:6)
Will Hartung的代码遇到了一个非常严重的问题。 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
- Switched to getc on 5/23/19 */
#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 = getc(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 = getc(stream);
}
(*lineptr)[pos] = '\0';
return pos;
}
通过锁定流一次并使用等效的getc_unlocked(3)
,可以提高平台的性能 - 但这些在C中没有标准化;如果你正在使用POSIX版本,那么你可能已经getline(3)
了。
答案 2 :(得分:3)
如果您正在编译BSD使用fgetln 代替
答案 3 :(得分:3)
使用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()。
答案 4 :(得分:0)
尝试使用fgets()代替getline()。我在Linux中使用getline(),在迁移到Windows之前,它一直运行良好。 Visual Studio无法识别getline()。因此,我将字符指针替换为character,将EOF替换为NULL。见下文:
之前:
char *line = (char*) malloc(sizeof(char) * 1000);
size_t size = 1000 * sizeof(char);
FILE *fp = fopen(file, "r");
while(getline(&line, &size, fp) != EOF) {
...
}
free(line);
之后:
char line[1000];
size_t size = 1000 * sizeof(char);
while(fgets(&line, &size, fp) != NULL) {
...
}