我需要一个内存保存的读取行版本。我有这个"工作"解。但我不确定它在记忆方面的表现如何。当我启用free(text)
时,它适用于几行,然后我收到错误。所以现在虽然我是malloc文本,但是文本和结果都没有被释放。那是对的吗 ?为什么会这样呢?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* readFromIn()
{
char* text = malloc(1024);
char* result = fgets(text, 1024, stdin);
if (result[strlen(result) - 1] == 10)
result[strlen(result) - 1] = 0;
//free(text);
return result;
}
我有很多的短线要阅读,我还需要stdin可以用FILE*
句柄替换。我没有必要重新分配文本,因为我只有短线。
答案 0 :(得分:2)
fgets
返回指向字符串的指针,因此在fgets
行之后,result
将与text
的内存地址相同。然后,当您致电free (text);
时,您将返回无效内存。
完成result
你也可以通过构造你的代码来传递一个像这样的缓冲区来避免malloc / free东西:
void parent_function ()
{
char *buffer[1024];
while (readFromIn(buffer)) {
// Process the contents of buffer
}
}
char *readFromIn(char *buffer)
{
char *result = fgets(buffer, 1024, stdin);
int len;
// fgets returns NULL on error of end of input,
// in which case buffer contents will be undefined
if (result == NULL) {
return NULL;
}
len = strlen (buffer);
if (len == 0) {
return NULL;
}
if (buffer[len - 1] == '\n') {
buffer[len - 1] = 0;
return buffer;
}
如果你正在处理许多小的,短命的项目,那么试图避免malloc / free可能是明智的,这样内存就不会碎片化,而且它也应该更快。
答案 1 :(得分:1)
char *fgets(char *s, int size, FILE *stream)
从流中读取最多一个小于大小的字符,并将它们存储到s
指向的缓冲区中。读数在EOF或换行符后停止。如果读取换行符,则将其存储到缓冲区中。终止空字节('\0'
)存储在缓冲区中的最后一个字符之后。
返回值:成功时返回s
,错误时返回NULL
,或者在没有读取任何字符时发生文件结束。
因此,您的代码存在两个严重问题:
fgets
您的功能可能如下所示:
public char* readFromIn() {
char* text = malloc(1024);
if (fgets(text, 1024, stdin) != NULL) {
int textLen = strlen(text);
if (textLen > 0 && text[textLen - 1] == '\n')
text[textLen - 1] == '\0'; // getting rid of newline character
return text;
}
else {
free(text);
return NULL;
}
}
然后该函数的调用者应该负责释放该函数返回值指向的内存。
答案 2 :(得分:1)
我知道你提到线路只是短路,但是所提供的解决方案都不适用于长度大于1024的线路。正是出于这个原因,我提供了一种解决方案,它将尝试读取整行,并在没有足够空间时调整缓冲区大小。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINIMUM_CAPACITY 16
size_t read_line(char **buffer, size_t *capacity) {
char *buf = *buffer;
size_t cap = *capacity, pos = 0;
if (cap < MINIMUM_CAPACITY) { cap = MINIMUM_CAPACITY; }
for (;;) {
buf = realloc(buf, cap);
if (buf == NULL) { return pos; }
*buffer = buf;
*capacity = cap;
if (fgets(buf + pos, cap - pos, stdin) == NULL) {
break;
}
pos += strcspn(buf + pos, "\n");
if (buf[pos] == '\n') {
break;
}
cap *= 2;
}
return pos;
}
int main(void) {
char *line = NULL;
size_t size = 0;
for (size_t end = read_line(&line, &size); line[end] == '\n'; end = read_line(&line, &size)) {
line[end] = '\0'; // trim '\n' off the end
// process contents of buffer here
}
free(line);
return 0;
}
理想的解决方案应该能够使用1字节的固定缓冲区运行。然而,这需要更全面地理解该问题。一旦实现,适应这样的解决方案将实现最佳解决方案。
答案 3 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readFromIn(FILE *fp)
{
char text[1024];
size_t len;
if (!fgets(text, sizeof text, fp)) return NULL;
len = strlen(text);
while (len && text[len-1] == '\n') text[--len] = 0;
return strdup(text);
}
答案 4 :(得分:0)
为什么没有人建议将缓冲区从堆移到堆栈?这是我现在的解决方案:
char input[1024]; // held ready as buffer for fgets
char* readFromIn()
{
char* result = fgets(input, 1024, stdin);
if (result == null)
return "";
if (result[strlen(result) - 1] == '\n')
result[strlen(result) - 1] = 0;
return result;
}