【问题标题】:infinite loop in while loopwhile循环中的无限循环
【发布时间】:2012-12-24 07:56:12
【问题描述】:
fp=fopen("Product.dat","rb+");
while (fread(&prod,sizeof (prod),1,fp)==1) {
    prod.stockquant = prod.stockquant + prod.stockorderquant;
    prod.stockorderquant = 0;
    fseek(fp, -sizeof(prod), SEEK_CUR);
    fwrite (&prod, sizeof(prod), 1, fp);
}
fclose (fp);

一旦我进入 while 循环,我就会进入一个无限循环。 文件指针是 fp,prod 是一个名为 PRODUCT 的 Struct 实例,stockquant 和 stockorderquant 都是 struct 中的变量。我正在尝试更改 stockquant 和 stockorderquant 的值。这是我为我的项目做的批量更新。我正在尝试在编辑每个产品的 stockquant 和 orderquant 时浏览名为 product.dat 的整个文件。

为什么会出现无限循环? 当我在检查 prod.id = userinput 的 if 语句中使用此方法时,它似乎有效。

有什么帮助吗?

一些额外的代码:

void batchupdate(void) { 
    system("cls");
    FILE *fp;
    int c=0;
    gotoxy(20,4);
    printf("****Batch Update Section****");
    char another='y';
    while(another=='y')
    {
        system("cls");
        gotoxy(15,6);
        printf("Are you sure you want to Batch update (Press Y or N)?");

        if((getch()=='y') || (getch() == 'Y')) {
        system("cls");
        int pos;

        fp=fopen("Product.dat","rb+");
        while(fread(&prod,sizeof(prod),1,fp)==1) {
                prod.stockquant = prod.stockquant + prod.stockorderquant;
                product.stockorderquant = 0;

                fseek(fp, -(sizeof(prod)), SEEK_CUR);
                fwrite (&prod, sizeof(prod), 1, fp);
                getchar();
                pos = ftell(fp);
                printf("%d",&pos);


        }
        fclose (fp);

        gotoxy(15,16);
        printf("Complete");
        gotoxy(15,18);
        printf("All products stock quantity have been updated. The stock order quantity has been reset");

        gotoxy(15,16);
        printf("Do you want to modify another product?(Y/N)");
        fflush(stdin);
        another=getch() ; }

    else { if((getch()=='n') || (getch() == 'N')) {
                mainmenu();
           }
    }
}
    returnfunction();
}

这就是我列出我的产品的方式(它有效!)(请注意这里显示的订单数量与 stockorderquant 无关

void listproduct(void)  
{
    int x;
    FILE *fp;
    system("cls");
    gotoxy(1,1);
    printf("*********************************Product List*****************************");
    gotoxy(2,2);
    printf("Name              ID    Price  StockQuant  Order Quant  Description");
    x=4;
    fp=fopen("Product.dat","rb");
    while(fread(&prod,sizeof(prod),1,fp)==1){
        gotoxy(2,x);
        printf("%s",prod.prodname);
        gotoxy(20,x);
        printf("%d",prod.prodid);
        gotoxy(26,x);
        printf("%.2f",prod.price);
        gotoxy(34,x);
        printf("%d",prod.stockquant);
        gotoxy(46,x);
        printf("%d",prod.orderquantity);
        gotoxy(59,x);
        printf("%s",prod.description);
        printf("\n\n");
        x++;
    }
    fclose(fp);
    gotoxy(35,25);
    returnfunction();
}

我的结构定义如下:

struct PRODUCT
{
    int id;
    char name[30];
    char desc[50];
    float price;
    int stockquant;
    int orderquant;
    int stockorderquant;
};

struct PRODUCT prod;

【问题讨论】:

  • 请不要使用作业标签。这是deprecated。
  • 今天有人告诉我用它。
  • @JurgenCuschieri 其他人显然不是 au courant。自去年秋天以来,家庭作业标签确实已被弃用。
  • @JurgenCuschieri:对此存在普遍分歧。我认为它应该留下来。但是,它已被正式弃用。
  • 提示,如果每次循环迭代都打印文件中的当前位置会发生什么(比如 ftell)。

标签: c loops infinite


【解决方案1】:

让我引用 fopen 的手册页:

读和写可以以任何顺序混合在读/写流上。请注意,ANSI C 要求文件定位函数在输出和输入之间进行干预,除非输入操作遇到文件结尾。 (如果不满足此条件,则允许读取返回除最近写入之外的写入结果。)因此,放置fseek(3) 或fgetpos(3) 操作是一种很好的做法(在Linux 下有时确实是必要的)在此类流上的写入和读取操作之间。此操作可能是明显的无操作(如
fseek(..., 0L, SEEK_CUR) 调用其同步副作用。

写完后调用fseek,

fseek(fp, -sizeof(prod), SEEK_CUR);
fwrite (&prod, sizeof(prod), 1, fp);
fseek(fp, 0, SEEK_CUR);

应该修复它。

【讨论】:

    【解决方案2】:

    问题是

    fseek(fp, -sizeof(prod), SEEK_CUR);
    

    会将当前指针sizeof(prod)移动到当前文件指针之前,下一次读取会读取相同的记录,并移动到之前等等。

    嘿嘿,无限循环。

    实际上它一直只读取第一条记录。

    【讨论】:

    • 但是fwrite(&product, sizeof(prod), 1, fp) 会将指针返回到下一条要读取的记录的开头,不是吗?
    • 如果我删除它,我仍然会得到一个无限循环!
    • 循环 1. 读取一条记录, 2. 将文件指针向后移动, 3. 写入一条记录。那应该将文件指针完全向前移动一条记录,不是吗?
    【解决方案3】:

    句子

    fwrite (&product, sizeof(prod), 1, fp);
    

    正在尝试在文件中存储一个名为 product 而不是 prod 的结构,并且可能会返回一个错误(未检查),这将阻止指针移动到要读取的下一条记录,从而使此代码一遍又一遍地读取相同的记录。

    您应该存储刚刚更改的prod 变量,并且不要忘记检查错误

    if (fwrite (&prod, sizeof(prod), 1, fp)==-1)
        perror("fwrite error");
    

    【讨论】:

    • 其实我之前改过。我也在这里编辑了。我仍然得到无限循环
    • 不要忘记,当我进入while循环时,它会立即进入无限循环模式,因此源代码的那个点是无法到达的
    • 那么...... while 循环不执行 任何 语句?甚至没有printf("hello\n")?
    【解决方案4】:

    -sizeof(prod) 的值会有问题,因为sizeof 返回一个无符号值。当你否定它时,它变成一个非常大的值,然后你将它隐式转换为long int。

    试试这个:

    fseek(fp, -(int)sizeof(prod), SEEK_CUR);
    

    另外,您需要测试您的fwrite 是否成功,否则您将继续倒带。

    【讨论】:

    • 但是 fseek 需要一个 long,所以隐式转换为 long int 应该做正确的事情。
    • 如果这真的导致了问题,那将是不寻常的。通常,sizeof(size_t) >= sizeof(long),以及从size_t 到long 的转换只是重新解释适当的位数。除非sizeof(prod) 很大,否则会产生与-(long)sizeof(prod) 相同的值。
    • 是的,我在发帖后意识到了这一点。
    • 不,那肯定不会导致问题,导致它在其他方法中工作。谢谢你发帖:D
    【解决方案5】:

    我相信你有一个无限循环,你总是重新寻找文件位置指示器:

    fseek(fp, -sizeof(prod), SEEK_CUR);
    

    所以你阅读了一个元素,然后重新搜索它,并且总是无限地阅读同一个元素。

    【讨论】:

    • 我希望 sizeof(prod) 是 1。你是什么意思?
    【解决方案6】:

    'long' 中 fseek() 的第二个默认参数类型。您需要将其类型转换为“long”,即 fseek(fp, -(long) sizeof(prod), SEEK_CUR);

    【讨论】:

      猜你喜欢
      • 2014-03-29
      • 2015-06-25
      • 2013-02-22
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多