问题
I can write into a relative file1, then when I try to read the content and display it on the screen (to check if data are actually into the file), I do not have the records which I believe are already present in the file. I am using Dev-C++. Any help will be appreciated. The code is below;
#include <iostream> // cin, cout
#include <iomanip>
#include <fstream>
#include <conio.h>
using namespace std;
#define SIZE 10
struct client // Client record
{
int account; // from 1 to SIZE
char name[20];
double balance;
};
void make_file(char filename[], int number_of_records)
{
cout << "\nMAKE_FILE: Creating a blank relative file " << filename
<< " containing " << number_of_records << " records.";
ofstream OS(filename, ios::out);
if(!OS) {cerr << "File open error." << endl; exit(1);}
client blank={0, "", 0.0}; // Create an empty client record
while(number_of_records--)
OS.write((char *)&blank, sizeof(blank));
cout << "\nFile created.";
OS.close();
}
int main(void)
{
client c;
void *ptr;
int n=0;
char *fname = "credit.txt";
make_file(fname, SIZE);
fstream iof("credit.txt",ios::in | ios::out);
if(!iof)
{
cerr<<"File open error! "<<endl;
exit(1);
}
cout<<"\n\nenter the 10 customers into the file: "<< fname<<endl<<endl;
while(0 < c.account) // && c.account <= maxrec)
{
iof.seekp((c.account-1) * sizeof(client)); // position the pointer
iof.write((char *)&c, sizeof(c));
cout << "Account[1.."<< SIZE
<< "], Name, Balance (0 0 0 to exit)= ";
cin >> c.account >> c.name >> c.balance;
}
cout << "\n\nSHOW_FILE: The contents of file " << fname;
iof.seekg (0, ios::beg);
while(iof.read((char *)&c, sizeof(c))) //where I think the problem is
{
cout <<'\n'<< setw(3)<< ++n << setw(6) << c.account <<setw(20)
<< c.name << setw(10) << c.balance ;
// << " | " << IS.eof() << " " << ptr;
}
iof.close();
cout << "\n\n";
system("pause");
return 0;
}
A relative file is a file in which each record is identified by its ordinal position in the file allowing for random as well as sequential access.
Relative Files
Relative file organization
http://cayfer.bilkent.edu.tr/~cayfer/ctp108/relative.htm
回答1:
You need to use binary reading/writing.
fstream iof("credit.txt",ios::in | ios::out | ios::binary);
回答2:
In your code, in first loop, c.account
is not initialitzed. Perhaps you are overwriting file with uninitialized values:
while(0 < c.account) // <--- c.account is not initialized!!
{
iof.seekp((c.account-1) * sizeof(client)); // position the pointer
iof.write((char *)&c, sizeof(c)); // <-- overwriting data??
回答3:
You're program intrigued me since I haven't done too much work with iostream. If you were ever working with data that had to be edited on a per record basis you'd use some type of database or specialized library that would encapsulate you from all this stuff, such as an xml library. Since your data is so small it's easier to just load all of it into your application using an array of your data structs. After, when you've got new user input, it's easiest clear the file, and the write the data fresh. Here is what I did.
#include <stdio.h>
#include <tchar.h>
#include <iostream> // cin, cout
#include <iomanip>
#include <fstream>
#include <conio.h>
using namespace std;
#define SIZE 10
#define BUFFER_SIZE 100
#define NAME_SIZE 20
struct client // Client record
{
int account; // from 1 to SIZE
char name[NAME_SIZE];
double balance;
};
/* Makes file if files does not exist.
* Returns true if file already exists
*/
bool make_file(char filename[], int number_of_records)
{
// Check if file exists
fstream file;
file.open(filename, ios_base::out | ios_base::in); // will not create file
if (file.is_open())
{
file.close();
return true;
}
else
{
file.clear();
file.open(filename, ios_base::out);
if(!file) {cerr << "File open error." << endl; exit(1);}
cout << "File created. \n";
file.close();
return false;
}
}
/* Create an application that reads x number of accounts from a text file
* into an array of client data structures.
*/
int _tmain(int argc, _TCHAR* argv[])
{
client clientArray[SIZE];
char cleanName[NAME_SIZE];
for(int i = 0; i < NAME_SIZE; i++)
cleanName[i] = NULL;
// Make file if doesn't not exist.
char *fname = "credit.txt";
bool fileExisted = false;
fileExisted = make_file(fname, SIZE);
// initialize client array
for(int j = 0; j < SIZE; j++)
{
clientArray[j].account = -1;
strcpy_s(clientArray[j].name, cleanName);
clientArray[j].balance = 0.0;
}
// Open file and populate the client array
fstream readFile("credit.txt", ios::in | ios::binary);
if(fileExisted)
{
if(!readFile)
{
cerr<<"File open error! "<<endl;
exit(1);
}
int index = 0;
bool firstRun = true;
client temp;
while(index < SIZE)
{
readFile >> temp.account;
readFile >> temp.name;
readFile >> temp.balance;
if(readFile.eof())
break;
if(firstRun)
{
cout << "Data read \n";
cout << "----------\n";
firstRun = false;
}
clientArray[index].account = temp.account;
strcpy_s(clientArray[index].name, temp.name);
clientArray[index].balance = temp.balance;
cout << setw(3) << index+1;
cout << setw(6) << clientArray[index].account;
cout << setw(20) << clientArray[index].name;
cout << setw(10) << clientArray[index].balance << "\n";
index++;
}
readFile.close();
readFile.clear();
}
// Get user input
{
client temp; // Create and initialize temp client
temp.account = 0;
temp.balance = 0;
strcpy_s(temp.name, cleanName);
int index = 0;
bool keepLooping = true;
while(keepLooping)
{
cout << "Account[1.."<< SIZE << "], Name, Balance (-1 to exit)= ";
cin >> temp.account;
// If user exited
if(temp.account == -1)
keepLooping = false;
else
{
cin >> temp.name; // If not keep reading data
cin >> temp.balance;
// Find either unused account or same account
bool found = false;
int firstEmpty = -1;
for(int i = 0; i<SIZE; i++)
{
if(temp.account == clientArray[i].account) // Same account found
{
strcpy_s(clientArray[i].name, temp.name);
clientArray[i].balance = temp.balance;
found = true;
break;
}
else if((clientArray[i].account == -1)&&(firstEmpty == -1)) // Empty account found
{
firstEmpty = i;
}
}
if((firstEmpty != -1)&&(!found)) // Copy input to empty account
{
clientArray[firstEmpty].account = temp.account;
strcpy_s(clientArray[firstEmpty].name, temp.name);
clientArray[firstEmpty].balance = temp.balance;
}
else if(found) //
{
cout << "Updating Client Data. \n";
}
else // No empty accounts break loop
{
cout << "Client array is full!\n";
keepLooping = false;
}
}
}
} // end of user input scope
// Clear file and write only valid data to new file
{
ofstream out;
out.open("credit.txt");
for(int i=0 ; i<SIZE ; i++)
{
if(clientArray[i].account != -1)
{
out << clientArray[i].account << "\t";
out << clientArray[i].name << "\t";
out << clientArray[i].balance << "\n";
}
}
out.close();
out.clear();
}
// Open file and read the data
{
ifstream readFile("credit.txt", ios::in | ios::binary);
// readFile("credit.txt", ios::in | ios::binary);
if(!readFile)
{
cerr<<"File open error! "<<endl;
exit(1);
}
if(!readFile.good())
{
cerr<<"File open error!2"<<endl;
exit(1);
}
int index = 0; // scope variables
client temp;
temp.account = 0;
temp.balance = 0;
strcpy_s(temp.name, cleanName);
cout << "\nAccounts" << "\n";
cout << "----------" << "\n";
bool readFileb = readFile.good();
while(index < SIZE)
{
readFile >> temp.account;
readFile >> temp.name;
readFile >> temp.balance;
if(readFile.eof())
break;
cout << setw(3) << index+1;
cout << setw(6) << temp.account;
cout << setw(20) << temp.name;
cout << setw(10) << temp.balance << "\n";
index++;
}
readFile.close();
readFile.clear();
}
system("pause");
}
来源:https://stackoverflow.com/questions/10546952/c-after-writing-into-a-relative-file-i-cannot-display-the-content