Here's what i have. Not sure what it is doing exactly.

You pack a account object and then you write it to the buffer right? So shouldn't it print after i write it?

Main

#include <iostream>
#include <iomanip>
#include "account.h"
#include "Lentext.h"
#include "Deltext.h"


using namespace std;
int main()
{
    int result;
    account a;
    LengthTextBuffer b;

    strcpy(a.account_Number,"1111111111");
    strcpy(a.name, "Name");
    strcpy(a.address, "Address");
    strcpy(a.city, "City");
    strcpy(a.state, "IL");
    strcpy(a.zip_Code, "60192");
    cout<<"person object's data\n";
    a.Print(cout);
    result=a.Pack(b);
    cout<<"result after pack is"<<result;
    b.Print(cout);
    result=b.Write(cout);
    cout<<"result after write is"<<result;



    return 0;
}
[/CODE]

Account.h
[CODE]
#include <iostream>
#include "Lentext.h"
#include "Deltext.h"

#include <string>
using namespace std;
class account
{
public:
    char account_Number[11];
    char name[1000];
    char address[1000];
    char city[16];
    char state[3];
    char zip_Code[10];
    char account_Balance[1000];

    //default account constructor
    account();

    //set each field to a empty string
    void Clear();

    //methods for Lentext
    int Pack(LengthTextBuffer&) const;
    int UnPack(LengthTextBuffer&);

    //methods for Deltext
    int Pack(DelimTextBuffer&) const;
    int UnPack(DelimTextBuffer&);

    //print data
    void Print(ostream &);

    //intializes a DelimTextBuffer to be used for Persons
    int InitBuffer(DelimTextBuffer &);

    //intializes a LengthTextBuffer to be used for Persons
    int InitBuffer(LengthTextBuffer &);
};


[/CODE]

Account.cpp
[CODE]
#include "Account.h"
#include <iostream>
#include <iomanip>
using namespace std;


account::account()
{
    Clear();
}

void account::Clear()
{
    account_Number[0]=0;
    name[0]=0;
    address[0]=0;
    city[0]=0;
    state[0]=0;
    zip_Code[0]=0;
    account_Balance[0]=0;
}

//pack the fields into a FixedTextBuffer
//return true if all succeed
int account::Pack(LengthTextBuffer & Buffer) const
{
    int result;
    Buffer.Clear();
    result=Buffer.Pack(account_Number);
    result=result&&Buffer.Pack(name);
    result=result&&Buffer.Pack(address);
    result=result&&Buffer.Pack(city);
    result=result&&Buffer.Pack(state);
    result=result&&Buffer.Pack(zip_Code);
    result=result&&Buffer.Pack(account_Balance);
    return result;
}

int account::UnPack(LengthTextBuffer & Buffer)
{
    int result;
    result=Buffer.Unpack(account_Number);
    result=result&&Buffer.Unpack(name);
    result=result&&Buffer.Unpack(address);
    result=result&&Buffer.Unpack(city);
    result=result&&Buffer.Unpack(state);
    result=result&&Buffer.Unpack(zip_Code);
    result=result&&Buffer.Unpack(account_Balance);
    return result;
}

//pack the fields into a FixedTextBuffer
//return TRUE if all succeed, False o/w
int account::Pack(DelimTextBuffer & Buffer) const
{
    int result;
    Buffer.Clear();
    result=Buffer.Pack(account_Number);
    result=result&&Buffer.Pack(name);
    result=result&&Buffer.Pack(address);
    result=result&&Buffer.Pack(city);
    result=result&&Buffer.Pack(state);
    result=result&&Buffer.Pack(zip_Code);
    result=result&&Buffer.Pack(account_Balance);
    return result;
}

int account::UnPack(DelimTextBuffer & Buffer)
{
    int result;
    result=Buffer.Unpack(account_Number);
    result=result&&Buffer.Unpack(name);
    result=result&&Buffer.Unpack(address);
    result=result&&Buffer.Unpack(city);
    result=result&&Buffer.Unpack(state);
    result=result&&Buffer.Unpack(zip_Code);
    result=result&&Buffer.Unpack(account_Balance);
    return result;
}

void account::Print(ostream & stream)
{
    stream<<"Person:"
        <<"\t accountnumber'"<<account_Number<<"\n"
        <<"\t name'"<<name<<"\n"
        <<"\t address'"<<address<<"\n"
        <<"\t city'"<<city<<"\n"
        <<"\t state'"<<state<<"\n"
        <<"\t zipcode'"<<zip_Code<<"\n"
        <<"\t account balance'"<<account_Balance<<"\n";
}
[/CODE]


Lentext.h
[CODE]
#ifndef CLASS_H_LENTEXT
#define CLASS_H_LENTEXT 


#include <iostream>

using namespace std;

//a buffer which holds length based text fields
class LengthTextBuffer
{
public:
    //construct with a maximum of maxFields
    LengthTextBuffer(int maxBytes=1000);

    //clear fields from buffer
    void Clear();

    int Read(istream &);

    int Write(ostream &) const;

    //set the value of the next field of the buffer
    int Pack(const char *, short size=-1);

    //extract the value of the next field of the buffer
    int Unpack(char *);

    void Print(ostream &) const;

    void Init(int maxBytes=1000);

private:
    //character array to hold field values
    char * Buffer;

    //size of packed fields
    int BufferSize;

    //maximum number of characters in the buffer
    int MaxBytes;

    //packing/unpacking position in buffer
    int NextByte;

};

#endif

[/CODE]

Lentext.cpp
[CODE]
#include "Lentext.h"
#include <string.h>

//constructor with a maximum of maxFields
LengthTextBuffer::LengthTextBuffer(int maxBytes)
{
    Init(maxBytes);
}

//clear fields from buffer
void LengthTextBuffer::Clear()
{
    BufferSize=0;
    MaxBytes=0;
    NextByte=0;
}

int LengthTextBuffer::Read(istream & stream)
{
    Clear();
    stream.read((char*)&BufferSize, sizeof(BufferSize));
    if(stream.fail())
    {
        return false;
    }
    //buffer overflow
    if(BufferSize>MaxBytes)
    {
        return false;
    }
    stream.read(Buffer,BufferSize);
    return stream.good();
}

int LengthTextBuffer::Write(ostream & stream) const
{
    stream.write((char *)&BufferSize, sizeof(BufferSize));
    stream.write(Buffer, BufferSize);
    return stream.good();
}

//set the value of the next field of the buffer
//if size=-1(default) use strlen(str) as length of field
int LengthTextBuffer::Pack(const char * str, short size)
{
    //length of string to be packed
    size_t len;
    if(size>=0)
    {
        len=size;
    }
    else
    {
        len=strlen(str);
    }
    //str is too short
    if(len>strlen(str))
    {
        return false;
    }
    //first character to be packed
    int start= NextByte;
    NextByte += (len+sizeof(len));
    if(NextByte>MaxBytes)
    {
        return false;
    }
    memcpy(&Buffer[start],&len,sizeof(len));
    strncpy(&Buffer[start+sizeof(len)],str, len);
    BufferSize=NextByte;
    return true;
}

//extract the value of the next field of buffer
int LengthTextBuffer::Unpack(char * str)
{
    //length of packed string
    short len;
    //no more fields
    if(NextByte>=BufferSize)
    {
        return false;
    }
    //first character to be unpacked;
    int start=NextByte;
    memcpy(&len, &Buffer[start], sizeof(short));
    NextByte += len +sizeof(short);
    if(NextByte > BufferSize)
    {
        return false;
    }
    strncpy(str, &Buffer[start+sizeof(short)],len);
    //zero termination for string
    str[len]=0;
    return true;
}

void LengthTextBuffer::Print(ostream & stream) const
{
    stream<< "Buffer has characters"<<MaxBytes
        <<" and Buffer Size " <<BufferSize<<endl;
}

//construct with a maximum of maxFields
void LengthTextBuffer::Init(int maxBytes)
{
    if(maxBytes<0)
    {
        maxBytes=0;
    }
    MaxBytes=maxBytes;
    Buffer=new char[MaxBytes];
    Clear();
}



[/CODE]


Deltext.h
[CODE]
#ifndef CLASS_H_DELTEXT
#define CLASS_H_DELTEXT 

#include <iostream>

using namespace std;

//a buffer which holds delimited text fields
class DelimTextBuffer
{
public:
    //constructor with fields with delimeters
    DelimTextBuffer(char Delim='|', int maxBytes=1000);
    //clear fields from buffer
    void Clear();
    int Read(istream &);
    int Write(ostream &) const;
    int Pack(const char *,int size=-1);
    int Unpack(char *);
    void Print(ostream &) const;
    void Init(char delim, int maxBytes=1000);
private:
    char Delim;
    //zero terminated string for Delim
    char DelimStr[2];
    //char array to hold field values
    char * Buffer;
    //size of packed fields
    int BufferSize;
    //maximum number of characters in the buffer
    int MaxBytes;
    //packing/unpacking position in buffer
    int NextByte;
};

#endif

[/CODE]

Deltext.cpp
[CODE]
#include "Deltext.h"
#include <string.h>



//construct with a maximum number of maxFields
DelimTextBuffer::DelimTextBuffer(char Delim, int maxBytes)
{

    Init(Delim,maxBytes);
}

//clear fields from buffer
void DelimTextBuffer::Clear()
{
    BufferSize=0;
    MaxBytes=0;
    NextByte=0;
}

int DelimTextBuffer::Read(istream & stream)
{
    Clear();
    stream.read((char*)&BufferSize, sizeof(BufferSize));
    if(stream.fail())
    {
        return false;
    }
    //buffer overflow
    if(BufferSize>MaxBytes)
    {
        return false;
    }
    stream.read(Buffer,BufferSize);
    return stream.good();
}

int DelimTextBuffer::Write(ostream & stream) const
{
    stream.write((char *)&BufferSize, sizeof(BufferSize));
    stream.write(Buffer, BufferSize);
    return stream.good();
}

//set the value of the next field of the buffer
//if size=-1(default) use strlen(str) as Delim of field
int DelimTextBuffer::Pack(const char * str, int size )
{
    //length of string to be packed
    size_t len;
    if(size>=0)
    {
        len=size;
    }
    else
    {
        len=strlen(str);
    }
    //str is too short
    if(len>strlen(str))
    {
        return false;
    }
    //first character to be packed
    int start=NextByte;
    NextByte +=len + 1;
    if(NextByte>MaxBytes)
    {
        return false;
    }
    memcpy(&Buffer[start],str, len);
    //add delimeter
    Buffer[start+len]=Delim;
    BufferSize=NextByte;
    return true;
}

//extract the value of next field of the buffer
int DelimTextBuffer::Unpack(char * str)
{
    //length of packed string
    int len=-1;
    //first character to be unpacked
    int start=NextByte;
    for(int i=start; i<BufferSize; i++)
    {
        if(Buffer[i]==Delim)
        {
            len=i-start;
            break;
        }
    }
    //delimeter not found
    if(len==-1)
    {
        return false;
    }
    NextByte +=len + 1;
    if(NextByte>BufferSize)
    {
        return false;
    }
    strncpy(str, &Buffer[start], len);
    //zero termination for string
    str[len]=0;
    return true;
}

void DelimTextBuffer::Print(ostream & stream) const
{
    stream<< "Buffer has max characters" <<MaxBytes
        <<" and Buffer Size "<<BufferSize<<endl;
}

void DelimTextBuffer::Init(char delim, int maxBytes)
{
    Delim=delim;
    DelimStr[0]= Delim;
    DelimStr[1]=0;
    if(maxBytes <0)
    {
        maxBytes=0;
    }
    MaxBytes=maxBytes;
    Buffer= new char[MaxBytes];
    BufferSize=0;
}

Recommended Answers

All 10 Replies

ahhhh it won't pack.. it returns 0 which means information isn't packed. This code in my book doesn't work.
main

#include <iostream>
#include <fstream>
#include <iomanip>
#include "account.h"
#include "Lentext.h"
#include "Deltext.h"


using namespace std;
int main()
{
    LengthTextBuffer a;
    account b;

    strcpy(b.account_Number,"1111111111");
    strcpy(b.name,"Name");
    strcpy(b.address,"Address");
    strcpy(b.city, "City");
    strcpy(b.state, "IL");
    strcpy(b.zip_Code, "60192");
    strcpy(b.account_Balance, "111111");
    b.Print(cout);
    //pack data into a buffer not happening
    int c=b.Pack(a);
    cout<<endl<<c<<endl;
    //ofstream out;
    //out.open("test.txt");
    //a.Write(out);
    return 0;
}

There is no need for the pack() functionality. The account class is already packed (fixed-length). Just write the account object to a binary file.

void write(Account& obj)
{
    ofstream out("filename.dat", ios::binary | ios:: app);
    out.write( (char*)&obj, sizeof(Account));
    out.close();
}

similar to read it

void read(vector<Account>& accountList)
{
    Account obj;
    ifstream in("filename.dat", ios::binary);
    while( in.read((char *)&obj, sizeof(Account))
    {
         accountList.push_back(obj);
    }
}

but the code in my book shows that i should pack and my teacher said I should Pack the object, then write it to the file, that way the person class and buffer class don't know anything about each other.

You don't have to read the data back into a account class. You can do anything you want with the data, such as read it back into individual char arrays if you want to. The data file is not tied to any class or structure.

If you made the individual fields of the account class std::string instead of character arrays, then you would need to pack the data into fixed-length fields before writing them to the file. But as it is, the account class already contains fixed-length fields, such packing is not necessary. When you write a class to a data file only the data objects are written, not any of the methods.

i don't think that is the intent of packing a buffer. IT is supposed to have a record which contains of fields and store it into a buffer everytime the all account objects assigned. The pack and send it to the buffer which does the reading and writing.

Here are my teachers directions

FILE PROCESSING - PROGRAMMING PROJECT 2
DUE: 10/28/09
This programming project is to modify the first project to be one that uses two of the buffers and the BufferFile classes outlined in the textbook in Chapter 4. The file is made of account information for a credit card company (class will be similar to project 1). To keep things simple we are only going to keep the following pieces of information about the account:

1. Account number - a 10 digit number
2. Card holder's name
3. Card holder's address which contains
* street address
* city
* state
* zip code
4. account balance

You are two write two separate programs using the buffer file class for each of the buffers chosen:
PROGRAM 1
This program is to create the file using the buffer class chosen. Your program is to be interactive with a user. You should first ask for the name of the file to be created, then create the file (in write mode). If the file cannot be created you should output an error message and quit. If the file is created then you should enter a loop that allows the user to input data into the file. Your program can use a sentinel value for the account number to exit the loop (an account number of -1 could be used).
PROGRAM2
This program is to access the file produced in program 1 and to produce a "nicely formatted" report on the contents of the file. You should be able to use the io manipulators in c++ to do formatting.
General Note:
Use the BufferFile class along with one of the Buffer classes outlined in the textbook (you can download the code from the textbook for this) for each of the programs. Note that you may need to rewrite parts of the buffer object classes because of the newer c++ standards for the language.

The program doesn't work because the Clear() method destroys the value of MaxBytes by setting it to 0, which makes that Pack() return false when checking if size > MaxBytes.

void LengthTextBuffer::Init(int maxBytes)
{
	if(maxBytes<0)
	{
		maxBytes=0;
	}
	MaxBytes=maxBytes;
	Buffer=new char[MaxBytes];
	Clear();
}

its still won't work. I don't understand why.

Here's what i have:

#include <iostream>
#include <fstream>
#include <iomanip>
#include "account.h"
#include "Lentext.h"
#include "Deltext.h"


using namespace std;
int main()
{
    LengthTextBuffer a;
    account b;

    strcpy(b.account_Number,"1111111111");
    strcpy(b.name,"Name");
    strcpy(b.address,"Address");
    strcpy(b.city, "City");
    strcpy(b.state, "IL");
    strcpy(b.zip_Code, "60192");
    strcpy(b.account_Balance, "111111");
    b.Print(cout);
    //pack data into a buffer not happening
    int c=b.Pack(a);
    cout<<endl<<c<<endl;
    return 0;
}

Now is when you need to learn how to use your compiler's debugger so that you can single-step through the program one line at a time. I already told you why your program doesn't work. The problem is in that Clear() method. Your program works ok for me when I made that change.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.