【发布时间】:2014-11-24 04:34:15
【问题描述】:
我编写了这个小函数来读取来自stdin 的所有数据。
我需要知道这个函数是否兼容 POSIX(我的意思是它可以在 Unix 和类 Unix 系统下工作)至少它可以在 Windows 上工作......
char* getLine()
{
int i = 0, c;
char* ptrBuff = NULL;
while ((c = getchar()) != '\n' && c != EOF)
{
if ((ptrBuff = (char*)realloc(ptrBuff, sizeof (char)+i)) != NULL)
ptrBuff[i++] = c;
else
{
free(ptrBuff);
return NULL;
}
}
if (ptrBuff != NULL)
ptrBuff[i] = '\0';
return ptrBuff;
}
该函数从标准输入读取所有数据,直到获得'\n' 或EOF,并返回一个指向包含所有字符的新位置的指针。我不知道这是否是最优化或更安全的方法,也不知道这是否适用于 Unix 和类 Unix 系统......所以,我需要一点帮助。我该如何改进该功能?或者有没有更好的方法从stdin 获取所有数据而不在缓冲区上留下垃圾?我知道fgets() 是一个选项,但是如果用户输入大于预期,它可能会留下垃圾......另外,我想获取用户编写的所有字符。
编辑:
新版getLine():
char* readLine()
{
int i = 0, c;
size_t p4kB = 4096;
void *nPtr = NULL;
char *ptrBuff = (char*)malloc(p4kB);
while ((c = getchar()) != '\n' && c != EOF)
{
if (i == p4kB)
{
p4kB += 4096;
if ((nPtr = realloc(ptrBuff, p4kB)) != NULL)
ptrBuff = (char*)nPtr;
else
{
free(ptrBuff);
return NULL;
}
}
ptrBuff[i++] = c;
}
if (ptrBuff != NULL)
{
ptrBuff[i] = '\0';
ptrBuff = realloc(ptrBuff, strlen(ptrBuff) + 1);
}
return ptrBuff;
}
最后编辑:
这是char* readLine() 函数的最终版本。现在我看不到更多的错误,也看不到改进它的最佳方法,如果有人知道更好的方法,请告诉我。
char* readLine()
{
int c;
size_t p4kB = 4096, i = 0;
void *newPtr = NULL;
char *ptrString = malloc(p4kB * sizeof (char));
while (ptrString != NULL && (c = getchar()) != '\n' && c != EOF)
{
if (i == p4kB * sizeof (char))
{
p4kB += 4096;
if ((newPtr = realloc(ptrString, p4kB * sizeof (char))) != NULL)
ptrString = (char*) newPtr;
else
{
free(ptrString);
return NULL;
}
}
ptrString[i++] = c;
}
if (ptrString != NULL)
{
ptrString[i] = '\0';
ptrString = realloc(ptrString, strlen(ptrString) + 1);
}
else return NULL;
return ptrString;
}
【问题讨论】:
-
查看这篇博文:powerfield-software.com/?p=65 - 它也被用作 SO 上几个问题的答案。
-
是的,你的函数是 POSIX,我在 Linux 中用 gcc 测试过,似乎可以正常工作。
-
像这样一次分配一个字节会导致二次性能——这是不好的。您应该一次分配数据块,每次需要更多空间时,分配的空间可能会加倍。您还应该注意,
ptrBuff = realloc(ptrBuff, new_size);在分配失败时会泄漏内存,因为您在指向先前内存分配的唯一指针上写入了 NULL。free(ptrBuff);是安全的,因为free(NULL)是无操作的。它不会释放内存,因为ptfBuff不再指向它。使用void *new_space = realloc(ptrBuff, new_size);并检查是否为空。 -
顺带一提,简单的 POSIX 兼容解决方案是使用
getline()。这也会根据需要分配内存。 -
@JonathanLeffler 抱歉,我的错误是:
if ((newSpace = realloc(ptrBuff, p4kb)) != NULL)但我在调试时正在测试,看看会发生什么......现在我怀疑我是否需要使用free()函数与否,因为当realloc()失败时,newSpace将包含一个空指针,而ptrBuff将包含最后一个具有有效数据的有效指针...
标签: c unix posix stdin getchar