Thread: Writing array, to file

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    First, on an array that has 3 as size, you quite obviously won't be able to use indices beyond three, so my_array[248] - that's going to access some other number.

    If you want to look up 248, then your array must be at least 249 in size [becuase elements are 0..248 -> 249 elements].

    But you can write a section at a time or the whole array to file using fwrite(), and read it back again with fread().

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  2. #2
    Registered User
    Join Date
    Aug 2007
    Posts
    4
    Thanks for the response, yes i'm aware you cannot put keys in larger than the array size, but obviously i don't want to have to make the array 248 length in size just to insert a value of 248 have the rest 247 values empty and wasting memory.

    I wrote my program using JUDY arrays (JUDYL), but I've found that at some point i'm going to have to store the values in them. I know i could do it by writing each Key=Value into a file then when they are needed read them each individually and insert them into a newly constructed Judy array/hash table then perform my lookups, but reading into a new structure is too slow.

    I need to know which data structure/if any binary tree/hash table/judy array/associative array could be modified to do this and if there any libraries that can do this already?
    Last edited by zootreeves; 09-07-2007 at 08:59 AM.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by zootreeves View Post
    Thanks for the response, yes i'm aware you cannot put keys in larger than the array size, but obviously i don't want to have to make the array 248 length in size just to insert a value of 248 have the rest 247 values empty and wasting memory.

    I wrote my program using JUDY arrays (JUDYL), but I've found that at some point i'm going to have to store the values in them. I know i could do it by writing each Key=Value into a file then when they are needed read them each individually and insert them into a newly constructed Judy array/hash table then perform my lookups, but reading into a new structure is too slow.

    I need to know which data structure/if any binary tree/hash table/judy array/associative array could be modified to do this and if there any libraries that can do this already?
    Aside from Salem's suggestion of using C++, there is really no way you can use indices that are beyond the limit of an array [sure you can use indices, but the effect of doing so is definitely undefined, and most likely will cause bad things with your application].

    What I would suggest is to use some sort of function to insert and retrieve data from your data-storage.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Aug 2007
    Posts
    4
    Thanks for your help, C++ isn't really an option since i can't seem to understand it for the life of me. But I've got it working with a hash table anyway. The too main things i found were.

    1. Realloc one pointer only and assign addresses within that space, this way you know it's contiguous and so can be written with fwrite by supplying only one pointer.
    2. The Values in the table should contain a pointer to the linked list which is relative to the address of the first pointer. So when you read it back from the file you can find them just by knowing the first address

    Sounds more complicated than it is i think. Here it is anyway in case someone of there is trying to to a similar thing

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/stat.h>
    #include "hashtable.h"
    
    typedef struct H* HashTable;
    HashTable createHashTable(unsigned int capacity);
    void addItem(HashTable table, int item, int value);
    int containsItem(HashTable table, int item);
    void destroyHashTable(HashTable table);
    
    struct Node;
    typedef struct Node* Link;
    
    struct Node {
        int item;
        int value;
        Link next;
    };
    
    
    struct H {
        Link* data;
        unsigned int capacity;
        unsigned int bytes;
    };
    
    /*
     * Allocates a new node to hold the given initial values, and
     * returns a pointer to that node.  Returns NULL if the node
     * could not be allocated.
     */
    Link newNode(int item, int value, Link next, HashTable table) {
        printf("New node Address of table &#37;d, bytes %d\n", table, table->bytes);
        table = realloc(table, table->bytes + sizeof(struct Node));
        int address = table;
        Link result = address + table->bytes; //calloc(1, sizeof(struct Node));
        int rel_address = table->bytes;
        printf("New node Address of link %d, bytes %d\n", result, table->bytes);
        printf("Relative adddress %d of item %d should make an address of %d\n", rel_address, item, address + rel_address);
        table->bytes = table->bytes + sizeof(struct Node);
    
        if (result == NULL) {
    	printf("Realloc failed\n"); 
           return NULL;
        }
    
        result->item = item;
        result->value = value;
    
        printf("Address of next %d\n", next);
        result->next = next;
        return rel_address;
    }
    
    /*
     * Creates a hashtable with the given capacity and hash function.
     * Returns a pointer to the newly created table, or NULL if the
     * table could not be created.
     */
    HashTable createHashTable(unsigned int capacity) {
        HashTable table = (HashTable)calloc(1, sizeof(struct H));
        table->bytes = sizeof(struct H);
        printf("Address of table %d, bytes %d\n", table, table->bytes);
        if (table == NULL) return NULL;
        table = (Link*)realloc(table, table->bytes + (sizeof(void *) * capacity));
        printf("Address of table after realloc %d, bytes %d\n", table, table->bytes);
        int address = table;
        printf("Predicted Address of table->data %d\n", address + table->bytes);
        table->data = address + table->bytes;
        printf("Address of table->data %d\n", table->data);
        table->bytes = table->bytes + (sizeof(void *) * capacity);
        if (table->data == NULL) return NULL;
        table->capacity = capacity;
        return table;
    }
    
    /*
     * Adds the given item to the table, unless the item is already in
     * the table, in which case it does nothing.
     */
    void addItem(HashTable table, int item, int value) {
        printf("Ok\n");
    
        /* Which bucket does the item hash to? */
        int index = item % table->capacity;
    
        /* Search the linked list - if already there, bail! */
        int rel_address = table->data[index];
        int address = table;
        printf("Table Address %d, Rel Address %d\n", address, rel_address);
        Link p = address + rel_address;
    
        int pnexta = rel_address;
        printf("Address of p->next %d\n", pnexta + address);
        while (pnexta != NULL) {
    	printf("Testing Rel address %d\n", pnexta);
            p = pnexta + address;
    	printf("%d == %d\n", p->item, item);
            if (p->item == item) {
    	    printf("Already in index\n");
                return;
            }
    	pnexta = p->next;
        }
    
        /* Didn't find it in the list - add it! */
        printf("Inserting %d into index\n", index);
        table->data[index] = newNode(item, value, table->data[index], table);
    }
    
    /*
     * Returns 1 (true) if item is in table, otherwise returns 0 (false).
     */
    int containsItem(HashTable table, int item) {
    
        /* Which bucket does the item hash to? */
        int index = item % table->capacity;
    
    
        int rel_address = table->data[index];
    
        printf("Relative address of lookup = %d\n", rel_address);
        int address = table;
        Link p = address + rel_address;
        printf("Real address of lookup = %d\n",  p);
    
        /* Search the linked list */
        int pnexta = rel_address;
        printf("Address of p->next %d\n", pnexta + address);
        while (pnexta != NULL) {
    	printf("Testing Rel address %d\n", pnexta);
            p = pnexta + address;
    	printf("%d == %d\n", p->item, item);
            if (p->item == item) {
    	    printf("Returning value %d\n", p->value);
                return p->value;
            }
    	pnexta = p->next;
        }
    
        /* Didn't find it in the list */
        return 0;
    }
    
    /*
     * Cleans up any memory allocated when we created the hashtable.
     */
    void destroyHashTable(HashTable table) {
    
        free(table);
    }
    
    
    int main () {
    
       HashTable table = createHashTable(100);
       addItem(table, 560, 34);
       addItem(table, 660, 12);
      // addItem(table, 570);
      // addItem(table, 550023);
    
     
        int bytes_to_read = table->bytes; //Cheat, should read table first to get the number of 
                                                           // bytes then read the rest, but i can't be bothered at the moment
    
        FILE * stream = NULL;
        if ((stream = fopen("./test", "wb+")) == NULL) {
          printf("Could not open file for writing\n");
          exit(1);
        } else {
          fwrite(table, table->bytes, 1, stream);
          fclose(stream);
        }
    
       destroyHashTable(table);
    
       /* Test reading it back */
    
        stream = NULL;
        if ((stream = fopen("./test", "rb+")) == NULL) {
          printf("Could not open file for reading\n");
          exit(1);
        } else {
          HashTable new_table = malloc(bytes_to_read);
          fread(new_table, bytes_to_read, 1, stream);
         
    	/*test search */
    	   int value = 0;
       	   if ((value = containsItem(new_table, 560)) != NULL) {
    	      printf("%d found\n", value);
               } else {
    	        printf("not found\n");
               }
          fclose(stream);
        }
    
    
    
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  2. Writing an array to a file.
    By Queatrix in forum C++ Programming
    Replies: 8
    Last Post: 04-24-2005, 01:41 PM
  3. writing data to a file from an array of pointers
    By Mingzhi in forum C++ Programming
    Replies: 1
    Last Post: 07-19-2004, 09:07 AM
  4. writing contents of array to file
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 06-26-2002, 04:06 PM
  5. File I/O problems!!! Help!!!
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 05-17-2002, 08:09 PM