Thread: Read/Write Inventory

  1. #1
    Registered User
    Join Date
    Dec 2011
    Posts
    6

    Read/Write Inventory

    When the program is run, for some reason the program will not write or delete from the database.txt when asked to and then returns with a segmentation error(my nightmare). Please Help!!


    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
     
    struct node_item {
        struct node_item *next;
        int id;
        char name[128];
        float price;
    };
     
    struct node_r {
        struct node_r *next;
        int id;
        int quantity;
    };
     
    void welcome();
    void add();
    void del();
    void cashreg();
    void buy();
    void pay();
    void insert(struct node_item*p, int id, float price, char *name);
    void rem(struct node_item *p, int id);
    void r_insert(struct node_r *p1, int id, int quantity);
    void save(struct node_item *p);
    void list_ini(struct node_r *p1);
    void list_init(struct node_item *p);
     
    int main () {
        FILE *fp = fopen("database.txt", "r");
        int id;
        char name[128];
        float price;
        struct node_item p;
        assert (fp);
        while (1) {
            fscanf(fp, "%d %s %f", &id, name, &price);
            if (feof(fp) || ferror(fp)) break;
            insert(&p, id, price, name);
        }
        fclose(fp);
        welcome();
        fp = fopen ("database.txt", "w");
        save(&p);
        fclose(fp);
        return 0;
    }
     
    void welcome() {
        int go;
        printf("1. Add item to inventory\n");
        printf("2. Delete item from inventory\n");
        printf("3. Cash register\n");
        printf("4. Exit\n");
        scanf("%d", &go);
     
        if (go == 1) add();
        else if (go == 2) del();
        else if (go == 3) cashreg();
    }
     
    void add() {
        int id, quantity;
        char name[128];
        double price;
        FILE *fp;
        struct node_item p;
     
        printf("Unique id: ");
        scanf("%d", &id);
        printf("Name: ");
        scanf("%s", name);
        printf("Price: ");
        scanf("%lf", &price);
     
        insert(&p, id, price, name);
    }
     
    void del() {
        int id;
        struct node_item p;
        FILE *fp;
        printf("Unique id: ");
        scanf("%d", &id);
        rem(&p, id);
    }
     
    void cashreg() {
        int to;
     
        printf("1. Buy an item\n");
        printf("2. Pay\n");
        printf("3. Go back to Inventory screen\n");
       scanf("%d", &to);
     
       if (to == 1) buy();
       else if (to == 2) pay();
       else welcome();
    }
     
    void buy() {
        int id, quantity;
        struct node_r p1;
        FILE *f = fopen("receipts.txt", "w");
        list_ini(&p1);
        printf("Unique id: ");
        scanf("%d", &id);
        printf("Quantity: ");
        scanf("%d", &quantity);
     
        r_insert(&p1, id, quantity);
        fclose(f);
        cashreg();
    }
     
    void insert(struct node_item *p, int id, float price, char *name) 
    {
        while (p->next != 0) p = p->next;
        p->next = (struct node_item*) malloc(sizeof(struct node_item));
        p->next->id = id;
        p->next->price = price;
        strcpy(p->next->name, name);
        p->next->next = 0;
    }
     
    void rem(struct node_item *p, int id) {
        while (p->next != 0 && p->next->id != id) p = p->next;
        if (p->next == 0) {
            printf("list_remove: could not remove %d\n", id);
            return;
        }
        else {
        struct node_item *tmp = p->next->next;
        free(p->next);
        p->next = tmp;
        }
    }
    void r_insert(struct node_r *p1, int id, int quantity) {
        while (p1->next != 0) p1 = p1->next;
        p1->next = (struct node_r *) malloc(sizeof(struct node_r));
        if (p1->next->id = id) 
        {
        p1->next->quantity += quantity;
        }
        else {
            p1->next->id = id;
            p1->next->quantity = quantity;
        }
        p1->next->next = 0;
    }
    void save(struct node_item *p) {
        FILE *fp;
        while (p->next != 0) 
        {
            //p = p->next;
                fprintf(fp, "%d %s %f", p->next->id, p->next->name,   p->next->price);
            p = p->next;
    
    
        }
    }
    void list_init(struct node_item *p) {
        p->id = -1;
        p->next = 0;
    }
    void list_ini(struct node_r *p1) {
        p1->id = -1;
        p1->next = 0;
    }
    void pay() {
        struct node_r p1;
        FILE * f = fopen("receipts.txt", "r");
        int id, quantity,tmp=0,tmp2=0;
        double price;
        assert(f);
        while(1) {
            fscanf(f, "%d %d", &id, &quantity);
        tmp=tmp+id;
        tmp2=tmp2+quantity;
            if (feof(f) || ferror(f))
        {       
            printf("%d %d \n", tmp, tmp2);
             break;
        }    
    }
    }

  2. #2
    Registered User
    Join Date
    Nov 2011
    Posts
    63
    Aren't you losing track of the head of your linked list?

  3. #3
    Registered User
    Join Date
    Dec 2011
    Posts
    6
    I didnt think so, where do you see that happening, i could be wrong.

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by pbjorkman View Post
    I didnt think so, where do you see that happening, i could be wrong.
    Looking at your code this is not a good task for linked lists. You can make this far more efficient with far less code using Random Access file techniques. Below is a very basic example of using binary files and random access... note how simple it is. This technique also lends itself well to indexing and sorting as well as binary searches, so expanding this into a full blown inventory program is actually quite simple....

    Copy and paste this into your compiler and run it, to get familiar with what it does. The key section is the Random Access File Handlers... note how much simpler that is than linked lists?


    Code:
    //random access file demo
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    #include <ctype.h>
    #include <string.h>
    
    #define FNAME "random.dat"
    
    // test data struct
    struct t_Record
      { int number;
        char word[16]; }
      Record;
    
    
    
    ///////////////////////////////////////////////////////
    // Random Access File Handlers
    //
    
    // open or create the file
    FILE *FileOpen(char* Filename)
      { FILE* pFile;
        pFile = fopen(Filename,"rb+");
        if (!pFile)
          pFile = fopen(Filename,"wb+");
        return pFile; }
    
    
    // Write a record to the file
    int WriteRecord(FILE *File, int RecNum)
      { if( fseek(File, RecNum * sizeof(Record), SEEK_SET) == 0 )
          if ( fwrite(&Record,sizeof(Record),1,File) )
            return 1;
        return 0; }
    
    
    // read a record from the file
    int ReadRecord(FILE *File, int RecNum)
      { if( fseek(File, RecNum * sizeof(Record), SEEK_SET) == 0 )
          if ( fread(&Record,sizeof(Record),1,File) )
            return 1;
        return 0; }
    
    
    int AddRecord(FILE *File)
      { fseek(File,0,SEEK_END);
        fwrite(&Record,sizeof(Record),1,File);
        return (ftell(File) / sizeof(Record)) - 1; }
    
    
    
    //////////////////////////////////////////////////////////////
    // View a Record
    //
    
    int ViewRecord (FILE *File, int RecNum)
      { if (! ReadRecord(File,RecNum))
          { printf("Invalid record\n"); 
            return -1; }
        printf("-----\n");
        printf("Record        : %d\n",RecNum);
        printf("Number Value  : %d\n",Record.number);
        printf("Word Value    : %s\n",Record.word);
        printf("-----\n");  
        return RecNum; }
    
    
    
    //////////////////////////////////////////////////////////////
    // Add a new record
    //
    
    int AddNewData(FILE *File)
      { memset(&Record,0,sizeof(Record));
        printf("\nEnter a number : ");
        scanf("%d", &Record.number);
        printf("Enter a word : ");
        scanf(" %s",Record.word);
        return AddRecord(File); }
    
    
    
    //////////////////////////////////////////////////////////////
    // Edit a record
    //
    
    int EditRecord(FILE *File, int RecNum)
      { if (! ReadRecord(File,RecNum))
          { printf("Invalid record\n");  
            return -1; }
        printf("\n-----\n");
        printf("Record        : %d\n",RecNum);
        printf("Number Value  : %d\n",Record.number);
        printf("Word Value    : %s\n",Record.word);
        printf("-----\n");  
        
        do
          { while(getchar() != '\n');
            printf("Change Values: Number, Word or Save (N, W or S) ? ");
            switch (toupper(getchar()))
              { case 'N' :
                  printf("\nEnter new number : ");
                  scanf("%d",&Record.number);
                  break;
                case 'W' : 
                  printf("Enter new word : ");
                  scanf(" %15s", Record.word);
                  break;
                case 'S' :
                  if (WriteRecord(File,RecNum))
                    printf("\nRecord #%d updated\n",RecNum);
                  return RecNum; } }
        while(1);
        return -1; }
    
    
    ////////////////////////////////////////////////////////////////
    // List records
    // 
    
    void ListRecords(FILE *File )
      { int i = 0;
        printf("\nRecord     Number\tWord\n\n");
        while (ReadRecord(File,i))
          { printf("%3d%16d\t%s\n",i,Record.number,Record.word); 
            i++; }
        printf("\n\n"); }
    
    
    
    ////////////////////////////////////////////////////////
    // this is for demonstration purposes only
    // you would not do this in a real program
    void InitFile(FILE* File)
     { int x, y;
       memset(&Record,sizeof(Record),0);
       for (x = 0; x < 10; x++)
          { Record.number = rand();
            for (y = 0; y < ((Record.number % 15) + 1); y++)
              Record.word[y] = (rand() % 26) + 'a';
            Record.word[y] = 0;
            if (! WriteRecord(File,x))
              printf("Oh drat!");  } }
     
    
    
    //////////////////////////////////////////////////////////
    // program mains
    //
    int main (void)
      { int Rec = 0; // record number
        FILE *File;
    
        srand(time(NULL));
    
        File = FileOpen(FNAME); 
        if (!File)
          { printf("Curses foiled again!\n\n");
            exit(-1); }
    
        printf("Random Access File Demonstration\n\n");
     
        do
          { printf("Menu : Dummy, Add, Edit, View, List, Quit (D, A, E, V, L or Q) : ");
            switch(toupper(getchar()))
              { case 'D' :
                  printf("Creating dummy file of 10 entries\n");
                  InitFile(File);
                  break;
                case 'A' :
                  Rec = AddNewData(File);
                  printf("Record #%d Added\n\n", Rec);
                  break;              
                case 'E' :
                  printf("\nRecord number (-1 Cancels): ");
                  scanf("%d",&Rec);
                  if (Rec > -1)
                    EditRecord(File,Rec);
                  break;
                case 'V' :
                  printf("\nRecord number (-1 Cancels): ");
                  scanf("%d",&Rec);
                  if (Rec > -1)
                    ViewRecord(File,Rec);
                  break;
                case 'L' :
                  ListRecords(File);
                  break;
                case 'Q' :
                  fclose(File);
                  return 0; } 
                  
             while(getchar() != '\n'); }
        while (1); 
        return 0; }

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Except, Tater, that this assignment probably specifies the use of a linked list, and the file handling is just ancillary.

  6. #6
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    One big problem:
    Code:
    struct node_item {
        struct node_item *next;
        int id;
        char name[128];
        float price;
    };
      
    ...
    
    int main () {
        FILE *fp = fopen("database.txt", "r");
        int id;
        char name[128];
        float price;
        struct node_item p;
        assert (fp);
        while (1) {
            fscanf(fp, "%d %s %f", &id, name, &price);
            if (feof(fp) || ferror(fp)) break;
            insert(&p, id, price, name);
        }
    
    ...
    
    void insert(struct node_item *p, int id, float price, char *name)
    {
        while (p->next != 0) p = p->next;
        p->next = (struct node_item*) malloc(sizeof(struct node_item));
        p->next->id = id;
        p->next->price = price;
        strcpy(p->next->name, name);
        p->next->next = 0;
    }
    #1 What value(s) are in p - specifically the next field - when you first call insert?
    #2 Don't cast malloc, the function returns a void pointer that can be safely assigned without the need for a cast.
    #3 Your code seems to want to treat the first node - the one passed in from main (p) - as a place holder. It's purpose seems to be nothing other than a "node that has a convenient next pointer" that we will be appending to. No data is written to it other than an attempt to reset its next pointer which doesn't even work correctly because of #1.
    Last edited by hk_mp5kpdw; 12-08-2011 at 12:38 PM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  7. #7
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by rags_to_riches View Post
    Except, Tater, that this assignment probably specifies the use of a linked list, and the file handling is just ancillary.
    Yep... that's a definite possiblity.

    I was thinking: "What if he doesn't know about this alternative" and thought I'd at least stick it up there. I mean really, when your doing stuff like inventories and phone books, linked lists are not the way to go... Random Access makes so much more sense.

  8. #8
    Registered User
    Join Date
    Dec 2011
    Posts
    6
    In my understanding aren't the values of p in the database.txt file when it reads it in? thats where iv run into trouble cause i thought that coding was correct.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Write and Read in a TXT.
    By Ervilha in forum C Programming
    Replies: 2
    Last Post: 04-06-2010, 07:38 AM
  2. Read + Write = ?
    By audinue in forum General Discussions
    Replies: 26
    Last Post: 01-23-2010, 06:14 AM
  3. read and write xml
    By munna_dude in forum C Programming
    Replies: 1
    Last Post: 12-13-2006, 02:43 AM
  4. read(), write() in GCC
    By Lord CyKill in forum C Programming
    Replies: 1
    Last Post: 09-24-2003, 11:10 PM
  5. write(), read()
    By RedRum in forum C++ Programming
    Replies: 5
    Last Post: 06-09-2002, 11:45 AM

Tags for this Thread