Thread: stock program

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    17

    Red face stock program

    Can someone help me and maybe adapt the code, I'm trying to create a small program to act like a database. I need to add edit and delete files I have done so but it doesn't work properly can I have some help? I want the program to read from file and write to it everytime I add an item. And also sometimes the program works and sometimes some function does not work so I'm not sure why this happens...
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ncurses.h> 
     
    #define MAXNAME 50
    #define MAXCODE 100
    #define MAXPRICE 50
    #define MAXITEMS 1000
     
    struct video {
       char name[MAXNAME];
       char code[MAXCODE];
       char price[MAXPRICE];
       int  quantity;         
    };
    typedef struct video stk;
     
    stk items[MAXITEMS];
    int NumItems;
     
    int Size = sizeof(stk); //display size for the test
    
    
     
    int addItems(void);  
    int idelete(void);
    int edit(void);
    int fetch(char *buff);
    void menu(void);
    void view(void);
    void sortRecords(void);
    
    int main(void) {
       char buff[214];
       int i; //number of entries
       
       FILE * fp_in;
      
       if((fp_in = fopen("stockdb.txt", "r")) == NULL) {
          fputs("Error! Can't find or open stockdb.txt\n", stderr);
          return 1;
       }
       i=0;
       while((fgets(buff, sizeof(buff), fp_in))!=NULL) {
          buff[strlen(buff)-1]='\0';
          sscanf(buff, "%[^,], %[^,], %[^,], %d ", items[i].name,items[i].code,items[i].price,&items[i].quantity);
          
          if(++i==MAXITEMS) {
             printf("Error! The array to hold data, is too small. Please enlarge it or delete stock record\n\n");
             getchar();
             break;
          }
       }
       
       fclose(fp_in);
       NumItems=i;
       sortRecords();
       //view();
       menu();
       printf("                                  \n");
       printf("                                  \r");
     
       return 0;
    }
    /* this function is 90% done */
    
    int addItems(void) {
       int i,j=0,ok=0,len;
       char buff[80]={'\0'};
       char ch='y';
       stk stk1; //variable only for this function
     
       while(ch=='y' || ch=='Y') {
          printf("                               \n");
          printf(" Name:                           ");
          fgets(buff, MAXNAME, stdin);
          len=strlen(buff)-1;
          buff[len]='\0';
          strcpy(stk1.name, buff);
    
          printf("                              *\n");
          printf(" Bar code:                      *");
    
          fgets(buff, MAXCODE, stdin);
          len=strlen(buff)-1;
          buff[len]='\0';
          strcpy(stk1.code, buff);
     
          printf("                              *\n");
          printf(" Price:                         *");
          fgets(buff, MAXPRICE, stdin);
          len=strlen(buff)-1;
          buff[len]='\0';
          strcpy(stk1.price, buff);
     
          printf("                              *\n");
          printf(" Quantity:                     * ");
          fgets(buff, sizeof(items[0].quantity), stdin);
          sscanf(buff, "%d", &stk1.quantity);
     
     
          for(j=0;j<MAXITEMS;j++) {
             if(!(items[j].name[0])) {
                items[j] = stk1;
                ok=1;
                ++NumItems;
                break;
             }
          }
          if(!ok) {
             printf("\nArray is full, couldn't add that record");
             --NumItems;
             break;
          }
          else {
             printf("\nAdd another item to the stock? [y/n]: ");
             scanf("%1c", &ch);
             getchar();
          }
       }
       
       //clean up screen
       for(i=12;i<22;i+=2) {
    
          printf("          *\n");
       }
       return ok;       //successful add
    }
    int edit(void) {
       char buff[80];
       int i=0;
     
       printf("\nEnter the name of the item you want to edit: ");
       fgets(buff, MAXNAME, stdin);
       if(buff[strlen(buff)-1]=='\n')
          buff[strlen(buff)-1]='\0';
     
       i = fetch(buff); //in the list?
       if(!i)                 //no
          return 0;
     
       //video was found, i is it's index in the array
    
       printf("\n\t  Name: %s\n\t  Bar_code: %s\n\t Quantity: %2d\n",
       items[i].name, items[i].code, items[i].quantity);
       printf("\n\t  Enter new name [hit <enter> to leave it unchanged]: ");
       fgets(buff, MAXNAME, stdin);
       if(strlen(buff) >1) {
          if(buff[strlen(buff)-1]=='\n') {
            buff[strlen(buff)-1]='\0';
            strcpy(items[i].name, buff);
          }
       }
       printf("\n\t  Enter new barcode [<enter> to leave it unchanged]: ");
       fgets(buff, MAXCODE, stdin);
       if(strlen(buff) >1) {
          if(buff[strlen(buff)-1]=='\n') {
            buff[strlen(buff)-1]='\0';
            strcpy(items[i].code, buff);
          }
       }
       printf("\n\t  Enter new quantity [<enter> to leave it unchanged]: ");
       fgets(buff, sizeof(items[0].quantity), stdin);
       if(strlen(buff) >1) {
          sscanf(buff, "%d", &items[i].quantity);
       }
       sortRecords();
       return i;
    }
    int fetch(char *buff) {
       int lo, hi, mid;
       lo=0;
       hi = NumItems-1;
          
       while(lo <= hi) {
          mid=(lo + hi)/2;
          if((strcmp(items[mid].name, buff)) <0) {
             lo=mid+1;
          }
          else if((strcmp(items[mid].name, buff)) >0) {
             hi=mid-1;
          }
          else
             return mid;
       }
       return -1;
    }
    int idelete(void) {
       char buff[80];
       int i;
       printf("\nEnter the name of the item in stock you want to delete:  ");
       fgets(buff, MAXNAME, stdin);
       buff[strlen(buff)-1]='\0';
       i = fetch(buff); //get buff's index in the array
       if(i) {
          printf("Delete this record [y/n] ? ");
          printf("\n\t Name: %s \n\t Bar code: %s \n\t Quantity: %d",items[i].name,\
          items[i].code, items[i].quantity);
          fgets(buff, 2, stdin);
          if(buff[0]=='y' || buff[0]=='Y') {
             printf("\nItem has been deleted");
             getchar();
             getchar();
             //*vids[i].name = "";
             //*vids[i].code = "";
             //*vids[i].rating = 0;
          }
          return i;
       }
       else
          return 0;
    }
    void menu(void) {
       char ch;
       char buff[80];
       int i,n, index, ok=0;
      
       do {
          //clear the menu area of the display
          //for(i=0;i<3;i++) {
          //printf("                                                                          *\n");
          //}
          printf("                                                                             \n");
    
          printf("                <<<<      Welcome to the Main Menu       >>>>                \n");
          printf("                                                                             \n");
          printf("        [a] Add an item            [d] Delete an item                        \n");
          printf("        [e] Edit an item           [s] Search for an item                    \n");
          printf("        [v] View all items                                                   \n");// not ready yet
          printf("                                                                            *\n");
          printf("                     Your Choice, or Q to quit:                              \n");
          printf("                                                                            *\n");
          //i=_wherey();
         
          fgets(buff, sizeof(buff), stdin);
          sscanf(&buff[0],"%c",&ch);
          switch (ch) {
             case 'a': 
                printf("\n Would you like to add a new item? [y/n]: ");
                ch = getchar();
                getchar();
                if(ch=='y' || ch=='Y') {
                   n=addItems();
                   if(n) {   //a successful add
             sortRecords();
                      printf(" One item  has been added. %d items in all now.                    **\n",NumItems);
                      getchar();
                   }
                }
               printf("                   *\n");
                break;
             case 'd':
                ok=idelete();
                if(ok) 
                   --NumItems;
                break;
          case 'e': edit();  
                    break;  
          case 's':
             for(i=0;i<10;i++) {
                printf("                  *\n");
             }
     
             printf("Enter item's  \n  Name: ");
             fgets(buff, sizeof(items[0]), stdin);
             buff[strlen(buff)-1]='\0';
             index = fetch(buff);
             //printf("Index: %d\n",index); getchar();
             if(index>-1) {
                printf(" #%d) title: %s\n  bar_code: %s\n   price: %s\n  quantity: %d\n\n",
                        index+1,items[index].name,items[index].code,items[index].price,items[index].quantity);
                printf("                   *\n");
                printf("                   *\n");
                printf("                   *\n");
                printf("                   *\n");
                getchar();
             }
             break;
          //case 'v':  view(); break;
          //case 'w':  writeAll(); break;
     
          case 'Q':  ch='q';
          case 'q':  break;
          default: printf("\n\t\t    Please enter a valid selection\n");
        };
     
      }while(ch!='q');
    }
     
    void sortRecords(void) {
       int i, j;
       stk testy;    
       for(i=1;i<NumItems;i++)
     { 
          testy = items[i];
          j = i-1;
          while((strcmp(items[j].name, testy.name)) > 0)
     {
             items[j + 1] = items[j];
             --j;
             if(j<0) break;
          }  
          items[j+1] = testy;
       }
     
    }
    Last edited by akerman; 11-04-2012 at 03:23 PM.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Ha Ha! yes, that does look quite familiar!

    Keep in mind that that program was not completed when I posted it, so parts of it didn't work. That can be fixed for this version you want.

    Programming is all about the big design, interacting successfully with small details, and we need to know what those small details are - like the data in your records - we need to see a sample of three records or so, to see how it's arranged.

    In my video program, for instance, I have each record (each video is a record), on a single line of text, with the struct members separated by a comma.

    Post up what you want**, and we can make suggestions from there. What you want to do is to keep it simple. That increases the chance of having a bug-free program, and decreases the amount of time it takes to have the program finish the task you give it.


    **And please, be complete so we know what you want to do. "Make it work", just won't cut it.

  3. #3
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    I changed my idea and the thing is I haven't changed a lot but the program works sometimes fine and sometimes it does not work... I have tried to test it and I just finishing the bit for adding but I don't think it will write to a file...
    Last edited by akerman; 11-04-2012 at 03:49 PM.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by akerman View Post
    I changed my idea and the thing is I haven't changed a lot but the program works sometimes fine and sometimes it does not work... I have tried to test it and I just finishing the bit for adding but I don't think it will write to a file...
    Well it has no writeAll() function, so that's a problem getting the data written to the file/s.

    Before working on writeAll(), you need to settle on what you are going to use for your data struct, AND for the way the records will be organized in the array.

    It's good to use 1 row of text per record, with something (space, comma, etc.), used to separate one record's field, from the next field.

    Another way you could organize it is to have one record field on each row. Easy to work with, but takes up a lot more space.

    This is the writeAll() function, and you WILL need it, because you need to write out your changes ONLY when you have:

    1) edited a record
    2) added a record
    3) deleted a record

    When viewing records, or viewing all records, there's no need to write out the data again - it would simply be a duplicate set of records.

    What I'd suggest is calling writeAll() at the end of the above three function: where you add a record, where you edit a record, or where you delete a record.

    Code:
    int writeAll(void) {
      int i;
      FILE *fp;
    
      //remove("videos.bak");
      if(rename("videodb.txt", "videodb.bak")==0) {
       
       if((fp=fopen("videodb.txt", "wt"))==NULL) {
          printf("\nError opening videos.txt file. No records were written.\n");
          return 1;
        }
    /*   
    }else {
        printf("\nError renaming in function writeAll()\n");
        return 1;
      }
    */
      i=0;
      while(1) {
        fprintf(fp, "%s, %s, %s, %d\n",videos[i].title,videos[i].actor,videos[i].genra, videos[i].rating);
        ++i;
        if(i>NumVideos) break;
      }  
      fclose(fp);
    
      return 0;
    }
    You'll need to make your changes to the struct and struct members, names.

    How many records do you expect to have in the file?

  5. #5
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    well I'm trying to have as many records as possible but in c you can only have limited so I'm aiming at around 1000 which I already specified in the code. The main problem is that some of the function when you run this program do not even active I'm not sure why but I will have a closer look at it again...

  6. #6
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    one more question sometimes I'm trying to open the file and when the program is running I cannot do it. Are there any chances of making it available when program is running?

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by akerman View Post
    one more question sometimes I'm trying to open the file and when the program is running I cannot do it. Are there any chances of making it available when program is running?
    1) In C, you can make HUGE arrays and files - you're just not doing it correctly yet. We'll show you how to fix that.

    2) C is a VERY strong file handler. If a file "isn't available", it's because it's been mishandled in some way. We'll show you how to fix that.

    Post up a 3 record example of your data. Then I can see what's right or wrong.

  8. #8
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    Hi, again. I have added what you gave me however, the program still does not delete or edit any of the records and I'm not to sure why... I have added writeAll function at the end of add edit and delete but it didn;t change anything

  9. #9
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    i have added the code you gave me but in the file it just shows this... , , , 0
    , , , 0
    not sure why?

  10. #10
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    adak if you see this post please help me out. I have tested the program and now it adds records and I can change them however delete function does not delete records from file but it just substitutes an empty row like , , , 0 do you know how to solve this?

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Yes. The way I work with records is not to delete an empty one - I keep it, and reuse it when another record must be entered. It doesn't display or show up on any output - it's just there, holding down a space in the file. When the file gets too many empty records, it will write out a new data file, and be sure to delete most (not all) empty records.

    But you can delete empty records at once, every time if you want. That means every time a record is to be deleted, the entire file is written out to a duplicate file, and empty records are deleted in the process. When that's finished, the old file is deleted, and the duplicate file is renamed with the old file name.

    There is a way to actually delete a record from the file, in place - but I would NOT recommend it. Commonly, that causes data to be written badly at some time, and now your data can be a mess if you aren't lucky.

    I'll check back with you in about 3 hours, if you need help doing this, post back with what has you stymied.

  12. #12
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    I would say that I need another function for deleting and it would be almost the same as the writeAll() how every I'm not sure how it suppose to be constructed...

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by akerman View Post
    I would say that I need another function for deleting and it would be almost the same as the writeAll() how every I'm not sure how it suppose to be constructed...
    The general outline would be:

    open the current data file for r with fopen() --used for input.

    open a second data file for writing with fopen() - used for output of the new file, without any empty records included.

    Using the same code that loaded up the data file in the first place, read through each record in the input data file. Every record with a name or other key value marked as deleted, doesn't get written into the new data file - it just gets looked at, seen as a deleted record by the program as described here, and passed over for the next record. When the new data file has finished being written to, fclose() both files. remove the old file first, and then rename the new file, to the old file's name. That prevents file opening errors next time you run or work with the program.

    You may want to create a two tier backup plan - writing out the old backup to a second backup file, before overwriting it. If you make regular backups of your own, that's not necessary, but otherwise, it's a good idea.

    As you stated, the code you need for the above is almost all in the program's input and output blocks of code. You just need to put it together to fit this use. And it won't hurt to get some practice coding, either! Practice may not make perfect, but it surely improves your skill. Be sure to use a practice set of data for this testing. It's not uncommon to garble or wipe out a file when doing this.
    Last edited by Adak; 11-12-2012 at 03:10 AM.

  14. #14
    Registered User
    Join Date
    Oct 2012
    Posts
    17
    hi again, I have left delete function for the end. However I'm trying to sort my other function which is for displaying all records from file but somehow I'm getting an error and not sure why...
    Code:
    void showAll(){
         FILE *fp;
         struct stock stk[1000];
         int totstock,i;
         fp = fopen("stockdb.txt","r");
         clrscr();
         fseek(fp,0,SEEK_END);
         totstock=ftell(fp)/sizeof(obj);
         printf("\n*****All items in stock*****\n");
         printf("\n\nName\tCode\t\t\tPrice\tQuantity\n\n");
         printf("\n\n%d\n",totstock);
         for(i=1;i<=totstock;i++){
         fscanf(fp,"%s %s %s %c",&stk.name,stk.code,&stk.price,&stk.quantity);
         fprintf(stdout,"%-15s %-15s %-8s %-2c \n",stk.name,stk.code,stk.price,stk.quantity);
         }
         getch();
         fclose(fp);
    }

    it says that array is incomplete... some suggestion?

  15. #15
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    1) To print the file's contents, you don't need an array.

    2) You don't need to know the file size, etc.

    3) Open the file, read from the file into your variables, and print out the variables with the format you want.

    That's all you need to do here.

    First, make an instance of struct stock, here, so you can read the data into the struct members correctly. You only need one, because you'll use it over and over in the while loop that reads from the file.

    Use the return value of fscanf() to help read the entire file:
    Code:
    //open the file for reading, same as always.
    
    char c;
    struct stock stk1;
    
    while((fscanf(fp, "%s %s %s %d%c",stk1.name,stk1. code,stk1.price, &stk1.quantity,&c)) > 3) {
       printf("%s %s %s %d \n", stk1.name,stk1.code,stk1.price,stk1.quantity);
    
    }
    
    fclose(fp);  
    getch();
    
    /* with fscanf(), use an & before the struct member if it's NOT a string (or pointer) */
    I believe you'll want to change price to a double, in your entire program, before long. It's now a string.
    Last edited by Adak; 11-13-2012 at 02:20 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Stock Program
    By Adrian K'Ski in forum C Programming
    Replies: 15
    Last Post: 06-03-2012, 07:30 AM
  2. Stock system
    By dan.goodridge in forum C Programming
    Replies: 7
    Last Post: 05-21-2012, 04:54 AM
  3. C Stock Sorting Program Issue
    By litebread in forum C Programming
    Replies: 18
    Last Post: 12-09-2011, 11:37 PM
  4. Stock Data
    By bskaer1 in forum C++ Programming
    Replies: 0
    Last Post: 10-16-2010, 11:59 PM
  5. Stock Taking program
    By C Babe in forum C++ Programming
    Replies: 3
    Last Post: 05-15-2003, 07:40 PM