写二进制文件改代码C语言避免死循环

问题遇到的现象和发生背景

目前这个代码while循环 while (!feof(pfBin1))总是死循环,能不能在不报错的情况下改成继续往下处理读写

遇到的现象和发生背景,请写出第一个错误信息
用代码块功能插入代码,请勿粘贴截图。 不用代码块回答率下降 50%
#include
#include
#include
typedef struct st_ocp
{
    unsigned char header;
    unsigned char version;
    unsigned char plen[2];
    unsigned char song[2];
    unsigned char shou[2];
    unsigned char ID[2];
    unsigned char luyou[2];
    unsigned char bao[4];
}OCP;

int main() {
    OCP *poCp = NULL;
    OCP r;
    poCp = &r;
    short pLen;
    FILE *pfBin1 = fopen("C:\\ocp\\ocp_cmds.bin", "rb+");//读文件
    if (pfBin1 == NULL) {
        printf(" error \n");
        return 0;
    }
    FILE *pfBin2 = fopen("C:\\ocp\\tlv.bin", "w");//写文件
    if (pfBin2 == NULL) {
        printf(" error \n");
        return 0;
    }
    while (!feof(pfBin1)) {
        fread(&r, 16, 1, pfBin1);//先读前十六个
        if ((r.song[0] == 0x04 && r.song[1] == 0x01) && (r.shou[0] == '\x2C' && r.shou[1] == 0x01))//判断
        {
            pLen = r.plen[0] * 256 + r.plen[1];
            unsigned char *pld = NULL;
            pld = (unsigned char *) malloc(sizeof(char) * pLen);
            memset(pld, 0, sizeof(unsigned char) * pLen);
            fread(pld, pLen, 1, pfBin1);
            int ph = 0;//设游标ph
            while (ph <= pLen)
            {
                if (pld[ph + 0] == 0x00 && pld[ph + 1] == 0x28 || pld[ph + 1] == 0x29)
                {
                    fwrite(&pld[ph + 3], pld[ph + 2], 1, pfBin2);
                }
                ph = pld[ph + 2] + ph + 3;
            }
           
            free(pld);//释放内存
        } else {
            fseek(pfBin1, pLen, SEEK_CUR);/
        }
    }
    fclose(pfBin2);
    fclose(pfBin1);//关闭文件
    getchar();
    getchar();
    return 0;
}

运行结果及详细报错内容
我的解答思路和尝试过的方法,不写自己思路的,回答率下降 60%

我的思路是在 while (ph <= pLen)加上 fread(&r, 16, 1, pfBin1);fread(pld, pLen, 1, pfBin1);可是没用

#include
#include
#include
typedef struct st_ocp
{
    unsigned char header;
    unsigned char version;
    unsigned char plen[2];
    unsigned char song[2];
    unsigned char shou[2];
    unsigned char ID[2];
    unsigned char luyou[2];
    unsigned char bao[4];
}OCP;

int main() {
    OCP *poCp = NULL;
    OCP r;
    poCp = &r;
    short pLen;
    FILE *pfBin1 = fopen("C:\\ocp\\ocp_cmds.bin", "rb+");//读文件
    if (pfBin1 == NULL) {
        printf(" error \n");
        return 0;
    }
    FILE *pfBin2 = fopen("C:\\ocp\\tlv.bin", "w");//写文件
    if (pfBin2 == NULL) {
        printf(" error \n");
        return 0;
    }
    while (!feof(pfBin1)) {
        fread(&r, 16, 1, pfBin1);//先读OCP前十六个
        if ((r.song[0] == 0x04 && r.song[1] == 0x01) && (r.shou[0] == '\x2C' && r.shou[1] == 0x01))//判断
        {
            pLen = r.plen[0] * 256 + r.plen[1];
            unsigned char *pld = NULL;
            pld = (unsigned char *) malloc(sizeof(char) * pLen);
            memset(pld, 0, sizeof(unsigned char) * pLen);//申请payload大小内存并清零
            fread(pld, pLen, 1, pfBin1);//读文件一个OCP读payload大小
            int ph = 0;//设游标ph 
            while (ph <= pLen)//游标在payload范围里面时
            {
                if (pld[ph + 0] == 0x00 && pld[ph + 1] == 0x28 || pld[ph + 1] == 0x29)
                {
                    fwrite(&pld[ph + 3], pld[ph + 2], 1, pfBin2);
                }
                ph = pld[ph + 2] + ph + 3;
            }
            fread(&r, 16, 1, pfBin1);
            fread(pld, pLen, 1, pfBin1);
            free(pld);//释放内存
        } else {
            fseek(pfBin1, pLen, SEEK_CUR);
            fread(&r, 16, 1, pfBin1);
        }
    }
    fclose(pfBin2);
    fclose(pfBin1);//关闭文件
    getchar();
    getchar();
    return 0;
}

我想要达到的结果,如果你需要快速回答,请尝试 “付费悬赏”

可以使用 fread() 函数的返回值来避免死循环。

fread() 函数返回实际读取的数据块数。如果返回 0,则表示已经到达文件末尾。因此,可以在循环内使用 fread() 的返回值来判断是否到达了文件末尾,从而避免死循环。

例如,可以修改你的代码如下:

while (!feof(pfBin1)) {
    // 读取数据块
    size_t count = fread(&r, 16, 1, pfBin1);
    if (count == 0) {
        // 到达文件末尾,退出循环
        break;
    }
    // 判断数据块是否符合条件
    if ((r.song[0] == 0x04 && r.song[1] == 0x01) && (r.shou[0] == '\x2C' && r.shou[1] == 0x01)) {
        // 执行其他操作
        ...
    } else {
        // 跳过不符合条件的数据块
        fseek(pfBin1, pLen, SEEK_CUR);
    }
}

在这个代码中,while (!feof(pfBin1)) 这个循环的作用是在文件末尾之前不断读取虚拟机的文件。由于 feof 函数只在读取到文件末尾时才会返回非零值,所以这个循环会一直执行,直到读取到文件末尾为止。

在这个代码中,如果希望在遇到特定条件时终止循环,可以使用 break 语句来终止循环。例如可以在内部循环(while (ph <= pLen))中加入一个条件判断,如果满足条件就使用 break 语句退出循环。

同时,也可以使用 goto 语句来跳出循环,但是这种方法并不是很推荐,因为它可能导致代码的可读性和可维护性降低。

另外如果想要跳过某个循环的剩余部分,可以使用 continue 语句。这将导致循环立即开始下一次迭代,而不会执行剩余的循环体。
望采纳。

你的代码在 while 循环内使用了 feof 函数来判断是否到达了文件末尾,但这是一种不正确的做法。

feof 函数会在读取到文件末尾之后返回非零值,但它并不会立即返回,直到你再次读取文件时才会返回。所以你的 while 循环会一直执行,即使已经到达了文件末尾。

要正确的判断是否到达了文件末尾,你应该使用 fread 函数的返回值来判断。fread 函数会返回成功读取的项数,如果返回 0,则表示到达了文件末尾。因此你可以使用下面的代码来修改 while 循环:

int result;
while ((result = fread(&r, 16, 1, pfBin1)) == 1)
{
// 其余代码不变
}

如果你想要继续往下处理读写,可以在 while 循环内部的 if 语句块之后添加代码。比如,你可以使用 fwrite 函数将数据写入另一个文件,或者使用其他函数处理数据。

希望这些信息对你有帮助。

是不是越界了

改成fscanf试试,返回值是读取成功的个数