Reputation: 788
I am trying to allocate memory for the content of a file with words(separated by: \n).
How do I replace the 16000 to make it usable with files of greater size?
My code:
typedef struct node {
bool is_word;
struct node* children[27];
} node;
node* root;
bool load(const char* dictionary)
{
FILE *fp;
fp = fopen(dictionary, "rb");
node* node_bucket = calloc(16000, sizeof(node));
node* next_free_node = node_bucket;
// compute...
// to later free the memory with another function
root = node_bucket;
}
Thanks
Upvotes: 2
Views: 72
Reputation: 16107
The simplest approach to get the size of a file is using ftell()
:
fseek(fp, 0, SEEK_END); // non-portable
long size = ftell(fp);
However, as the comment says, this is not portable, because N1570 documents in "7.21.9.2 The seek function":
2 ...... A binary stream need not meaningfully support fseek calls with a whence value of SEEK_END.
Alternatively, you can write a function to get the size of a file on your own:
size_t fSize(FILE *fp)
{
void *ptr = malloc(1);
size_t size = 0;
while(fread(ptr, 1, 1, fp) == 1)
size++;
if(feof(fp))
return size;
else
return 0; // reading error
}
An accuracy-efficiency trade-off:
size_t fRoughSize(FILE *fp)
{
void *ptr = malloc(1024);
size_t size = 0;
while(fread(ptr, 1024, 1, fp) == 1024)
size += 1024;
if(feof(fp))
return size;
else
return 0; // reading error
}
Upvotes: 1
Reputation: 34585
You can allocate memory dynamically without knowing how large the file is. I used a block size that is a power of 2, which is generally kinder towards block I/O. It wastes a little when the last block is only partially used, but here is an example, which you could adapt to work with your node structs:
#include <stdio.h>
#include <stdlib.h>
#define BLOCKSIZE 16384
int main(void) {
unsigned char *buf = NULL;
unsigned char *tmp = NULL;
size_t totalread = 0;
size_t currentsize = 0;
size_t currentread = 0;
FILE *fp;
if((fp = fopen("test.txt", "rb")) == NULL)
exit(1);
do {
currentsize += BLOCKSIZE;
if((tmp = realloc(buf, currentsize)) == NULL)
exit(1);
buf = tmp;
currentread = fread( &buf[totalread], 1, BLOCKSIZE, fp);
totalread += currentread;
} while (currentread == BLOCKSIZE);
printf("Total size was %zu\n", totalread);
free(buf);
fclose(fp);
return 0;
}
Upvotes: 2