2
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);

Once I get into the while loop, I am getting an infinite loop. The file pointer is fp, the prod is an instance of Struct called PRODUCT, stockquant and stockorderquant ara variables in the struct. I am attempting to change the values of stockquant and stockorderquant. This is a batch update tht im doing for my project. I am trying to go through the whole file called product.dat while editing each product's stockquant and orderquant.

Why am I getting an infinite loop? This method seems to work when I use it in an if statement that checks if the prod.id = userinput or not.

Any help?

Some extra code:

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

This is how I list my products (and it works!) (Please not the order quantity displayed here has nothing to do with the 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();
}

my struct is defined like below:

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

struct PRODUCT prod;
Jurgen Cuschieri
  • 658
  • 14
  • 33
  • 1
    Please don't use the homework tag. It's [deprecated](http://meta.stackexchange.com/questions/147100/the-homework-tag-is-now-officially-deprecated). – chris Jan 10 '13 at 01:14
  • someone else today told me to use it. – Jurgen Cuschieri Jan 10 '13 at 01:17
  • 2
    @JurgenCuschieri That someone else apparently isn't au courant. The homework tag is indeed deprecated since last fall. – Daniel Fischer Jan 10 '13 at 01:19
  • 1
    @JurgenCuschieri: There is general disagreement on that one. I for one think it should stay. However, it is officially deprecated. – Ed S. Jan 10 '13 at 01:19
  • can someone please help me? lol the homework tag is no longer there :D yay – Jurgen Cuschieri Jan 10 '13 at 01:20
  • 1
    hint, what happens if you print the current position in the file each iteration of the loop (with, say ftell). – cmh Jan 10 '13 at 01:21
  • Check the return values of functions for errors. – zch Jan 10 '13 at 01:24
  • If you are doing a lot of this and need it to be fast, you may want to consider using the old-skool I/O routines. See [my question](http://stackoverflow.com/questions/13171052/what-goes-on-behind-the-curtains-during-disk-i-o) related to this. – paddy Jan 10 '13 at 01:40
  • i better fix this prob first mate – Jurgen Cuschieri Jan 10 '13 at 01:44
  • cmh: I had 3 items and I got 2686672, with ftell(fp) now I created new file with 4 items and I'm getting 2686208 with every iteration – Jurgen Cuschieri Jan 10 '13 at 02:25
  • `printf("%d",&pos);` <- you're printing the address of `pos`, remove the `&`. And add a `pos = ftell(fp); printf("%d\n",pos);` before and after the `fseek` too to see that that does what it is supposed to. – Daniel Fischer Jan 10 '13 at 03:00
  • 100 100200 200300 300400 400500 500600 600700 this is what im getting. it seems like it is actually getting the file bigger by the infinite loop – Jurgen Cuschieri Jan 10 '13 at 03:08
  • Yes, it's getting bigger. Now to find out why. – Daniel Fischer Jan 10 '13 at 03:08
  • Can you add some debug info, `"Before fseek"`, `"After fseek"`, `"After fwrite"` to the printouts of `pos`? – Daniel Fischer Jan 10 '13 at 03:10
  • before fseek 100 after fseek 0 after fwrite 100 before fseek 200 after fseek 100 after fwrite 200 before fseek 300 after fseek 200 after fwrite 300 – Jurgen Cuschieri Jan 10 '13 at 03:16
  • @JurgenCuschieri http://chat.stackoverflow.com/rooms/22492/discussion-between-daniel-fischer-and-jurgen-cuschieri – Daniel Fischer Jan 10 '13 at 03:17

6 Answers6

3

Let me quote the man page for fopen:

Reads and writes may be intermixed on read/write streams in any order. Note that ANSI C requires that a file positioning function intervene between output and input, unless an input operation encounters end-of-file. (If this condition is not met, then a read is allowed to return the result of writes other than the most recent.) Therefore it is good practice (and indeed sometimes necessary under Linux) to put an fseek(3) or fgetpos(3) operation between write and read operations on such a stream. This operation may be an apparent no-op (as in
fseek(..., 0L, SEEK_CUR) called for its synchronizing side effect.

Calling fseek after the write,

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

ought to fix it.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
2

The problem is that

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

will move the current pointer sizeof(prod) before the current file pointer, and the next read will read the same record, and move before, etc.

Hece, the infinite loop.

Practicallym it reads all the time only the first record.

alinsoar
  • 15,386
  • 4
  • 57
  • 74
1

The sentence

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

Is trying to store a struct called product, and not prod in the file, and may be returning an error (not checked) that will prevent the pointer to move to the next record to read, making this code read once and again the same record.

You should store the prod variable you just changed, and dont forget to check for errors

if (fwrite (&prod, sizeof(prod), 1, fp)==-1)
    perror("fwrite error");
Manuel Miranda
  • 823
  • 5
  • 13
0

You will have problems with the value -sizeof(prod) because sizeof returns an unsigned value. When you negate this, it becomes a very large value, and then you implicitly cast it to long int.

Try this:

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

Also, you need to test that your fwrite succeeded or you will keep rewinding.

paddy
  • 60,864
  • 6
  • 61
  • 103
  • But fseek expects a long, so the implicit cast to long int should do the correct thing. – cmh Jan 10 '13 at 01:30
  • It would be unusual if that really caused the problem. Usually, `sizeof(size_t) >= sizeof(long)`, and the conversion from `size_t` to `long` just reinterprets the appropriate number of bits. Unless `sizeof(prod)` is huge, that would result in the same value as `-(long)sizeof(prod)`. – Daniel Fischer Jan 10 '13 at 01:30
  • Yeah I realised that after posting. – paddy Jan 10 '13 at 01:30
  • no thats surely not causing the problem, cause its working in other methods. thanks for posting anyways :D – Jurgen Cuschieri Jan 10 '13 at 01:34
0

I believe that you have an infinite loop, you always reseek the file position indicator:

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

So you read one element then reseek it and always read the same element, infinitely.

Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187
0

Second default argument type of fseek() in 'long'. You need to type cast it to 'long' i.e. fseek(fp, -(long) sizeof(prod), SEEK_CUR);