C 从缓冲区获取字符串

C 从缓冲区获取字符串,c,C,我希望从内存中的原始字节缓冲区中获取字符串,是否可以正常工作 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 N

我希望从内存中的原始字节缓冲区中获取字符串,是否可以正常工作

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;
}

所有对
buf[i]
的引用都应该是
l\u buf[i]
。buf[i]是从一个空指针(不是您想要的)进行索引,但l_buf[i]是从一个字符指针进行索引。

我认为,建议的解决方案至少存在一个问题,即没有检查以确保您不会在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`;
然后在字符串提取函数中,将空检查添加到行终止测试中,如下所示:

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()中的指针,如下所示:


除非您正在为标准C库函数编写代码(您不是),否则不要使用以
\uu
开头的变量名,因为这些变量名是根据C标准保留的。@SiegeX:通常情况下,函数中的变量名是可以的,\n不会。(如果您很挑剔,请准确地说)strncpy的第二个参数应该是
(buf+i)
&buf[i]
,但其他参数看起来至少可以工作。我会避免使用“string”作为变量名,这样它就不会混淆那些用来读取C++“STL”代码的人,其中“string”是一种类型。非常感谢!我负责Win、Unix、Mac—您写道:建议的代码不处理同时包含“\r”和“\n”的行终止。为什么?这些符号在内存中一个字符接一个字符,因此我们只能检查它们中的第一个,不是吗?我强调的是,在有双字符行终止的情况下(例如在Windows上),如果只检测到其中的第一个(如上面的代码中所示)然后返回的字符串的第一个字符将包含第二个终止字符。因此,您需要检查是否有第二个终止字符,然后在执行strncpy()之前“跳过”它。第一个
for()
检查缓冲区开头是否有行尾字符
*in = j;