二进制结构删除错误

时间:2013-05-04 13:27:01

标签: c++ binary structure

这是整个计划。现在,删除功能不会写入临时文件。我将尝试将str数组更改为字符串,看看它是否有帮助。

该程序应该读取写入编辑搜索并使用结构对二进制文件进行排序。

#include <cstdlib>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include<string>
#include<limits>
#include<iomanip>
#include<stdio.h>
#include <errno.h>

using namespace std;
const int SIZE=40;
char typedef str[SIZE];
char fname[]="c:/solident.dat";
char tname[]="c:/temp.dat";
struct Rec{int id;str lname,fname;};


//prototypes
void menu(string&);
void engine(string&,Rec&,fstream&,fstream&,int,char[],char[]);
void openFile(char[]);
void addRec(Rec&,char[]);
void delAll(char[]);
void listAll(Rec&,fstream &,char[]);
void appRec(Rec&,fstream &,char[]);
void delRec(Rec&,fstream &, fstream &,char[],char []);
void srcRec(Rec&,fstream& ,char[]);
void modRec(Rec &J,fstream &outfile, char fname[]);
void sort();

int main(int argc, char *argv[])
{
string choice;
Rec Student;
fstream infile;
fstream outfile;

do
    {    
        menu(choice);
        engine(choice,Student,infile,outfile,SIZE,fname,tname);
    } while(choice[0]!='0');  


    system("PAUSE");
    return EXIT_SUCCESS;
}

//function menu

void menu(string &choice)
{
    cout<<"\n\n\n\t\t========================"; 
    cout<<"\n\n\t\tMENU \n";
    cout<<"\n\t\t========================\n\n";
    cout<<"\t\t[1] Open/check file\n";
    cout<<"\t\t[2] Add records\n";
    cout<<"\t\t[3] Append records\n";
    cout<<"\t\t[4] Search for a record\n";
    cout<<"\t\t[5] Delete a record\n";
    cout<<"\t\t[6] Delete all records\n";
    cout<<"\t\t[7] Modify a record\n";
    cout<<"\t\t[8] List all records\n";
    cout<<"\t\t[9] Sort all records\n";
    cout<<"\t\t[0] Exit\n";
    cout<<"\n\t\t========================= \n";
    cout<<"\t\tYour choice :";
    getline(cin,choice);

    while (choice[0] !='1' && choice[0] !='2' &&choice[0] !='3' &&choice[0] !='4' &&choice[0] !='5' &&choice[0] !='6' &&choice[0] !='7' &&choice[0] !='8' &&choice[0] !='9' &&choice[0] !='0' )
       { 
       cout<<"\n\t\t"<<choice<<" is invalid!";                           
       cout<<"\n\t\tEnter correct choice: ";
       getline(cin,choice);  
       }

    cout<<"\n\t\t========================= \n\n";
}


//function 
void engine(string &choice,Rec &J,fstream &infile,fstream &outfile,int SIZE,char fname[],char tname[])
{

 switch (choice[0]){
 case '1':
      {
      cout<<"Executing number "<<choice<<":"<<"Open/check file\n"<<endl;
      openFile(fname);
      break;
      } 


 case '2':
      {
      cout<<"Executing number "<<choice<<":"<<"Add records\n"<<endl;
      addRec(J,fname);
      break;
      } 


 case '3':
      {
      cout<<"Executing number "<<choice<<":"<<"Append records\n"<<endl;
      appRec(J,outfile,fname);
      break;
      } 


 case '4':
      {
      cout<<"Executing number "<<choice<<":"<<"Search for a record\n"<<endl;
      srcRec(J,infile,fname);
      break;
      } 


 case '5':
      {
      cout<<"Executing number "<<choice<<":"<<"Delete a record\n"<<endl;
      delRec(J,infile, outfile,fname,tname);
      break;
      } 

 case '6':
      {
      cout<<"Executing number "<<choice<<":"<<"Delete all records\n"<<endl;
      delAll(fname);
      break;
      } 


 case '7':
      {
      cout<<"Executing number "<<choice<<":"<<"Modify a record\n"<<endl;
      modRec(J,outfile,fname);
      break;
      } 

case '8':
      {
      cout<<"Executing number "<<choice<<":"<<"List all records\n"<<endl;
      listAll(J,infile,fname);
      break;
      } 

      case '9':
      {
      cout<<"Executing number "<<choice<<":"<<"Sort all records\n"<<endl;
      sort();
      break;
      } 


default:exit(0); 
}

}   

//function 
void openFile(char fname[])
{
 cout<<"\nOpening file"<<fname<<"..."<<endl;
 //confirm if file exists and opens

 fstream infile;
 fstream outfile;


 infile.open(fname,ios::in|ios::binary);
 if (infile.is_open())
 {
                     cout<<"File "<<fname<<" exists, and was opened succesfully.";
 }


 infile.close();


 //if fail ask to create
 if (infile.fail())
 {
     cout<<"File does not exist. Create? [Y]/[N]";
     char ch;
     cin>>ch;
     cin.ignore(numeric_limits<streamsize>::max(), '\n');
     //if yes then create file
     if(ch=='y'|| ch=='Y')
     outfile.open(fname,ios::out| ios::binary);
     //if not created display error
     if (outfile.fail())
        {
                      cout<<"Error: File not created"; 
        }                             
     //else confirm creation of file
     cout<<"File "<<fname<<" has been created.\n\n";
     outfile.close();
 }

}   

//function 
void addRec(Rec&J,char fname[])
{
     fstream outfile;
    outfile.open(fname,ios::out|ios::binary|ios::app);
    char another[10];



    do
    {    

        cout<<"Please enter ID number :";
        cin>>J.id;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout<<"\nPlease enter first name: ";
        cin.getline(J.fname,SIZE);
        cout<<"\nPlease enter lastname: ";
        cin.getline(J.lname,SIZE);

        outfile.write((char*) &J, sizeof(J));

        cout<<"Add another record:[Y]/[N] ";
        cin.get(another[0]);
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
     } while(another[0]=='y'||another[0]=='Y');

    cout<<"exiting to main menu.."<<endl;



}   

//function 
void delAll(char fname[])
{

 fstream outfile;

     cout<<"\n------------------\n"<<endl;
     cout<<"\nDelete all records"<<fname<<"..."<<endl;
     cout<<"\nAre you sure you want to delete all records in "<<fname<<" [Y]/[Any key for exit]?"<<endl;
     char ch;
     cin>>ch;
     cin.ignore(numeric_limits<streamsize>::max(), '\n');

     if(ch=='y'||ch=='Y')
     {

                         outfile.open(fname,ios::out|ios::binary|ios::trunc);

                         outfile.close();
     }



     else {cout<<"\nExiting to main menu..."<<endl;}

}   

//function 
void listAll(Rec&J,fstream &infile,char fname[])
{
    infile.clear();                      
    infile.open(fname,ios::in|ios::binary);

    infile.read((char*)&J,sizeof(J)); 
    cout<<"|=======================================================|"<<endl;
    cout<<"| #     | ID       | FIRST         | LAST               |"<<endl;
    cout<<"|=======================================================|"<<endl;
        int count=1;
        while(!infile.eof())
        {
         cout<<"| "<<setw(6)<<left<<count<<left<<"| "<<setw(9)<<J.id<<"| ";
         cout<<left<<setw(14)<<J.fname<<"| ";
         cout<<left<<setw(19)<<J.lname<<"|"<<endl;
         infile.read((char*)&J,sizeof(J));
         count=count+1;
         cout<<"|-------------------------------------------------------|"<<endl;
        }
    infile.close();

}


//function 
void appRec(Rec &J,fstream &outfile, char fname[])
{

        outfile.open(fname,ios::out|ios::binary|ios::app);
        outfile.clear();        
        cout<<"Please enter ID number :";
        cin>>J.id;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout<<"\nPlease enter first name: ";
        cin.getline(J.fname,SIZE);
        cout<<"\nPlease enter lastname: ";
        cin.getline(J.lname,SIZE);
        outfile.write((char*) &J, sizeof(J));
        outfile.close();


}

//----------------------------------------------------

void delRec(Rec&s,fstream &infile, fstream &outfile,char fname[],char tname[])
{
int current, request=1;
infile.open("c:/solident.dat",ios::in|ios::out|ios::binary);
if (!infile.is_open())
    cout << "infile not open\n";
outfile.open("c:/temp.dat",ios::out|ios::binary|ios::trunc);
if (!outfile.is_open())
    cout << "outfile not open\n";
for (;;)
{
    infile.read((char*)&s, sizeof s);
    if (infile.eof())
        break;
    current = s.id; 
    if (current != request)
        outfile.write((char*)&s, sizeof s);
}
infile.close();
outfile.close();



infile.open("c:/temp.dat)",ios::in|ios::binary);
outfile.open("c:/solident.dat)", ios::out|ios::binary|ios::trunc);

for (;;)
{
    infile.read((char*)&s, sizeof (s));
    if (infile.eof())
        break;
    outfile.write((char*)&s, sizeof (s));
}


infile.close();
outfile.close();


}

void srcRec(Rec&Job,fstream &infile,char fname[])
{
    cout << "Allowing the user to open a specific record.\n";
    infile.open(fname, ios::in | ios::binary) ;

    if(infile.fail())
    {
        cout << "Could not access file.\n";
    }
    else
    {
        int position;   //user's position

        //gets user's position
        cout << "Please the record you would like to read: ";
        cin >> position;
        //ignore luki
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        //find the specific record, read it, and display it
        infile.seekp((position - 1)*sizeof(Job));
        infile.read((char*) &Job, sizeof(Job));
    cout<<"|===============================================|"<<endl;
    cout<<"| ID       | FIRST         | LAST               |"<<endl;
    cout<<"|===============================================|"<<endl;
    cout<<left<<"| "<<setw(9)<<Job.id<<"| ";
    cout<<left<<setw(14)<<Job.fname<<"| ";
    cout<<left<<setw(19)<<Job.lname<<"|"<<endl; 
    }

    //clears and closes the file
    infile.clear();
    infile.close();
}


void modRec(Rec &J,fstream &outfile, char fname[])
{
    int position,   //user's position
        cntr = 0;   //marks the current record within the file

    cout << "Modifying a record.\n";

    //open the two files
    outfile.open(fname, ios::out | ios::in | ios::binary);

    //get the user's desired position
    cout << "please enter the record you would like to modify: ";
    cin >> position;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout << endl;

    if(outfile.fail())
    {
        cout << "File could not be read.\n";
    }
    else
    {
        //find the desired record
        outfile.seekp((position - 1)*(sizeof(J)));

        //get the user's modification
        cout<<"Please enter ID number :";
        cin>>J.id;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout<<"\nPlease enter first name: ";
        cin.getline(J.fname,SIZE);
        cout<<"\nPlease enter lastname: ";
        cin.getline(J.lname,SIZE);

        //write over the desired record
        outfile.write((char*) &J, sizeof(J));
    }

    //closes the files
    outfile.close();
}


void sort()
{
    int StructureSize, Idx1, Idx2;

    FILE * binaryFile;
    binaryFile = fopen("c:/solident.dat","rb+");
    Rec Index, IndexTemp;
    StructureSize = sizeof(Index);
    fseek(binaryFile, 0, SEEK_END);
    int fileSize = ftell(binaryFile);
    rewind(binaryFile);


    for (Idx1 = 0; Idx1 < fileSize; Idx1 += StructureSize)
    {
        for (Idx2 = 0; Idx2 < fileSize - StructureSize; Idx2 += StructureSize)
        {
            fread(&Index, StructureSize, 1, binaryFile);
            fread(&IndexTemp, StructureSize, 1, binaryFile);

            if (Index.id > IndexTemp.id)
            {
                fseek(binaryFile, -(StructureSize * 2), SEEK_CUR);
                fwrite(&IndexTemp, StructureSize, 1, binaryFile);
                fwrite(&Index, StructureSize, 1, binaryFile);
                fseek(binaryFile, -StructureSize, SEEK_CUR);
            }
            else
            {
                fseek(binaryFile, -StructureSize, SEEK_CUR);
            }
        }

        rewind(binaryFile);
    }

    fclose(binaryFile);
}

2 个答案:

答案 0 :(得分:0)

我不知道,这段代码似乎存在一些问题。这里只是其中一个

int request=1,current;

...

while (!infile.eof())
{    
      s.id=current; 
      if (current!=request)

在此代码中,您没有给current一个值,但您仍在使用该变量。这是未初始化的变量,这是您的代码无法正常工作的一个原因。

我想知道你是否打算写

      current=s.id; 

代替?这会更有意义。

尝试使用这样的循环读取文件

infile.open("c:/solident.dat",ios::in|ios::out|ios::binary);
if (!infile.is_open())
    cout << "infile not open\n";
outfile.open("c:/temp.dat",ios::out|ios::binary|ios::trunc);
if (!outfile.is_open())
    cout << "outfile not open\n";
for (;;)
{
    infile.read((char*)&s, sizeof s);
    if (infile.eof())
        break;
    current = s.id; 
    if (current != request)
        outfile.write((char*)&s, sizeof s);
}
infile.close();
outfile.close();

如果我是你,我不会使用fail()。我认为用它来检测真正的读写失败是极不可能的。它更可能是文件错误结束或打开文件失败。

答案 1 :(得分:0)

@john。谢谢! 第一部分有效,但是尝试了     重命名(tempname,destination)不起作用: (目标文件存在)

虽然文件temp.dat现在包含记录减去已删除的记录,但输出不会写入solident.dat文件(它保持不变)

//所以我尝试从文件中读取每个rec并将每个记录写入dest文件:

infile.open("c:/temp.dat)",ios::in|ios::binary);
outfile.open("c:/solident.dat)", ios::out|ios::binary|ios::trunc);
infile.read((char*)&s, sizeof s);
for (;;) 
{
if (infile.eof())
    break;
infile.read((char *)&s, sizeof (s));
outfile.write((char*)&s, sizeof (s));


}

infile.close(); outfile.close();

我的理解是,outfile和infile非常简单:fstream.open,close,clear,它应该可以工作(我想)。虽然我错过了一些必不可少的东西,因为程序中的简单删除二进制结构函数似乎很受欢迎,而且我已经在圈子中转了几天:部分工作,然后我添加几行代码和一个函数失败或整个程序失败。我倾向于将它归咎于编译器或devc ++ :)但我确定它必须是无效的代码!

感谢您的帮助!