fgetc并没有阻止我的循环

时间:2015-11-19 13:18:50

标签: c loops fgetc

int ch;
char Name1[24], Name2[24],*p1,*p2;  
while ((ch = fgetc(inz)) != EOF){

            fseek(inz, -1, SEEK_CUR);

        fgets(Name1, 24, inz);
        fgets(Name2, 24, inz);
        p1 = Name1;
        p2 = Name2;
        p1 += 3;
        p2 += 3;

        if (atoi(p1) > atoi(p2)){
            fseek(inz, -46, SEEK_CUR);              
            fputs(Name2, inz);              
            fputs(Name1, inz);              

        }
        fseek(inz, -23, SEEK_CUR);      
        i --;
    }

我有这个代码。 inz是我在r + mod中的文件。我想将每个字符串与下一个字符串进行比较,并根据第4个字符对它们进行排序。这个功能正在发挥作用,但它不可阻挡地永远运行...... **我试图改变int ch;也是char。仍然没有奏效,而且feof没有用。

2 个答案:

答案 0 :(得分:1)

您的代码存在一些问题:

1)您假设每行至少有4个字符(加上换行符)。如果该行小于4个字节,则不会根据字符串本身进行排序,并且可能基于未初始化的内存进行排序。

2)你说你想根据第4个字符比较每一行,但你实际上是根据从第4个字符开始的字符串来比较它。您将其转换为整数,这意味着您还假设该行包含数值。

3)你假设每个字符串在文件中占用了24个字节。我猜你假设每个字符串长23个字符加一个换行符?这个假设有效吗?如果行可能短于24个字节,则此代码不正确:

fseek(inz, -46, SEEK_CUR);              

相反,您想要回退到两个字符串的实际总长度加上两个换行符。即使字符串是23个字节,你也不会在这里考虑新行,所以你想要重绕-48而不是-46。

4)将字符串写回文件时,您使用的是不包含换行符的fput。

5)你真的没有对文件进行排序,你只是经历了一次冒泡排序的迭代。您正在根据比较重新排序当前的两行,但这不会对整个文件进行排序。所以排序的逻辑也是错误的。

读取每一行,将其粘贴在一个数组中,根据您提到的标准对数组进行排序,然后将其写回文件将更加清晰。

除此之外,为什么循环永远不会结束?

循环的最后一行是:

fseek(inz, -23, SEEK_CUR);  

这意味着总是在尝试获取下一个字符(fgetc)之前返回23个字节。你永远不会看到EOF。

答案 1 :(得分:0)

好吧,如果你使用文件指针已经位于文件末尾的fgets,你将只获得一个EOF。而在您测试返回值的唯一fgetc之前的指令是fseek(inz, -23, SEEK_CUR);

这意味着当你到达文件末尾时,你首先返回23个字节,成功读取一些内容,并且可能在fgets后面的两个中忽略返回值的任何一个上获得EOF。并永远重复......

你应该怎么做?至少测试每个读取函数的返回值:

    if (fgets(Name1, 24, inz) == NULL) break;
    if (fgets(Name2, 24, inz) == NULL) break;

但并非全部。除非你非常确定所有行总是只有23个字符并且文件以二进制模式打开(或者你在Linux上),否则永远不要使用fseek。唯一合理的方法是将ftell然后fseek的位置存储到该位置。

最后但并非最不重要的是,你的algorythm返回一行,在Name1中读到你刚刚在Name2中读到的内容。您应该交换p1和p2,始终读入p2并比较p1和p2

这个文件将对文件进行排序,条件是它们都比SIZE短但长于4:

size_t oldpos = 0, tmp;
char Name1[SIZE], Name2[SIZE],*p1,*p2;
p1 = Name1;
p2 = Name2;
/* read first line and note position after it */
if (fgets(p1, SIZE, inz) == NULL) return;
tmp = ftell(inz);
/* loop reading in p2 */
while (fgets(p2, SIZE, inz) != NULL){

    if (atoi(p1 + 3) > atoi(p2 + 3)){
        /* swap last two lines */
        fseek(inz, oldpos, SEEK_SET);              
        fputs(p2, inz);
        fputs(p1, inz);          
        /* and go back to beginning of file - not optimal but robust */    
        fseek(inz, 0, SEEK_SET);
        /* again last line in p1 and note position */
        fgets(p1, SIZE, inz);
        oldpos = 0;
        tmp = ftell(inz);
    }
    else {
        /* order is ok untill here, note new position and swap buffers */
        oldpos = tmp;
        tmp = ftell(inz);
        swap(&p1, &p2);
    }
}