Thread: How to Link Various Files

  1. #16
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Quote Originally Posted by MacGyver View Post
    fgets() and fgetc() are the way to read text.

    One way to read/write, is to read from the file, while making your changes to the strings you are reading. At the same time, write the new version to a new file. When you're done, close both files, delete the original, and rename the new one with the name of the original. There are other ways to possibly go about it, but this is a pretty simplistic approach.

    Dynamic structs.... I assume you mean dynamically sized arrays of structs, or something similar. It's the same concept as a dynamic array for ints or any other basic type.

    Well, thing is, I don't know how to pick it up,

    I have a xml file, I'll write part of it:

    Code:
    <pos>
    <company>Company X</company>
    <tax>1.21</tax>
    −
    	<suppliers>
    −
    	<supplier>
    <id>1</id>
    <name>BlaBla Lda.</name>
    <number>501031034</number>
    <suppliers>
    
    <clients>
    −
    	<client>
    <id>1</id>
    <name>John Doe</name>
    <number>124124124</number>
    </client>
    </clients>
    
    <products>
    −
    	<product>
    <ref>ABC9T</ref>
    <description>Monitor ABC 19</description>
    <cost>100.00</cost>
    <pvp>200.00</pvp> <!--With tax-->
    <amount>0</amount>
    </product>
    And so, on, it also has the Bills for the stuff that is bought, and then you print a receipt when it is paid.

    So, my question is..

    I can just go and do:

    Code:
    struct client {
    	char name[50+1]; /* I'm unsure whether to put the * pointer or not, since there is a mode in which you can create a new client */
            int id, number[9+1];
    	struct client *next;
    };
    
    typedef struct client CLIENT;
    And, how to insert the said client, how do I:
    1) Find the end of the the <clients>? With an fscanf, which will look for </clients> and write immediatly before? If so, how do I do "that".

    2) Write with the tags already?, Like, with a mention of a scanf, which will ask for the name, and the number, and then a fwrite, that will go like
    Code:
    fwrite 
    <client><name>%c</name>, client_name

  2. #17
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Yes, you have a few options.

    Beware of how fscanf() reads in strings. Do NOT use a plain &#37;s. This will cause issues, particularly with whitespace or a bad file. This is the easiest way to handle it if you can manage to read in the strings properly. The real issues comes up with newline chars, however. You can't be sure if your file will be formatted as either of the two:

    Code:
    <client>...</client>
    Code:
    <client>
    ...
    </client>
    You could try to make fscanf() figure it out, but you may waste a lot of time with it. If you have lots of spaces in your string values that you have to read, it might be better for you to just forget fscanf(). It all depends on the format of the file.

    Whatever you do, you should have a function to read a client from a given FILE *. Then a function to read all the clients by repeatedly calling the readclient() function you make. This type of function can be duplicated to read in products, or any other type. Then for every read function you come up with, write a corresponding write function to dump the data back to a FILE *.

    This is why I suggested an already written XML parsing library would be good to use. If you have to write your own, it's not impossible. One thing you could try is to read the entire file into memory, and then edit it that way. You could get quite complicated and fancy actually.

    Here's a general idea what you could do:

    1. fopen() the file in question and use fseek() and ftell() to get the file size.
    2. malloc() a buffer to hold the entire file. (Check to make sure this worked.)
    3. Read in the entire file repeatedly with either fgetc() or fgets() in a loop into the buffer that you just allocated.
    4. Learn how strstr() works. This will come in handy.
    5. To read in clients, you need to perform a strstr() on the buffer for "<clients>". If this succeeded, you know where the client section is.
    6. To find the ending, search for "</clients>". Now you're set. You have the starting and ending positions of the section of the string that corresponds to the clients.
    7. Either malloc() a new string and copy all of the client buffer over, or take heed not to bust over memory you don't have.
    8. Read in all the clients.
      1. For example, strstr() for "<client>".
      2. strstr() for "</client>".
      3. Now you have the starting and ending positions of the actual client section.
      4. You can continue to do this for the actual positions of the data in the file.
    9. Do the same for products and any other type of data.
    10. free() any malloc()'ed data.


    There are a bunch of ways of doing this, but this is just one way I thought of. Overall, using code already written for this would be ideal.
    Last edited by MacGyver; 12-30-2007 at 06:51 AM.

  3. #18
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Very well, I shall use your idea then, I will come back after lunch and some more frustrated tries!!

  4. #19
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Can I just use:

    Code:
    struct client { 
    	int id_client;
    	char name_client;
    	int cont_client;
    	struct client *next;
    };
    
    typedef struct clien CLIENT;
    And, in another function, that asks the user the Name and the Social Security Number:

    Code:
    void new_client(CLIENT **start)/* I don't know what pointer to use, and how to define a pointer to the start of the file would it be SEEK_SET?.. */ {
    	CLIENT *walker, *last, *new;
    	char name_client[100];
    	int cont_client, id_client, i=0;
    	last = NULL;
    	printf("Client's name > ");
    	while ((ch = getchar()) != '\n')
    		nome[i++] = ch;
    	name_client[i] = '\0';
    	printf("Client's Social Security Number >");
    	scanf("%d", cont_client);  /* I am highly unsure of this, I have no idea, if the numbers go the same way as characters */
    
    	clean_buffer(); /* a simple buffer clean up- {
    	while (getchar() != '\n');
    } My teacher told me to use it so, here goes */

    And would this be of any use?

    Code:
    		new = (CLIENT*) malloc(sizeof(CLIENT));
    		new->name_client = malloc(sizeof(char) * strlen(name_client));
    		strcpy(new->name_client, name_client);
    		new->cont_client = cont_client; 
    		new->next = NULL;
    		if (last == NULL) {
    			*elem = new;
    		} else {
    			last->next = new;
    		}
    	} 
    }
    Does that even make sense? And what if I want the other variable id_client, to start at 1, and then go up one value for each client that is added? Or, just read the number of clients and would be equal to number of clintes + 1?

  5. #20
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    In general, perhaps, yes, but your comments in the code seem to indicate you or your fellow team member(s) are very unsure about what you're doing.

  6. #21
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Quote Originally Posted by MacGyver View Post
    In general, perhaps, yes, but your comments in the code seem to indicate you or your fellow team member(s) are very unsure about what you're doing.

    Yep, mostly it's whats happening, I think that what I have written makes sense, but, I don't know if it will go well.

    And can I save the numbers to a vector string like that?

    And that cycle thing, to fit with the ID number, how do I set it up?

  7. #22
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Vector string? Cycle thing? Help me out. What exactly are you trying to do?

    If you're trying to convert numbers to strings or vice versa, yes, you can do that. No one form is necessarily more correct than another in a general setting.

  8. #23
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Quote Originally Posted by MacGyver View Post
    Vector string? Cycle thing? Help me out. What exactly are you trying to do?

    If you're trying to convert numbers to strings or vice versa, yes, you can do that. No one form is necessarily more correct than another in a general setting.


    Okay, so I can just.. scanf("%d", *save it to a vector here?*)

    And for the other doubt, it's the following,

    They want the customers to have a Company ID Number.

    So, imagine there's two customers.

    John Doe
    Social Sec. Number = 123456789
    ID Number = 1

    Michael Smith
    Social Sec. Number: 123123123
    ID Number = 2

    So, I want to add another client to the file.
    For that, I need the function to:
    Find where the last client is, by looking for </client>, and find the end of the file space it has </clients>, and create memory there.

    I suppose I can do that with a simepl malloc(),

    Now, my doubt is, the client's ID number is automatically given, so, if I was to add a new customer, I would only need to put the name and the social security number, and the ID Number would automatically be 3.

    So, how do I do that? Create a Cycle, that counts the number of clients, and gives the ID number to the next?

  9. #24
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    &#37;d means you're saving it as an integer. I wouldn't call it a vector, since that might be confused with the C++ std::vector or with a math vector.

    As far as creating clients..... You can't malloc() space in a file. malloc() deals only with memory, not hardrive space. This is why I recommended putting the entire file into memory. Once you edit memory, you just dump it all back to a file (with some of the fancy renaming I think I mentioned earlier), and you're done.

  10. #25
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Quote Originally Posted by MacGyver View Post
    As far as creating clients..... You can't malloc() space in a file. malloc() deals only with memory, not hardrive space. This is why I recommended putting the entire file into memory. Once you edit memory, you just dump it all back to a file (with some of the fancy renaming I think I mentioned earlier), and you're done.
    Okay, you told me to malloc() a Buffer, I'd guess tomorrow morning, I'll do some research on that.

    Supposedly, I would want to malloc() something bigger than the original file, that's why I would have ftell() to tell me how big it is, but, if I'm to write in it, the sie would be bigger, so, I can't just malloc() a huge quantity, and freely write in it, or.. loose spaces are dangerous?

  11. #26
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    One thing you could do is just have a linked list of clients, a linked list of products, etc. etc..

    You read in all of the clients into the client linked list. Then you just keep adding to that list as you create new clients. Then when you're going to write all the clients, you write that linked list to the file.

  12. #27
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Quote Originally Posted by MacGyver View Post
    One thing you could do is just have a linked list of clients, a linked list of products, etc. etc..

    You read in all of the clients into the client linked list. Then you just keep adding to that list as you create new clients. Then when you're going to write all the clients, you write that linked list to the file.
    Actually, I need to do that, it's using the struct, and the pointer to the next struct, the problem seems to be writing with the tags. Which I seem to have some troubles at.

  13. #28
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Well if you write a function to write one client to a file, that is easy. First you write "<client>" to a file, and then the tag for the variable you write next, etc. etc.. Do it one function at a time.

    Once you have that, you can write a function to write all clients to a file by starting with "<clients>" and then walking the linked list and calling the previous function to write every client to the file, and then ending with writing "</clients>".

  14. #29
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    Very well, the only thing I'm having trouble at, is the following, to be 100% sure of what to do:

    I wanted to know if I can, find the starting tag of <clients>, copy all the data to a list, up to </clients>.

    Then, the same function, but for the <products>, since I won't have more than one function of these running at a time, there is no trouble using malloc(), I'd suppose.

    Now, thing is, How can I be sure, that I'm altering the malloc()'ed data? I'd suppose, that creating a function simply for altering can solve it, without opening the initial database?

    Also, with the Lists, that take structs, and have all that pointer work, I can handle it for now, the current problem that now appeared, is to:

    1. After having creating new clients/changing the existent in that malloc()'ed space, how do I write that part in the original database.xml?

    2. Overwriting? How do I overwrite, without overwriting writing in places I do not want overwritten, or, rephrasing, how do I only write in the <clients> . . . </clients> part?

  15. #30
    Registered User
    Join Date
    Dec 2007
    Location
    Lisbon, Portugal
    Posts
    19
    I can't get it to work, I simply can't,

    It's starting to annoy me, I don't know how to read only the client database, I don't know how to write new info only inside the client database, I know nothing...Also, all of the clients need to be in a List, that is, I think it can be defined like this:

    Code:
    struct client{
               int client_id;
               char client_name[50+1];
               int client_social_number[9+1];
               struct client *next;
                        }
    That would be the code to make the structs point to each other, in a List, right?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Error opening files in a different dir
    By Ozzie in forum C++ Programming
    Replies: 3
    Last Post: 10-09-2008, 06:55 AM
  2. Program Deployment and DLL/OCX Files?
    By dfghjk in forum C++ Programming
    Replies: 5
    Last Post: 06-16-2008, 02:47 AM
  3. accessing all files in a folder.
    By pastitprogram in forum C++ Programming
    Replies: 15
    Last Post: 04-30-2008, 10:56 AM
  4. Help with loading files into rich text box
    By blueparukia in forum C# Programming
    Replies: 3
    Last Post: 10-19-2007, 12:59 AM
  5. reading from files
    By recluse in forum C Programming
    Replies: 25
    Last Post: 12-26-2004, 10:33 AM