Thread: Inventory System

  1. #16
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by headshot119 View Post
    I did compile it but I got some errors.

    WHAT?!! Yeah, sorry, originally "database" was just called array, then I changed the name but left one instance of array in the post by accident.

    So I've fixed that/edited the post. It compiles without error for me, gcc -Wall -pedantic.

    Code:
    	for (i=0; i<Total; i++) show(array[i]);
    Whoops!

    strncpy() maybe an issue for some compilers, I dunno. The reason I used that instead of strcpy() was as a primitive form of "input validation", which is important in database programming.
    Last edited by MK27; 09-23-2009 at 02:59 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #17
    Registered User
    Join Date
    Aug 2009
    Posts
    31
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp||In function `record** create(char*, record**)':|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|14|error: invalid conversion from `void*' to `record*'|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|15|error: invalid conversion from `void*' to `record**'|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp||In function `int main()':|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|32|error: `array' was not declared in this scope|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|32|warning: unused variable 'array'|
    ||=== Build finished: 3 errors, 1 warnings ===|

    Still got errors, even with the new code. Or is my compiler being funny?

  3. #18
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Talking

    Quote Originally Posted by headshot119 View Post
    Or is my compiler being funny?
    Yes, it is. I would guess that is because you are compiling it as C++? I don't use VS, or C++, but if something passes gcc -Wall -pedantic it is standard compliant C, and then some.

    Also, "error: invalid conversion from `void*" is not a C error, methinks. In fact, a void pointer in C automatically converts to the appropriate type, according to the lvalue, in this case:
    Code:
    struct record *ptr = malloc(sizeof(struct record));
    malloc returns a void*. This will be a problem in C++; it is not in C.

    Those last two lines still refer to "array", which there is no "array" in the code from post #14 anymore.

    Hopefully one of the other regulars who know C++ can confirm this, and hopefully they can also explain how to use VS for you...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #19
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by headshot119 View Post
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp||In function `record** create(char*, record**)':|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|14|error: invalid conversion from `void*' to `record*'|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|15|error: invalid conversion from `void*' to `record**'|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp||In function `int main()':|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|32|error: `array' was not declared in this scope|
    C:\Documents and Settings\Karl\Desktop\C++\Projects\database\main.c pp|32|warning: unused variable 'array'|
    ||=== Build finished: 3 errors, 1 warnings ===|

    Still got errors, even with the new code. Or is my compiler being funny?
    So C files don't end with .cpp. If you're using C++ you would probably use new instead of malloc; if you're using C, then you use .c (and if you're using MSVS then it will automatically notice that it's a C file and use the C compiler instead).

  5. #20
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Code:
    ptr->data[64] = '\0';
    This is overwriting the array, and will probably cause a crash. A much safer way of doing this is:
    Code:
    ptr->data[sizeof(prt->data)-1] = '\0';
    bit∙hub [bit-huhb] n. A source and destination for information.

  6. #21
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by bithub View Post
    Code:
    ptr->data[64] = '\0';
    This is overwriting the array, and will probably cause a crash. A much safer way of doing this is:
    Code:
    ptr->data[sizeof(prt->data)-1] = '\0';
    Yeah check that...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #22
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Looking at it further, I'm not really a big fan of the double pointer design. It makes the code unintuitive (in my opinion). I would rather use the approach of keeping the records stored in a separate database structure. I think it makes the design a bit cleaner (although opinions may vary).

    Here is an example of what I mean. Note that this is based on MK27's code, and also I didn't do any checking to see if malloc() or realloc() failed (to keep the code as clean as possible).
    Code:
    #include <stdio.h>
    #include <stdlib.h> /* malloc, realloc, free */
    #include <string.h>
    
    #define DATA_SIZE 64
    struct record {
        int ID; 
        char data[DATA_SIZE];
    };
    
    struct database {
        struct record* records;
        unsigned int num_records;
    };
    
    struct database* create_database(void) {
        struct database* db = malloc(sizeof(*db));
        db->records = NULL;
        db->num_records = 0;
        return db; 
    }
    
    void free_database(struct database* db) {
        if(db)
        {   
            if(db->records)
                free(db->records);
            free(db);
        }   
    }
    
    int add_record(const char* data_string, struct database* db) {
        static int id = 0;
        db->records = realloc(db->records, sizeof(struct record) * (db->num_records+1));
        if(strlen(data_string) >= DATA_SIZE)
            return -1; /* Error, data too big */
        db->records[db->num_records].ID = ++id;
        strcpy(db->records[db->num_records++].data, data_string);
    
        return 0;  
    }
    
    void show (struct record *ptr) {
        printf("ID: %d Data: %s\n",ptr->ID,ptr->data);
    }
    
    int main() {
        unsigned int i;
        struct database* db = create_database();
        add_record("first record", db);
        add_record("second record", db);
        for (i=0; i<db->num_records; i++) 
            show(&db->records[i]);
        free_database(db);
        return 0;
    }
    bit∙hub [bit-huhb] n. A source and destination for information.

  8. #23
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by bithub View Post
    Looking at it further, I'm not really a big fan of the double pointer design. It makes the code unintuitive (in my opinion). I would rather use the approach of keeping the records stored in a separate database structure. I think it makes the design a bit cleaner (although opinions may vary).
    There are definitely more than a few ways to skin this cat. Really, using a global array of predefined size would be fine, and in fact, that might be the best idea since there will only be one database and this will hardly make the program somehow "unmanageable"; the central conceit is the db, making it a global object makes sense.

    But I think it is important to understand and feel comfortable with double pointers ASAP, esp. with something like this, which is partially why I brought that in. Being able to do something in many specific ways may be better than having many ways of avoiding one specific method. I dunno if I agree using the outer container (struct database) is less confusing or more intuitive, but I do agree being able to conceive of many alternative methods is essential.

    Pointer arrays are common and useful. A dynamic pointer array is a often a double pointer, so they cannot be totally written off.

    @headshot119: notice bithub uses free(). This is not really necessary here, since the OS will do that at the end anyway, but it is a good illustration of the principle.
    Last edited by MK27; 09-23-2009 at 04:55 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #24
    Registered User
    Join Date
    Aug 2009
    Posts
    31
    Program compiles now . I even managed to add a third record!!!!! I understand a lot more of the code now I've seen it in action.

    Unfortunately I am more used to C++ functions, such as cin and cout and other functions of #iostream.

    Is there any way to quickly convert this program to C++?

    Then I can mess around with user input into records.

  10. #25
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by headshot119 View Post
    Unfortunately I am more used to C++ functions, such as cin and cout and other functions of #iostream.

    Is there any way to quickly convert this program to C++?
    Not by me there isn't

    Seriously, tho, you should decide whether you are learning C or C++, it probably is not so good to mix and match as you go. For example, I think it might be better to take a very different approach here in C++ and make record and database classes. Not that that is so substantially different, but if you are going to use C++, you might as well learn how and do it right, rather than mixing the syntax based on what you know of each one.

    Then I can mess around with user input into records.
    Conversely, if you are going to use C, you might as well learn how -- for user input, scanf() or fgets(). In the demo, create() could be adjusted to take user input, but presuming the database is going to be stored in a file, and you will also want to read from the file, I would go with two separate small functions: one which gets data from a file and feeds it to create(), and one which takes user input and feeds it to create().
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #26
    Registered User
    Join Date
    Aug 2009
    Posts
    31
    My last program was built in C++, but I'd rather learn C, I'll do some reading up on user inputs in C. But I basically understand the program, so I'll see if I can knock up the bit to read and write to a file.

    One thing I'm not sure off, is how multiple parts of the record are kept on one line a file, I assume I need to read the spaces between the words, or something similar?

    EDIT, what are the equivalent functions in C to C++'s Cout and Cin?
    Last edited by headshot119; 09-24-2009 at 09:49 AM.

  12. #27
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by headshot119 View Post
    One thing I'm not sure off, is how multiple parts of the record are kept on one line a file, I assume I need to read the spaces between the words, or something similar?
    That depends how you want to parse it. Using a single line is a good idea, because the is only one '\n' in a line, and it is at the end. Also, if you use fgets(), fgets works by the line.

    If possible, pick a character that will not be used in any of the data, and use that as a field seperator. Or you could use an extend ascii character like 129, aka �
    Code:
    doohickey�orange�large�123-X-a57
    So you use 129 as the separator for strtok, or just use pointers and strchr for 129. Then change each seperator to a '\0', move the pointer forward one and voila, you have some pointers to now separate strings contained in the line retrieved with fgets().

    Just whatever your separator is, make sure you validate your input to make sure it does not contain that character, accidentally or otherwise
    Last edited by MK27; 09-24-2009 at 10:02 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #28
    Registered User
    Join Date
    Aug 2009
    Posts
    31
    Right this is the program so far.

    Code:
    #include <stdio.h>
    #include <stdlib.h> /* malloc, realloc, free */
    #include <string.h>
    
    struct record {
    	int ID;
    	char data[64];
    };
    
    int Total = 0;
    
    struct record **create (char *string, struct record **rp) {
    	static int id = 1;
    	struct record *ptr = malloc(sizeof(struct record));
    	rp = realloc(rp,(Total+1)*sizeof(struct record*));
    	ptr->ID = id++;
    	strncpy(ptr->data,string,63);
    	ptr->data[63] = '\0';
    	rp[Total++] = ptr;
    	return rp;
    }
    
    void show (struct record *ptr) {
    	printf("ID: %d Data: %s\n",ptr->ID,ptr->data);
    }
    
    int main() {
    	int i, menu;
    
    
    	//Opens the database file inventory.txt, or creates it if it does not exist.
        FILE *f;
        f = fopen("inventory.txt","w+");
    
    	//Prints a message
    	printf("Welcome to the inventory system \nWhat would you like to do? \nRead the database (1) Write to the database (2)?\n");
        scanf("%d", &menu);
    
        if (menu == 1){
    
    
    	//Displays the database as ID: Data:
    	struct record **database = NULL;
    	database=create("first record",database);
    	database=create("second record",database);
    	for (i=0; i<Total; i++) show(database[i]);
    	return 0;
        }
    
        if (menu == 2){
    
        printf("You have chosen to write to the database!");
    	return 0;
        }
    
    }
    Which basically now opens or creates the text file "inventory" and also provides a simple menu for the user.

    I'm now stuck on adding records to the database, as I'm not sure what this means.

    Code:
    database=create("first record",database);
    Is create a function? Any example off how I could get the user input then write it to a new line on a text file?

  14. #29
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by headshot119 View Post
    I'm now stuck on adding records to the database, as I'm not sure what this means.
    Yep, thats the call to the function struct record **create (char *string, struct record **rp).

    I would hold off on cluttering up your code with the UI menu at this point.

    Here's something to consider: you probably want to load the database into memory at start. Then, when a record is added, ALSO add a line to the file, so that the file and the db in memory match. So before you get going on the menu, create a fake db file and try to load that into your program's database, then output the contents to make sure it is correct. THEN you can add a function that will take user input, create a new record, and write that record to the file for posterity.

    IMO, the UI menu is the simplest part; it is easy to add to and modify as you go along. You do not need to create the whole thing, etc, etc, at this point.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. inventory system
    By linucksrox in forum Game Programming
    Replies: 0
    Last Post: 04-19-2006, 01:19 PM
  2. measuring system resources used by a function
    By Aran in forum C Programming
    Replies: 1
    Last Post: 03-13-2006, 05:35 PM
  3. BIOS system and memory allocation problem
    By beely in forum Tech Board
    Replies: 9
    Last Post: 11-25-2003, 07:12 AM
  4. Thoughts on Menu System for Book Inventory
    By curlious in forum C++ Programming
    Replies: 3
    Last Post: 09-29-2003, 03:32 AM
  5. need help with an inventory program
    By lackerson191 in forum C++ Programming
    Replies: 3
    Last Post: 09-10-2001, 09:32 PM