C fgets未读取整行

C fgets未读取整行,c,fgets,C,Fgets,我有一个简单的函数,它应该从标准输入中读取行并将其放入一个字符数组中,我在循环中调用这个函数,直到输入EOF。问题是,对于非常长的行(超过10k个字符),fgets只读取一些字符并停止,尽管它没有遇到任何字符\n并且缓冲区有足够的空间,因此下次调用此函数将读取行的其余部分。这种行为是否有原因(错误编写的代码,我不知道的一些缓冲区)?有可能把它修好吗?如果我在代码中有错误,如果你指出,我将不胜感激 static int getLine(char** line){ if(feof(stdin

我有一个简单的函数,它应该从标准输入中读取行并将其放入一个字符数组中,我在循环中调用这个函数,直到输入EOF。问题是,对于非常长的行(超过10k个字符),fgets只读取一些字符并停止,尽管它没有遇到任何字符\n并且缓冲区有足够的空间,因此下次调用此函数将读取行的其余部分。这种行为是否有原因(错误编写的代码,我不知道的一些缓冲区)?有可能把它修好吗?如果我在代码中有错误,如果你指出,我将不胜感激

static int getLine(char** line){
    if(feof(stdin)) return 0;
    int len=0;
    char* pointer=NULL;
    int max = 1;
    while(1){
        max+=400;
        *line=(char*)realloc( *line,max);
        if(pointer==NULL)
            pointer=*line;
        if(fgets(pointer, 401, stdin)==NULL)break;
        int len1=strlen(pointer);
        len+=len1;
        if(len1!=400 || pointer[len1]=='\n')break;
        pointer+=len1;
    }
    if(len==0)return 0;
    if((*line)[len-1]=='\n'){
    *line=(char*)realloc(*line, len); 
    (*line)[len-1]='\0';
    return len-1;}//without \n
    return len;
}

我认为您的问题可能是您使用指针的方式:

char* pointer=NULL;
int max = 1;
while(1){
    max+=400;
    *line=(char*)realloc( *line,max);
    if(pointer==NULL)
        pointer=*line;
    if(fgets(pointer, 401, stdin)==NULL)
        break;
    int len1=strlen(pointer);
    len+=len1;
    if(len1!=400 || pointer[len1]=='\n')
        break;
    pointer+=len1;
}
问题在于
realloc()
可以更改数据的存储位置,但您可以将其修复到第一次给定的位置。如果您处理大量数据,则更有可能在重新分配时移动数据。您可以通过跟踪
*行的值来诊断此问题(在每次迭代的
realloc()
之后打印)

解决方法相当简单:使用偏移量而不是指针作为权威长度,并在每次迭代中设置
指针

enum { EXTRA_LEN = 400 };
size_t offset = 0;
int max = 1;
while (1)
{
    max += EXTRA_LEN;
    char *space = (char*)realloc(*line, max);  // Leak prevention
    if (space == 0)
        return len;
    *line = space;
    char *pointer = *line + offset;
    if (fgets(pointer, EXTRA_LEN + 1, stdin) == NULL)
        break;
    int len1 = strlen(pointer);
    len += len1;
    if (len1 != EXTRA_LEN || pointer[len1] == '\n')
        break;
    offset += len1;
}
我对在调用
fgets()
时使用401而不是400有所保留,但我没有精力确定它是否正确。我已经尽我所能对您的代码进行了最少的更改;如果是我正在润色的代码,我可能会做更广泛的更改。(特别是,
max
将从0开始,而不是1,并且我不会在调用
fgets()

时使用+1。如果
realloc()
失败,
*line=(char*)realloc(*line,max);
是内存泄漏(可能)。您会丢失指向仍然分配的内存的指针。重复400次(作为401的一部分)。您应该使用命名值,可以是
#define
enum
,甚至只是一个变量。此外,为了进行测试,请将其设置为较小的值(可能为20);然后在调试后进行调整以供生产使用。