File Processing via seekp and seekg C++

  • Context: C/C++ 
  • Thread starter Thread starter duydaniel
  • Start date Start date
  • Tags Tags
    C++ File Processing
Click For Summary

Discussion Overview

The discussion revolves around file processing in C++ using seekp and seekg, specifically in the context of creating and updating a binary file that stores credit card records. Participants explore issues related to file handling, data structure design, and the behavior of file streams.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Exploratory

Main Points Raised

  • One participant describes a C++ class for credit cards and methods for creating and updating a binary file to store records.
  • Another participant questions whether the file is opened in the correct mode for reading and writing, suggesting the use of fstream instead of ofstream.
  • A participant mentions the use of file.clear() to reset the end-of-file indicator and expresses confusion about the output seen in a binary editor.
  • Concerns are raised about the implications of writing to a file that has been initialized with empty records, particularly regarding the size of account numbers and their corresponding file positions.
  • One participant suggests that the issue with writing new records may stem from the assumption that account numbers can exceed the initialized range of records.
  • Another participant proposes the need for a method to indicate empty records in the file, suggesting the use of reserved or illegal values in the class fields.

Areas of Agreement / Disagreement

Participants express differing views on the file handling methods and the implications of the data structure design. There is no consensus on the best approach to resolve the issues presented, and multiple competing views remain regarding file initialization and record management.

Contextual Notes

Participants note limitations regarding the assumptions made about account number ranges and the initialization of records in the file. The discussion highlights unresolved questions about the behavior of fstream and the handling of binary data.

Who May Find This Useful

Readers interested in C++ programming, file handling, and data structure design may find this discussion relevant, particularly those working on projects involving binary file manipulation and record management.

duydaniel
Messages
6
Reaction score
0
Hello,

I am working on a program about credit card that basically, generate 16 ramdom digits, a starting balance and write it to a file. The file works as an database and can be updated later.

Here is my credit card class

Code:
class CCard
{
// variables section
private:
	//sixteen digits of a credit card
	int group1[4]; 
	int group2[4];
	int group3[4];
	int group4[4];
	double balance;
	double cardNumber;
	int ID;

// methods sections
public:
	CCard(int=0); // constructor
	double getAccount() const; // return account number
	double getBalance() const; // return balance number
	void setBalance(double);
	void resetGroups(); // initialize 16 digits to 0
	
private: //should not be accessible by outside objects.
	
	int randomNumber(); // return random number from 0->9
	void setRandNumberToCard(); // set random number for card
	int calculateCheckDigit(); // find the last digit of the card
	double arrayToNumber(int [], double); // convert array of int to a double number
	void convertGroupsToCardNumber(); //convert 16 digits to cardNumber (account)
};

Here is the method to create a random access file which can hold 1000 record

Code:
void createFile()
{
	ofstream file("data.dat",ios::out|ios::binary);
	if (!file){
		cerr << "File could not be opended" << endl;
		exit(1);
	}
	
	// empty object, all the value is 0
	CCard card;

	card.resetGroups();
	//create 1000 accounts
	for (int i = 0; i < 1000; i++)
	{
		file.write(reinterpret_cast<const char *>(&card),sizeof(CCard));	
	}
	file.close();
}

Here is the method of writing new record to the file (does not work somehow)

Code:
void newRecord(fstream &insertFile)
{
	double acc = 0.0;
	cout << "\nEnter 3-7 :"; //possible starting digits of a credit card
	cin >> acc;
	
	//create an object which include 15 random digits of a card and balance
	CCard card(acc);
	
	// get the 16 digits account number (generated randomly)
	double accountNumber = card.getAccount();
	
	//move the pointer to the place
	insertFile.seekp((accountNumber -1)*sizeof(CCard));

	//write to the place (assume the place is empty)	
	insertFile.write(reinterpret_cast<char *>(&card),sizeof(CCard));
}
Any input would be appreciated.

Regard,
 
Last edited:
Technology news on Phys.org
Did you open the file as read and write (replacement allowed) or write only (creation)?

ofstream file("data.dat",ios::in|ios::out|ios::binary);

Do fstream files support write in place?
 
Last edited:
Dear Reid,

Yeah, I think I did.
Here is the code in main

Code:
int main()
{

	//createFile();
	fstream file("data.dat",ios::in|ios::out|ios::binary);
	if (!file)
	{
		cerr << "Can't open file";
		exit(1);
	}

	int choice;

	while ((choice = enterChoice()) != 4)
	{
		switch (choice)
		{
		case 1: display(file);break;
		case 2: updateRecord(file);break;
		case 3: newRecord(file);break;
		default: cerr << "incorrect choice";
			break;
		}
		file.clear();
	}
	file.close();
	
	cin.ignore();
	cin.ignore();
	return 0;
}

PM me if you need the full source I am working on :(
 
Last edited:
What does file.clear() do?

If you open up the file with a binary editor what is going on?
 
Jeff Reid said:
What does file.clear() do?

If you open up the file with a binary editor what is going on?

Hi Reid,
the file.clear(); is to reset end-of-file indicator.
I never heard of a binary editor before :(
I use notepad to open up the data.dat file after generated 1000 empty records... it shows garbage.
like this :

ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ
...

Interestingly, if I read from that file ( the data.dat )into a normal txt in nonbinary mode, it show correctly:

0 0 0
0 0 0
0 0 0
0 0 0
... (repeated 1000 times)

Here is the code:
Code:
void display (fstream &readFile)
{
	ofstream outPrintFile("print.txt",ios::out);

	if (!outPrintFile)
	{
		cerr << "File could not be created";
		exit(1);
	}
	
	// put the pointer into the beginning of the file
	readFile.seekg(0);

	CCard card;
	readFile.read(reinterpret_cast<char *>(&card),sizeof(CCard));

	while(!readFile.eof())
	{
		if(card.getID() != 0) // skip it if you want to show zeros
		outputLine(outPrintFile,card);

		readFile.read(reinterpret_cast<char *>(&card),sizeof(CCard));	
	}
	cout << "\ndone";
}

Code:
void outputLine(ostream &output, const CCard &record)
{
	output << setprecision(20) << " " << record.getAccount() << " " << record.getBalance() << " " << record.getID() << endl;

	//cout << "\n account is: " << record.getAccount() << endl << "Balance is: " << record.getBalance();
}

but the bottom line is the method to create newRecord (actually, it is to insert a generated object into the empty record in the data.dat) doesn't work. This project dues this Saturday... beside, I have another huge Java project dues the same day but haven't started it yet since I stuck with the C++ here :(
 
Last edited:
duydaniel said:
I never heard of a binary editor before.
What C++ compiler are you using? Microsoft's Visual Studio's open file dialog box includes a down arrow on the open button (enabled after you click on a file name) that let's you select "open with", where you can then specify "binary editor". If you change the name of the file to "data.bin", generally most programming editors will default to binary mode when you open the file.

Link to what should be a working example:

http://www.cplusplus.com/reference/iostream/ostream/seekp.html

Also, you might need to do a flush after each write.
insertFile.write(...)
insertFile.flush()

More on fstream (I haven't used fstream class before, so this link is mostly for me):

http://www.cplusplus.com/reference/iostream/fstream
 
Last edited by a moderator:
Jeff Reid said:
What C++ compiler are you using? Microsoft's Visual Studio's open file dialog box includes a down arrow on the open button (enabled after you click on a file name) that let's you select "open with", where you can then specify "binary editor". If you change the name of the file to "data.bin", generally most programming editors will default to binary mode when you open the file.

Thanks Reid for the binary :D
I use VS 2008 Pro SP1. It is now showing in binary mode now.
I think the error (doesn't write) is actually because of the nature of create 1000 empty objects. When the method create file with 1000 empty slots and set them into a file, their location will be

Code:
// put the pointer to the position of the appropriate place (min 0 to 999 max depends)
// example
insertFile.seekp ((from 0 to 999)*reinterpret_<cast char *>sizeof (CCard));

The problem is that I use credit card number (16 digits which equivalent to some trillions perhaps) and try to plug it into the file, which does not have the appropriate room because it only have room from 0 to 999.

Code:
insertFile.seekp((accountNumber -1)*sizeof(CCard)); // the accountNumber is way too big
// I think unless the file extends to some trillion records, then it could work
insertFile.write(reinterpret_cast<char *>(&accountNumber-1),(sizeof(CCard));

I tried replacing the accountNumber - 1 with the balance (which is maximum $1000 in this particular program) and it did write :)
 
I knew the account numbers had 16 digits, but wrongly assumed you would limit the values to 1 -> 1000 based on the code. You'll need to initialize the file with "empty" records, some "reserved" or illegal value in one of the class fields to indicate that record in the file is empty. Then when you need to add a new record, just scan the file by reading records sequentially until you find an empty slot and write the record there.

With the short time period for the project, I assume you're not expected to optimize the searching process with some type of hashing algorithm or sorting and binary searching?
 
Jeff Reid said:
I knew the account numbers had 16 digits, but wrongly assumed you would limit the values to 1 -> 1000 based on the code. You'll need to initialize the file with "empty" records, some "reserved" or illegal value in one of the class fields to indicate that record in the file is empty.

Hello Reid,

Thanks a lot. I suspected it was wrong but kept trying somehow :(
Then when you need to add a new record, just scan the file by reading records sequentially until you find an empty slot and write the record there.

I think it is self sorted in binary file? Instead of using 16 digits to move the pointer, I now use the last four digits. The possibility is 0 -> 9999 so I just need 10000 empty records to store them. When I use
insertFile.seekp((lastFourDigit -1)*sizeof (CCard));
It would place the pointer into a unique position on the record file Data.dat, thus when I print them out, I would expect them sorted by lastFourDigit order?

With the short time period for the project, I assume you're not expected to optimize the searching process with some type of hashing algorithm or sorting and binary searching?
I wonder if you have some performance experience with such approach vs hashing algorithm?
 
  • #10
duydaniel said:
I now use the last four digits.
As long as those last four digits are different for every number that wil work.

The possibility is 0 -> 9999 so I just need 10000 empty records to store them. When I use insertFile.seekp((lastFourDigit -1)*sizeof (CCard));
Since the value is 0->9999, the you'd wouldn't subtract 1: insertFile.seekp((lastFourDigit)*sizeof (CCard)).

I wonder if you have some performance experience with such approach vs hashing algorithm?
For a 1000 records on a homework program it's not worth the effort. Since you're directly accessing the records via the last 4 digits, which are assumed to be unique, you're directly indexing off a value, so no need to use a hashing algorithm which would convert a 16 digit number into a semi-unique 4 digit number, for the initial probe into the file, followed by more probes (adding a prime number to the index | 10000 would probably be good enough) until you find a match or empty slot.
 
Last edited:

Similar threads

Replies
6
Views
2K
  • · Replies 17 ·
Replies
17
Views
2K
Replies
20
Views
2K
  • · Replies 8 ·
Replies
8
Views
2K
Replies
10
Views
2K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 6 ·
Replies
6
Views
12K
  • · Replies 32 ·
2
Replies
32
Views
4K
Replies
12
Views
2K
  • · Replies 12 ·
Replies
12
Views
2K