C file Fwrite and fread struct pointers - c

The program only works for the first time. What was supposed to happen the second time was to add the same data to the binary file but that doesn't happen.
First run: It runs normal and it shows that it writed to the file.
Secound run: It writes to the file but doesnt read.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name, *role, *course;
int year, id;
} StudentFile;
void saveBin(StudentFile *studentsFile, int lines){
FILE *file = fopen("studentsx.bin","ab");
if (!file) {
printf("\n\n\tImposible to open file. \n\n");
exit(1);
}
for (int i = 0; i < lines; i++){
fwrite(&studentsFile[i], sizeof(StudentFile), 1, file);
}
fclose(file);
}
void readBin(){
StudentFile *studentsFile = malloc(sizeof(StudentFile)*5000);
FILE *file = fopen("studentsx.bin","rb");
if (!file) {
printf("\n\n\tImposible to open file. \n\n");
exit(1);
}
int j = 0;
while (fread(&studentsFile[j], sizeof(StudentFile), 1, file)){
printf("\nLine read %d: %s\t%s\t%d\t%d\t%s", j+1, studentsFile[j].name, studentsFile[j].role, studentsFile[j].year, studentsFile[j].id, studentsFile[j].course);
j++;
}
fclose(file);
}
void main(){
StudentFile *studentsFile = malloc(sizeof(StudentFile)*2);
int lines = 0;
studentsFile[0].name = "John";
studentsFile[0].role = "Gamer";
studentsFile[0].year = 1999;
studentsFile[0].id = 1;
studentsFile[0].course = "IOT";
studentsFile[1].name = "Piter";
studentsFile[1].role = "GamerXL";
studentsFile[1].year = 1991;
studentsFile[1].id = 2;
studentsFile[1].course = "IOTXL";
lines = 2;
saveBin(studentsFile, lines);
readBin();
}

You are writing pointers, not strings. fwrite writes single contiguous array of memory. In your case the StudentFiles and actual strings are scattered all over the static memory and heap memory.
Consider your struct:
typedef struct {
char *name, *role, *course;
int year, id;
} StudentFile;
it looks something like this in memory:
[<pointer to name><pointer to role><pointer to course><year><id>]
somewhere else in a different block of memory:
[John\0Gamer\0\OIT\o.......]
You wrote the first block above and left out the second one.
There are multiple approaches to this problem and we usually name them "serialization" - take your complex data structure and serialize it into a linear file.
One of the approaches is to allocate fixed size block within your structure StudentFile:
#define MAX_NAME 100
#define MAX_ROLE 100
#define MAX_COURSE 100
typedef struct {
char name[MAX_NAME];
char role[MAX_ROLE];
char course[MAX_COURSE];
int year, id;
} StudentFile;
then strings name, role and course will be inside of StudentFile:
[<100 bytes for name><100 bytes for role><100 bytes for course><year><id>]
this is contiguous block of memory and if can be written using single call to fwrite like you did.
But you won't be able to assign strings like you did with
studentsFile[i].name = "John";
C has strncpy for that:
strcpy(studentsFile[0].name, "John", MAX_NAME);
Another approach is to have several calls to fwrite. For every string, you write length first, then the string itself. For primitive types like int you just write that int.
First you gather strings from different locations pointed by the pointers:
size_t nameLen = strlen(studentsFile[i].name) + 1;/* +1 for the final zero*/
fwrite(&nameLen, sizeof(size_t), 1, file);
fwrite(studentsFile[i].name, nameLen, 1, file);
size_t roleLen = strlen(studentsFile[i].role) + 1;
fwrite(&roleLen, sizeof(size_t), 1, file);
fwrite(studentsFile[i].role, roleLen, 1, file);
size_t courseLen = strlen(studentsFile[i].course) + 1;
fwrite(&courseLen, sizeof(size_t), 1, file);
fwrite(studentsFile[i].course, courseLen, 1, file);
Then you write primitive types:
fwrite(&studentsFile[i].year, sizeof(int), 1, file);
fwrite(&studentsFile[i].id, sizeof(int), 1, file);
Next time when you read the file, you rely on the order of writes and read the fields back in the same order:
size_t nameLen;
fread(&nameLen, sizeof(size_t), 1, file);
char *name = malloc(nameLen);
fread(name, nameLen, 1, file);
size_t roleLen;
fread(&roleLen, sizeof(size_t), 1, file);
char *role = malloc(roleLen);
fread(role, roleLen, 1, file);
size_t courseLen;
fread(&courseLen, sizeof(size_t), 1, file);
char *course = malloc(courseLen);
fread(course, courseLen, 1, file);
int year;
fread(&year, sizeof(int), 1, file);
int id;
fread(&id, sizeof(int), 1, file);
printf("\nLine read %d: %s\t%s\t%d\t%d\t%s", j+1, name, role, year, id, course);

The problem lies somewhere else: Think carefully, what is your code doing with fwrite() here?
typedef struct {
char *name, *role, *course;
int year, id;
} StudentFile;
fwrite(&studentsFile[i], sizeof(StudentFile), 1, file);
What does the file content look like after writing a single element from studentFile?
Three strings and two integers (in their binary form)
Three pointers to somewhere and two integers (all in their binary forms)

Related

Declaring char variable breaks program

I am exploring .tga files.
I have fully working code that looks like this:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
const int letterHeight = 34;
const int spacer = 5;
typedef struct{
uint8_t idlength;
uint8_t colourmaptype;
uint8_t datatypecode;
uint16_t colourmaporigin;
uint16_t colourmaplength;
uint8_t colourmapdepth;
uint16_t x_origin;
uint16_t y_origin;
uint16_t width;
uint16_t height;
uint8_t bitsperpixel;
uint8_t imagedescriptor;
} TGA_Header;
typedef struct
{
uint8_t B;
uint8_t G;
uint8_t R;
} Pixel;
typedef struct{
TGA_Header header;
Pixel* pixels;
int width;
int height;
} Image;
void readHeader(TGA_Header* header, FILE* input_F){
fread(&header->idlength, sizeof(header->idlength), 1, input_F);
fread(&header->colourmaptype, sizeof(header->colourmaptype), 1, input_F);
fread(&header->datatypecode, sizeof(header->datatypecode), 1, input_F);
fread(&header->colourmaporigin, sizeof(header->colourmaporigin), 1, input_F);
fread(&header->colourmaplength, sizeof(header->colourmaplength), 1, input_F);
fread(&header->colourmapdepth, sizeof(header->colourmapdepth), 1, input_F);
fread(&header->x_origin, sizeof(header->x_origin), 1, input_F);
fread(&header->y_origin, sizeof(header->y_origin), 1, input_F);
fread(&header->width, sizeof(header->width), 1, input_F);
fread(&header->height, sizeof(header->height), 1, input_F);
fread(&header->bitsperpixel, sizeof(header->bitsperpixel), 1, input_F);
fread(&header->imagedescriptor, sizeof(header->imagedescriptor), 1, input_F);
}
void writeHeader(TGA_Header* header, FILE* output_F){
fwrite(&header->idlength, sizeof(header->idlength), 1, output_F);
fwrite(&header->colourmaptype, sizeof(header->colourmaptype), 1, output_F);
fwrite(&header->datatypecode, sizeof(header->datatypecode), 1, output_F);
fwrite(&header->colourmaporigin, sizeof(header->colourmaporigin), 1, output_F);
fwrite(&header->colourmaplength, sizeof(header->colourmaplength), 1, output_F);
fwrite(&header->colourmapdepth, sizeof(header->colourmapdepth), 1, output_F);
fwrite(&header->x_origin, sizeof(header->x_origin), 1, output_F);
fwrite(&header->y_origin, sizeof(header->y_origin), 1, output_F);
fwrite(&header->width, sizeof(header->width), 1, output_F);
fwrite(&header->height, sizeof(header->height), 1, output_F);
fwrite(&header->bitsperpixel, sizeof(header->bitsperpixel), 1, output_F);
fwrite(&header->imagedescriptor, sizeof(header->imagedescriptor), 1, output_F);
}
void image_load(Image* image, const char* path){
FILE* input_F = fopen(path, "rb");
readHeader(&image->header, input_F);
image->width = image->header.width;
image->height = image->header.height;
image->pixels = (Pixel*) malloc(sizeof(Pixel) * image->header.width * image->header.height);
fread(image->pixels, sizeof(Pixel), image->header.width * image->header.height, input_F);
fclose(input_F);
}
void image_create(Image* image, const char* path){
FILE* output_F = fopen(path, "wb");
writeHeader(&image->header, output_F);
fwrite(image->pixels, sizeof(Pixel), image->header.width * image->header.height, output_F);
fclose(output_F);
}
void load_letters(Image (*letters)[26], const char* f){
char path[101];
for(int i=0; i<26; i++){
strcpy(path, f);
strcat(path, "/");
char c[2] = {(char)(65+i), '\0'};
strcat(path, c);
strcat(path, ".tga\0");
image_load(&(*letters)[i], &path[0]);
}
}
void drawLetter(Image* image, Image* letter, int X, int Y){
Y += letterHeight - letter->height;
int letter_y = letter->height;
int letter_x = letter->width;
int image_x = image->width;
for(int y=0; y<letter_y; y++){
for(int x=0; x<letter_x; x++){
if(letter->pixels[y*letter_x+x].R != (uint8_t)0 || letter->pixels[y*letter_x+x].G != (uint8_t)0 || letter->pixels[y*letter_x+x].B != (uint8_t)0){
image->pixels[(y+Y)*image_x+(x+X)] = letter->pixels[y*letter_x+x];
}
}
}
}
void drawString(Image* image, Image (*letters)[26], char (*text)[101], int Y){
int dejToSzajzym = 0;
for(int i=0; i<strlen((*text)); i++){
dejToSzajzym += (*letters)[(int)(*text)[i] - 65].width;
}
dejToSzajzym = dejToSzajzym/2;
dejToSzajzym = image->width/2 - dejToSzajzym;
for(int i=0; i<strlen(*text); i++){
if((*text)[i] != ' '){
drawLetter(image, &(*letters)[(int)(*text)[i] - 65], dejToSzajzym, Y);
dejToSzajzym += (*letters)[(int)(*text)[i] - 65].width;
}else{
dejToSzajzym += 10;
}
}
}
int main(int argc, char* argv[]){
Image* image;
Image letters[26];
image_load(image, "img1.tga");
load_letters(&letters, "font");
/*
char buffer[100];
*/
drawString(image, &letters, "LOL", 5);
image_create(image, "image.tga");
free(image->pixels);
image->pixels = NULL;
for(int i=0; i<26; i++){
free(letters[i].pixels);
letters[i].pixels = NULL;
}
return 0;
}
But when I write the declaration of buffer as shown (could be anywhere in main) the program immediately breaks.
It doesn´t even need to do anything.
error:
Unable to open 'memmove-vec-unaligned-erms.S': Unable to read file '/build/glibc-YYA7BZ/glibc-
2.31/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S'
(Error: Unable to resolve non-existing file '/build/glibc-YYA7BZ/glibc-2.31/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S').
BTW: Isn't there any easier way to copy the header data?
As noted by Retired Ninja in their comment, your primary problem is that Image *image; doesn't initialize image to point anywhere in particular. You pass the uninitialized pointer to image_load(), which then scribbles on memory — and you've no idea where. This is all undefined behaviour. Adding the variable buffer moves something around and changes the behaviour, but it is still undefined — anything goes and any (mis-)behaviour is valid, especially crashes. You must fix that! One way would be to change the definition to Image image; and pass &image to image_load() and the other functions that expect an Image *.
BTW: Isn't there any easier way to copy the header data?
Yes, there is, and there are a couple of ways to do it. The fundamental observation is that you could write the header with fwrite(header, sizeof(*header), 1, fp), and read it with fread(header, sizeof(*header), 1, fp).
However, with the data structure as currently defined, there is some padding in the structure — one byte after datatypecode and another after colourmapdepth. If you moved colourmapdepth after datatypecode (or anywhere near the start of the structure before the first uint16_t member), you'd save two bytes in memory and have no padding bytes on disk. OTOH, there's not a lot of harm in the padding bytes being read/written. It isn't clear to me whether you're dealing with an externally imposed header structure or whether you're free to modify it.
The best way to avoid padding in a structure is to put the most stringently aligned types at the start of the structure (uint16_t is more stringently aligned than uint8_t) and less stringently aligned types at the end. That normally avoids holes in the structure. There can still be padding at the end of the structure even so.
The compiler is attempting to call memmove and can't find it because you're running with no libraries.
Assuming you're doing what I think you're doing, the best way is to provide it. In another file, declare memmove like so.
void *memmove(void *sm, const void *tm, size_t n)
{
char *s = (char *)sm;
const char *t = (const char *)tm;
if (s > t) {
s += n;
t += n;
while (n--)
*--s = *--t;
} else {
while (n--)
*s++ = *t++;
}
return sm;
}
You may have to fiddle with the declaration to get the compiler to accept it.
Note that this is not the best possible memmove, it's the simplest. If it's too slow, write or obtain a faster one.

Loop through the file and read all records

I've got a file with multiple records. Each record contains a type(a binary value number), len(bin value again), and data(binary value whose length is len). The file contains multiple records. I want to print every record which contains it's own type, len, and data.
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
typedef struct file_s {
int16_t type;
int32_t length;
// Assumption: Each record is 16 bits
// For a record size of 32 bits, use int32_t*
int16_t* data;
} file_s;
int main() {
file_s file;
FILE* f = fopen("file.bin","r");
if (f == NULL) {
perror("Error");
return 1;
}
fread(&file.type, sizeof(file.type), 1, f);
fread(&file.length, sizeof(file.length), 1, f);
file.data = malloc(file.length * sizeof(*file.data));
fread(file.data, sizeof(*file.data), file.length, f);
fclose(f);
// Process the data
/* ... */
free(file.data);
return 0;
}
How do I loop through the file and print each record.
The idea is to check the return value of fread every time, if the return value is smaller than expect, then check feof() to see if the end of the file reached. You can check the man page, by google "man fread" and "man feof". You can use a do while loop to loop through the file.
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
int feof(FILE *stream);
something like:
while(1) {
size_read = fread(&file.type, sizeof(file.type), 1, f);
if(size_read!=1 || feof(f))
break;
fread(&file.length, sizeof(file.length), 1, f);
//do the same check
file.data = malloc(file.length * sizeof(*file.data));
fread(file.data, sizeof(*file.data), file.length, f);
//do the same check, remember to free the memory!
}

Sigsegv in malloc

I want to save a struct containing a pointer that I use as a dynamic array but when I load the struct and malloc this pointer, it fails.
I have three structs (Orientation, ShipType, Status and PlayerType are enumerations, you can replace them by Int) :
struct Map
{
int width, height;
int* cases;
};
typedef struct Map Map;
struct Ship
{
int x, y, length, firstShoot, color;
int hasBeenDiscovered;
Orientation orientation;
ShipType type;
Status status;
};
typedef struct Ship Ship;
struct Player
{
int activeShips;
Map map[2];
char lastMoves[5][128];
Ship ships[10];
PlayerType type;
int shipcolor[4];
int color;
};
typedef struct Player Player;
I declare an array of 2 Player like this : Player players[2]; and initialize their properties. Then I want to save the struct in a file in order to load it afterwards.
Also, I use the Map struct as a 2d dynamic array using four functions :
void mallocMap(Map* map, int width, int height)
{
map->cases = malloc(sizeof(int) * width * height);
map->width = width;
map->height = height;
if (map->cases == NULL)
{
printf("Erreur d'allocation de memoire\n");
exit(0);
}
}
void freeMap(Map* map)
{
free(map->cases);
}
int getMapValue(Map map, int x, int y)
{
return *(map.cases + y*map.width + x);
}
void setMapValue(Map* map, int value, int x, int y)
{
*(map->cases + y*map->width + x) = value;
}
So when I store the struct, map.cases is only a pointer and I need to store the values at its address separately like so :
int save(Player players[2])
{
int* i;
FILE* file = NULL;
file = fopen("save.txt","w+");
if (file != NULL)
{
fwrite(players, sizeof(Player), 2, file);
fwrite(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fwrite(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fwrite(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fwrite(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
}
else
{
// error
}
fclose(file);
return 1;
}
Each player has 2 maps so there are 4 maps to store at the end.
The problem is in my load() function :
int load(Player players[2])
{
FILE* file = NULL;
file = fopen("save.txt","r");
if (file != NULL)
{
int *i;
fread(players, sizeof(Player), 2, file);
mallocMap(&players[0].map[0], players[0].map[0].width, players[0].map[0].height);
mallocMap(&players[0].map[1], players[0].map[1].width, players[0].map[1].height);
mallocMap(&players[1].map[0], players[1].map[0].width, players[1].map[0].height);
mallocMap(&players[1].map[1], players[1].map[1].width, players[1].map[1].height);
fread(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fread(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fread(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fread(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
}
else
{
// error
}
fclose(file);
return 1;
}
When I call mapAlloc(), it fails to allocate the memory and exit(0); my program stops.
The way you've declared your load function doesn't look right:
int load(Player* players[2])
This takes an array of pointers to Player, while your save routine takes an array of Player (i.e. Player players[2]). You probably need to change it to:
int load(Player players[2])
You're also reading the values back in to the wrong address:
for(i = players[0]->map[0].cases; i < players[0]->map[0].cases + players[0]->map[0].width * players[0]->map[0].height; i++)
fread(&i, sizeof(int), 1, file);
You're passing to fread the address of i. That means you're reading in an int and storing it in i, which is a local int * and not the dynamically allocated array you want to write to.
Remove the address-of operator here and pass in i directly, just like you do when you use fwrite
fread(i, sizeof(int), 1, file);
This will write the int that you read in into your array.
Also, there is no need to use loops to read / write individual ints here. Just do a single read / write passing in the number of values to read/write.
So saving would be:
fwrite(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fwrite(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fwrite(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fwrite(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
And loading would be:
fread(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fread(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fread(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fread(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
When compiling your code, there shouldn't be any warnings. If there are any, you're probably doing something wrong that you need to fix.

Dynamic array inside struct and malloc fail

Consider the following abstracted code that reads some bytes from a file:
typedef struct A{
int size;
char * dataArray;
}A
A load(char* filename, int inSize)
{
A newA;
newA.size = inSize;
FILE *filePtr;
filePtr = fopen(filename,"rb");
char buff[1];
int i = 0;
newA.dataArray = ( char*)malloc(sizeof(char) * newA.size);
for (i = 0; i < newA.size; i++)
{
fread(buff, sizeof(char), 1, filePtr);
newA.dataArray[i] = buff[0];
}
char* copyOfDataArray = (char*)malloc(sizeof(char) * newA.size);
for (i = 0; i < newA.size; i++)
{
fread(buff, sizeof(char), 1, filePtr);
copyOfDataArray[i] = newA.dataArray[i];
}
newA.dataArray = copyOfDataArray;
return newA
}
void Initialize()
{
A first = load("file1", 100);
A second = load("file2", 20);
}
Both calls to function load return the expected result (data array has the same bytes as the file). Variables first and second are never used again.
However after a couple of hundreds lines of code the program always crashes with:
*malloc.c:2451: sYSMALLOC: Assertion '(old_top == (..... failed.*
The crash always occurs on the same line of code, but that line has nothing to do with variables first, second or even with struct A whatsoever.
My question is: is my way of instancing and loading 'first' and 'second' wrong? Can it cause some kind of memory leak / memory overflow that crashes the program long after the load function has finished?
Bonus: The crash does not occur if I only load "file1", as soon as i load both "file1" and "file2" the crash reappears.
Sorry for the long question.
You have memory leaks there. You have to free the previously allocated memory in newA.dataArray, before you assign there a new memory.
As stated by Joachim, read operation is very time consuming and you shall read data in blocks to minimize overhead.
Additionally, you have to close file descriptors, otherwise they will be depleted soon.
There are many issue on the code as already given by others.
Please checks bellow
typedef struct A{
int size;
char * dataArray;
}A
A load(char* filename, int inSize)
{
A newA;
newA.size = inSize;
FILE *filePtr = NULL ; //Use NULL
char buff[1]; //Size of buffer is only 1 ,If needed increase that to copy more at a time
int i = 0;
filePtr = fopen(filename,"rb");
//Try to check for the filePtr == NULL or not
newA.dataArray = ( char*)malloc(sizeof(char) * newA.size);
//Same checking should be done here
for (i = 0; i < size; i++) //What is size
{
fread(buff, sizeof(char), 1, filePtr);
newA.dataArray[i] = char[0]; //What is char[0]
}
//instead this you can read the bytes in a single call, use that.
// fread(buff, sizeof(char), <size to read >, filePtr);
char* copyOfDataArray = (char*)malloc(sizeof(char) * newA.size);
for (i = 0; i < size; i++)
{
fread(buff, sizeof(char), 1, filePtr);
copyOfDataArray[i] = newA.dataArray[i];
}
//why reading again once you done above.
newA.dataArray = copyOfDataArray;
return newA; //Please check: How you can return a auto variable.
}
void Initialize()
{
A first = load("file1", 100);
A second = load("file2", 20);
}

C How to make a list of messages?

I would like to make a list of messages witch I call by an index number. So I would get the input 13, then message 13 should be printed. My issue is that I need a lot of theses messages and they need to be of multiple lines, this would take up to much space in my main file. So my question is how do I store all these messages and call them when needed?
I would store them in a separate source file in an array of char*. The number can simply be an index into the array.
According to my understanding of your question. You should use array of string. because array is the fastest way of storing and retrieving data. you may use like below:
char a[2][1000];
strcpy(a[0], "I hello how r u");
strcpy(a[1], "i m fine");
You can access messages by index of array. if you want access first message then you will get by a[0],for second message a[1], for third a[2] and so on.
A simple approach
char const * getMessageByIndex( int const index ) {
static char const * const messages[] = {
"I am message 0",
"I am message 1",
// ...
};
int const numMessages = sizeof messages / sizeof messages[ 0 ];
if( (index < 0) || (numMessages <= index) {
// error handling
return "index out of bound";
}
return messages[ index ];
}
make index file and message file. and message read by index file.
e.g.)*Error handling is omitted.
make index and message file:
#include <stdio.h>
const char* message[] = {
"1st message",
"2nd message\ninclude newline",
"3rd message"
//...
};
int main(){
FILE *indexFile, *textFile;
long loc=0;
int i, size, len;
size=sizeof(message)/sizeof(char*);
indexFile=fopen("index.dat", "wb");
textFile=fopen("message.dat", "wb");
for(i=0;i<size;++i){
loc = ftell(textFile);
fwrite(message[i], sizeof(char), len=strlen(message[i]), textFile);
fwrite(&loc, sizeof(long), 1, indexFile);
fwrite(&len, sizeof(int), 1, indexFile);
}
fclose(textFile);
fclose(indexFile);
return 0;
}
use sample:
#include <stdio.h>
#include <stdlib.h>
char* readMessage(int n){
char *message;
FILE *indexFile, *textFile;
long loc;
int i, size, len;
int recordSize = sizeof(long) + sizeof(int);
indexFile=fopen("index.dat", "rb");
textFile=fopen("message.dat", "rb");
loc = recordSize * n;
fseek(indexFile, loc, SEEK_SET);
fread(&loc, sizeof(long), 1, indexFile);
fread(&len, sizeof(int ), 1, indexFile);
message=(char*)malloc(sizeof(char)*(len+1));
fseek(textFile, loc, SEEK_SET);
fread(message, sizeof(char), len, textFile);
message[len]='\0';
fclose(textFile);
fclose(indexFile);
return message;
}
int main(){
char *mes;
int n;
n =1;
mes = readMessage(n);//zero origin
printf("message %d is \"%s\"\n", n, mes);
free(mes);
return 0;
}

Resources