我希望从内存中的原始字节缓冲区中获取字符串,会运行良好吗?
static int in = 0;
void *loadFile (FILE *fp)
{
fseek (fp, 0L, SEEK_END);
size_t size = ftell (fp);
fseek (fp, 0L, SEEK_SET);
char *buf = malloc (sizeof(char) * size);
if (!buf)
return NULL;
if (fread (buf, sizeof(char), size, fp) != size) {
free (buf);
return NULL;
}
return buf;
}
char *getString (void *buf)
{
char *l_buf = buf;
int i, j, num;
char *string = NULL;
for (i = in; l_buf[i] == '\n' || l_buf[i] == '\r'; i++);
for (j = i; l_buf[j] != '\n' && l_buf[j] != '\r'; j++);
num = j - i;
string = malloc (sizeof(char) * (num + 1));
if (!string)
return NULL;
in = j;
strncpy (string, &l_buf[i], num);
string[num] = '\0';
return string;
}
答案 0 :(得分:1)
对buf[i]
的所有引用都应为l_buf[i]
。 buf [i]是从void指针索引(不是你想要的),但是l_buf [i]是从char指针索引的。
答案 1 :(得分:1)
我认为解决方案至少存在一个问题,即没有检查以确保您不会在getString()中运行内存缓冲区的末尾。因此,在读取代码中避免这种情况的一种方法是在缓冲区的末尾添加一个显式NULL,如此
char *buf = malloc (sizeof(char) * (size + 1));
if (!buf)
return NULL;
if (fread (buf, sizeof(char), size, fp) != size) {
free (buf);
return NULL;
}
buf[size] = `\0`;
然后在你的字符串提取函数中添加一个NULL检查到行终止测试,如下所示:
for (i = in; l_buf[i] != '\0' && (l_buf[i] == '\n' || l_buf[i] == '\r'); i++);
if (l_buf[i] == '\0') {
/* Never saw the start of a line before the buffer ran out */
return NULL;
}
for (j = i; l_buf[i] != '\0' && l_buf[j] != '\n' && l_buf[j] != '\r'; j++);
if (i == j) {
return NULL;
}
还有另一个潜在的问题但是你没有说你是在UNIX或Windows上运行还是在这里关心可移植性我无法确定。建议的代码不处理包含'\ r'和'\ n'的行终止。
我还建议通过用这样的参数替换全局起始位置索引来使函数重入:
char *getString (void *buf, int *in) { ...
然后只需更新getString()中的指针:
*in = j;