0

I'm a bit new when it comes to files and records in C, and i'm currently working on a project. The following program, must give the user the options to edit,add,delete and view all records on a file.

#include <stdio.h>

typedef struct {
    int code;
    char description[100];
    int volume;
} product;

void addition(FILE *filePtr);
void removal(FILE *filePtr);
void showcase(FILE *filePtr);
void edit(FILE *filePtr);
void description(FILE *filePtr);

int main() {
    int pick, i;
    product p = { 0, "", 0 };
    FILE *filePtr;
    if ( ( filePtr = fopen( "stock.dat", "a+") ) == NULL ) {
        printf("The file could not be read");
    } else {
        for( i = 0; i < 100; i++ )
                fwrite( &p, sizeof(p) , 1 , filePtr) ;
        fclose(filePtr) ;


        while ( !feof( filePtr)) {
            printf("    ************ MAIN MENU ************\n");
            printf("  ** -------------welcome------------- **\n");
            printf(" **                                      ** \n");
            printf("*  Please select one of the commands below *\n");
            printf("********************************************\n");
            printf("* Press 1 to remove products from the list *\n");
            printf("* Press 2 to change a product's quantity   *\n");
            printf("* Press 3 to add a new product to the list *\n");
            printf("* Press 4 to view product list             *\n");
            printf("* Press 5 to change a product's description*\n");
            printf("********************************************\n");
            scanf("%d", &pick);

            switch ( pick ) {
            case 1:
                removal(filePtr);
                break;
            case 2:
                edit(filePtr);
                break;
            case 3:
                addition(filePtr);
                break;
            case 4:
                showcase(filePtr);
                break;
            case 5:
                description(filePtr);
                break;
            default:
                printf("Error! Please enter a correct number");
                break;
            }
        }
    }
    return 0;
}

void removal(FILE *cfPtr) {
    product p;
    int code, volume;
    product empty = { 0, "", 0 };
    cfPtr = fopen("stock.dat", "a");

    printf("\nYou are about to remove a product from the list\n");
    printf("Please type that product's code\n");
    scanf("%d", &code);
    fseek(cfPtr, (p.code - 1)*sizeof(p), SEEK_SET);
    fread(&p, sizeof(p), 1, cfPtr);

    if (code == 0) {
        printf("\nProduct code %d not found, please try again\n", &code);
    } else {
        printf("\nProduct found! Record is being deleted...");
        fseek(cfPtr, (p.code - 1)*sizeof(p), SEEK_SET);
        fwrite(&empty, sizeof(p), 1, cfPtr);
        printf("\nRecord succesfully deleted!\n");
    }
    fclose(cfPtr);
}

void addition(FILE *cfPtr) {
    product p;
    int code, quantity;

    printf("You are about to add a new product in the list\n");
    cfPtr = fopen("stock.dat", "a");
    printf("Please input the product's code that you wish to add\n");
    fscanf( stdin, "%d", &p.code);
    printf("Now input the available quantity of the product that is in stock\n");
    fscanf(stdin, "%d", &p.volume);

    fseek( cfPtr, (p.code - 1) * sizeof(p), SEEK_SET);
    fseek( cfPtr, (p.volume - 1) * sizeof(p), SEEK_SET);
    fwrite(&code, sizeof(p), 1, cfPtr);
    fwrite(&quantity, sizeof(p), 1, cfPtr);

    printf("\n\nThe Product with code %d and quantity of %d has been added succesfully\n\n", p.code, p.volume);
    fclose(cfPtr);
}

void showcase(FILE *cfPtr){
    product p;
    int i;

    cfPtr = fopen("stock.dat", "a");
    printf("\n\n\n               ****SHOWING ALL PRODUCTS****\n\n\n");
    printf("PRODUCT CODE                  QUANTITY IN STOCK");

    for (i=0; i=100; i++) {
        printf("\n%d", p.code);
        printf("                  %d\n", &p.volume);
    }
    fclose(cfPtr);
}

void edit(FILE *cfPtr){
    product p;
    int code, volume;

    cfPtr= fopen("stock.dat", "a");
    printf("\n\n\n\You are about to edit a product's quantity\n");
    printf("Please enter that product's code\n");
    scanf("%d", &code);

    while ( !feof( cfPtr)) {
        fseek(cfPtr, ( code - 1)*sizeof(p), SEEK_SET);
        fread( &code, sizeof(p), 1, cfPtr);
        if (code = p.code){
            printf("Product %d was found! current quantity: %d\n", &code, &p.volume);
            printf("Please enter the new quantity of the product\n");
            scanf("%d", &volume);

            fseek(cfPtr, ( volume - 1)*sizeof(p), SEEK_SET);
            fwrite( &p, sizeof(p), 1, cfPtr);

            printf("List has been updated, product %d has now %d units\n\n", &code, &volume);
            break;
        } else {
            printf("Product code %d was not found please try again", &code);
        }
    }
    fclose(cfPtr);
}

void description(FILE *cfPtr) {
    product p;
    char desc;
    int i, code, check=0;

    cfPtr= fopen("stock.dat", "a");

    printf("\n You are about to change a product's description\n");
    printf("Please enter the product's code");

    scanf("%d", &code);

    for (i=0; i=100; i++) {
        fseek( cfPtr, (code -1)*sizeof(p), SEEK_SET);
        fread( &code, sizeof(p), 1, cfPtr);
        if (code = p.code) {
            printf("\nCode found, now please enter the description");
            scanf("%c", &desc);
            p.description[i] = 'desc';
            fwrite( &p, sizeof(p), 1, cfPtr);
            check = 1;
        }
    }

    if (check != 1){
        printf("Code not found! Please try again");
    }
}

This is not the final code, and it surely has a lot of mistakes in it, what concerns me however most of all are the following code lines:

void showcase(FILE *cfPtr) {
    product p;
    int i;

    cfPtr = fopen("stock.dat", "a");
    printf("\n\n\n               ****SHOWING ALL PRODUCTS****\n\n\n");
    printf("PRODUCT CODE                  QUANTITY IN STOCK");

    for (i=0; i<100; i++) {  
        printf("\n%d", p.code);
        printf("                  %d\n", &p.volume);
    }
    fclose(cfPtr);
}

When this section runs, the program goes on and on nonstop, showing nonsense records. I've been working on this for 2 days, I've researched all I could, but nevertheless didn't find a solution myself. Again, I'm very new at this, and surely my stupid mistakes are probably going to get a lot of hate.Anyhow i would greatly appreciate even a hint of what I've done wrong, to make the program not properly save the record and show them.

Thanks in advance :)

UPDATE minor mistake was fixed on the aforementioned function, but the code still fails to save newly written records..

mc110
  • 2,825
  • 5
  • 20
  • 21
Tsusis
  • 23
  • 2
  • 5
    Typo here causing infinite loop: `for (i=0; i=100; i++)` – hmjd Jun 03 '14 at 10:50
  • 2
    Turn on compiler warnings. Also, [`while(!feof(f))` is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong). – The Paramagnetic Croissant Jun 03 '14 at 10:59
  • In addition, it would seem that you call fopen() twice on the same file, using the same pointer, without closing it in between. – Lundin Jun 03 '14 at 11:17
  • …and you have several lines like `fwrite(&code, sizeof(p), 1, cfPtr);`. `sizeof(code)` is not the same as `sizeof(p)` – mafso Jun 03 '14 at 11:21
  • [And your `scanf` calls are likely to cause trouble](http://stackoverflow.com/questions/3744776/simple-c-scanf-does-not-work) – mafso Jun 03 '14 at 11:27

3 Answers3

2
for (i=0; i=100; i++) {

= is assignment. i gets assigned the value 100 before each iteration.

You want to use a comparison operator, probably <:

for (i=0; i<100; i++) {
Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
  • thank you! fixed, but still it seems ive made another mistake within the code, that probably leads to the programm showing records that make no sense. To be precise, even after i change several times p.volume, it seems they are not saved, so when the function showcase is performed, the screen writes illogical records – Tsusis Jun 03 '14 at 11:00
  • @Tsusis check my answer. I explained both of the for loop and the values printed. – Zach P Jun 03 '14 at 11:17
1
 for (i=0; i=100; i++) {

 printf("\n%d", p.code);
 printf("                  %d\n", &p.volume);
 }

the problem is here. You probably meant to type for(i = 0 ; i < 100 ; i++) so it'll loop 100 times
What it does now is actually just check if he can put the value of 100 in i and as there's no error in that he continues, it'll be an endless loop in this case :P Also notice that the product p variable doesn't change through the loop (and it wasn't even initialized) so you're basically printing the same values - and not just any values, garbage values (garbage values is what found in the memory of that variable as no variable is initialized to zero in C, they all get some garbage values from that spot in memory) 100 times :P Take that in mind.

Zach P
  • 1,731
  • 11
  • 16
0

For each line.

p.description[i] = 'desc';

Is wrong. I'm not exactly sure what you are trying to do with this. I'm guessing to copy the string "desc" into the description char array. There are 2 things wrong with this. Firstly you must use double quotes to denote a string literal and single quotes denote a character literal, which can only be one character. The difference being that "" also allocates a NULL terminator character to signal the end of the string.

e.g.

char* mystr = "This is my string"; 
char p = 'p';
char nullchar = '\0';

Secondly you cannot just assign a string to a character array using the equals operator (unless you assign it character by character in a loop). You must copy the string.

strcpy(p.description, "desc");

Note for other strings you would want to check that they do not overrun the 100 character limit of your array. You could use strncpy or snprintf to achieve this.

Also why do you pass in the file pointer to all the action functions, but then open the file again in each function?


This code has many problems my advice is to hold all the inputted values in memory until the programme exits and at that time write out to the file. There is no need to do it after every addition, if you just hold it in memory. Unless of course something else is reading this file too?

You should also consider the format of your saved file. You are trying to write the structures themselves into the file at offsets decided by the user input. What if someone entered a very large code or volume value?

You could instead consider an in memory storage of a linked list for your products or if there are going to be a lot of products, a hash table indexed on the product code (disadvantage of using C is that these things don't come as part of the language) will be faster. Another option is a simple database (sqlite) and finally when writing out to a file you could consider a human readable format, such as

<code> <description> <volume>

For each entry. e.g.

1 "My Product" 10 2 "My Other Product" 25

When your programme starts you parse the file and turn it into the in memory representation, modify it then when you exit you write back the updated list.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61