Solved

Structures to file

Posted on 1998-05-14
9
209 Views
Last Modified: 2010-04-15
I'm creating a database to help reinforce some of the basic ideas that I've learned in C.  I'm using a structure to store the info.  I've come across scripts that allow me to write structures out to a file, but none that show me how I can append a single record to this file without reloading the entire structure from the file.  Also, when I do load the entire database back into a structure, how can I determine how many records (this is an array of structures) have been read into my array of structures ?
0
Comment
Question by:tkw829
9 Comments
 
LVL 2

Accepted Solution

by:
kellyjj earned 140 total points
ID: 1250753
one way to do this is:

fh=fopen("test.txt","wr");

while (!eof(fh)) fread(buffer,1,sizeof(struct),fh);

fwrite(struct,1,sizeof(struct),fh);

now to keep track of how many records are read into simply keep a counter of each read:

while (!eof(fh))
{
  num_of_recs=num_of_recs+1;
  fread(buffer,1,sizeof(struct),fh);
}


I hope this helps you get going.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1250754
open the file for append.

0
 
LVL 11

Expert Comment

by:alexo
ID: 1250755
Use fseek() to position your pointer at the end of the file (or any other position, if you use a multiple of sizeof() of your structure).
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1250756
fseek of course relies on you knowing how many records are there.  To simply aapend new records, open (binary) for read/write with append should do the trick.

0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 84

Expert Comment

by:ozo
ID: 1250757
you can fseek(fh,0,SEEK_END)
(of course, append ensures that happens automatically)
0
 
LVL 11

Expert Comment

by:alexo
ID: 1250758
fseek() (or it's low level counterpart lseek()) can position the pointer at the beginning of the file or end of the file without any knowledge of the file's length or contents.  Positioning the pointer in the middle of the file will work best if you land on a structure boundary :-)

Openning the file for append (mode "a" or "a+") does not allow changing existing records.  You'll need to open it for R/W access (mode "r+") for that.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1250759
fairy nuff ozo :-)

BTW: check out strucfil.c at www.snippets.org

This does direct file i/o using fseek etc.

0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 1250760
here is the source for it... it is hard-coded for a struct called 'blackbook' .. but it s very good starting point!!

===========
strucfil.h:
===========
/* +++Date last modified: 05-Jul-1997 */

/*
**  SNIPPETS header file for STRUCFIL.C
*/

#ifndef STRUCFIL__H
#define STRUCFIL__H

#include <stdio.h>

/* make sure the record structure is byte aligned */

#if defined(_MSC_VER) || defined(_QC) || defined(__WATCOMC__)
 #pragma pack(1)
#elif defined(__ZTC__)
 #pragma ZTC align 1
#elif defined(__TURBOC__) && (__TURBOC__ > 0x202)
 #pragma option -a-
#endif

static struct blackbook {
    int delete_flag;        /* 0 = active  -1 = deleted */
    int recordnum;          /* a sequential number in the file */
   /* The data fields in asciiz.  */
    char firstname[11];
    char lastname[16];
    char addr[26];
    char city[16];
    char state[3];
    char zip[10];
    char phone[11];
} rec, oldrec;             /* 97 byte record  * 2 */

/* set structure alignment to default */

#if defined (_MSC_VER) || defined(_QC) || defined(__WATCOMC__)
 #pragma pack()
#elif defined (__ZTC__)
 #pragma ZTC align
#elif defined(__TURBOC__) && (__TURBOC__ > 0x202)
 #pragma option -a.
#endif

FILE * open_file(char *filename);
int    datadd(void);
int    data_delete(void);
int    data_read(long recnum);
int    data_update(void);
int    read_forward(void);
int    read_backward(void);

#endif /* STRUCFIL__H */

===========
strucfil.c:
===========

/* +++Date last modified: 05-Jul-1997 */

/*******************************************************************
 * Generic structure <> disk file manipulations. These functions
 * form a basic template for reading and writing structures to a
 * sequential file. This template is probably most useful for files
 * with 500 or less records and eliminates the need for a more
 * elaborate file handler such as C-Tree, DB-Vista, Mix etc.
 * Routines to put data in the struct is out of scope here.
 * Written by Lynn Nash 8/28/91 and donated to the public domain.
 */
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include "sniptype.h"
#include "strucfil.h"
 
/*-------------------- general globals ---------------------*/

static long cur_rec = 0;      /* the current record number */
static FILE *fsptr = NULL;    /* fixed record data file pointer */
 
/* if file exists open in read/write mode else create file */

FILE * open_file(char *filename)
{
      if (access(filename, 0) == 0)
            fsptr = fopen(filename, "rb+");
      else  fsptr = fopen(filename, "wb+");
      return fsptr;                       /* return the file pointer */
}
 
/* add new records to the data file */

int datadd(void)
{
      if (fsptr)
      {
            if (fseek(fsptr, 0L, SEEK_END) != 0)
                  return Error_;  /* seek failure */
            rec.delete_flag = 0; /* active record tag */
            rec.recordnum = (int) (ftell(fsptr) /
                  (long) sizeof(struct blackbook));
            if (fwrite(&rec, sizeof(struct blackbook), 1, fsptr) != 1)
            {
                  return Error_; /* write error */
            }
            else
            {
                  /* put your clean up code here */
                  return Success_;
            }
      }
      return Error_;
}

/* tag the last record read in the file as deleted */

int data_delete(void)
{
      if (fsptr)
      {
            if (fseek(fsptr, (long) sizeof(struct blackbook) * -1L,
                  SEEK_CUR) != 0)
            {
                  return Error_;
            }
            rec.delete_flag = -1;   /* tag the record as deleted */
            if (fwrite(&rec, sizeof(struct blackbook), 1, fsptr) != 1)
                  return Error_;
            else  return Success_;
      }
      return Error_;
}

/* read a random structure. If successful the global cur_rec will
 * contain the number of the last record read & it can be compared
 * to the number in the struct as a double check (belt & suspenders)
 */

int data_read(long recnum)
{
      if (fseek(fsptr, (long) sizeof(struct blackbook) * recnum,
            SEEK_SET) != 0)
      {
            return Error_;
      }
      cur_rec = recnum; /* keep tabs on record pointer in global */  

      /* now read the record into save struct*/

      if (fread(&oldrec, sizeof(struct blackbook), 1, fsptr) != 1)
      {
            return Error_;
      }
      else                          /* copy save struct to edit struct */
      {
            memcpy(&rec, &oldrec, sizeof(struct blackbook));
            return Success_;
      }
}
 
/* rewrite the last read record back to disk */

int data_update(void)
{
      if (memcmp(&rec, &oldrec, sizeof(struct blackbook)) == 0)
            return True_;  /* no update needed */

      /* back up one record before writing */

      if (fseek(fsptr, (long) sizeof(struct blackbook) * -1L,
            SEEK_CUR) != 0)
      {
            return Error_; /* seek error */
      }

      /* now write the record */

      if (fwrite(&rec, sizeof(struct blackbook), 1, fsptr) != 1)
            return Error_; /* write error */
      return Success_;
}

/* get the next valid record in the file */

int read_forward(void)
{
      do
      {
            cur_rec++; /* upcount the record number */
            if (data_read(cur_rec) != 0)
            {
                  cur_rec--; /* decrement the record number */
                  return Error_;
            }
      } while (oldrec.delete_flag != 0); /* record read was deleted */
      return Success_;
}

/* get the previous valid record in the file */

int read_backward(void)
{
      do
      {
            cur_rec--;  /* decrement the record number */
            if (cur_rec >= 0)
            {
                  if ( data_read(cur_rec) != 0 )
                  {
                        cur_rec++; /* increment the record number */
                        return Error_;
                  }
            }  
      } while (oldrec.delete_flag != 0); /* record read was deleted */
      return Success_;
}

0
 

Author Comment

by:tkw829
ID: 1250761
Thanks kelly!!
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now