File Processing via seekp and seekg C++

In summary: I think I just have to figure out how to insert the accountNumber into the file with the method newRecord...Thanks for your help Reid.Reid,I solved it!I just have to remove the accountNumber - 1 then it could write into the file :DIn summary, the conversation discusses a program about credit cards which generates 16 random digits and a starting balance and writes it to a file. The file acts as a database and can be updated later. It also includes a credit card class with various methods for setting and getting account and balance numbers. The conversation also delves into creating and writing to a new record in the file, with some troubleshooting and problem-solving along the way.
  • #1
6
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
  • #2
Did you open the file as read and write (replacement allowed) or write only (creation)?

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

Do fstream files support write in place?
 
Last edited:
  • #3
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:
  • #4
What does file.clear() do?

If you open up the file with a binary editor what is going on?
 
  • #5
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:
  • #6
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:
  • #7
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 :)
 
  • #8
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?
 
  • #9
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:

What is the purpose of using seekp and seekg in C++ file processing?

The seekp and seekg functions in C++ are used for positioning the file pointer at a specific location in a file. This allows for random access to different parts of the file, making it easier to read and write data.

How do you use seekp and seekg in C++?

To use seekp and seekg, you must first open a file using the fstream library. Then, you can use the seekp function to set the file pointer to a specific position for writing data, or use the seekg function for reading data. Both functions take in two parameters: the offset and the direction from the current position.

What is the difference between seekp and seekg?

The main difference between seekp and seekg is their purpose. seekp is used for positioning the file pointer for writing data, while seekg is used for positioning the file pointer for reading data. Additionally, seekp uses the file's output position as a reference point, while seekg uses the file's input position.

Can you use seekp and seekg to move the file pointer to the beginning or end of a file?

Yes, you can use both seekp and seekg to move the file pointer to the beginning or end of a file. To move to the beginning, you can use an offset of 0 and the beg direction. To move to the end, you can use an offset of 0 and the end direction.

What happens if you try to use seekp or seekg on a file that is not open?

If you try to use seekp or seekg on a file that is not open, the functions will not work and the file pointer will not be moved. It is important to ensure that the file is opened correctly before using these functions.

Suggested for: File Processing via seekp and seekg C++

Replies
1
Views
305
Replies
2
Views
451
Replies
3
Views
1K
Replies
10
Views
1K
Replies
16
Views
4K
Replies
9
Views
1K
Back
Top