簡體   English   中英

從 c++ 中的文件中刪除特定行

[英]Deleting specific line from file in c++

我希望用戶輸入學生的卷號,然后在我的文件中我想刪除該特定記錄。

假設我的文件包含以下信息

1 Abhi 92
2 Ravi 89
3 Kiran 45

用戶輸入2,然后我希望文件更改為:

1 Abhi 92
3 Kiran 45

這怎么可能?

編輯

這是這個項目的一部分,我想創建另一個案例,上面寫着刪除:

#include<iostream>
#include<stdlib.h>
#include<fstream>
using namespace std;
class Students
    {
        private:

            int roll_number;
            char name[80],dummy;
            float marks;
            char grade;
        public:
            void read_info()
            {
                calc_grade();
                cout<<roll_number<<"\t"<<name<<"\t\t\t"<<marks<<"\t\t"<<grade<<endl<<endl;
            }
            void write_info()
            {
                cout<<"Roll Number: ";
                cin>>roll_number;
                cin.get(dummy);
                cout<<"Name: ";
                cin.get(name,80);
                cin.get(dummy);
                start:
                cout<<"Marks: ";
                cin>>marks;
                if(marks < 0 || marks > 100)
                {
                    cout<<"Invalid"<<endl;
                    goto start;
                }
                cin.get(dummy);
            }
            void calc_grade()
            {
                if(marks>=80)
                    grade = 'A';
                else if(marks>=60)
                    grade = 'B';
                else if(marks>=40)
                    grade = 'C';
                else if(marks>=20)
                    grade = 'D';
            }
            int return_roll()
            {
                return roll_number;
            }
            float return_marks()
            {
                return marks;
            }
    };
int main()
    {
        int start_swit;
        do
        {
            system("pause");
            system("cls");
            cout<<"\t\t\t\t\tStudents Database"<<endl;
            cout<<"------------------------------------------------------------------------------------------------------------------------"<<endl;
            cout<<"------------------------------------------------------------------------------------------------------------------------"<<endl;
            Students s;
            fstream fil;
            char ch;
            int search_rn;
            cout<<"1.Read\t\t2.Write\t\t3.Specific student\t\t4.Topper"<<endl<<endl;
            cin>>start_swit;
            switch(start_swit)
                {
                case 1:
                    {
                        system("cls");
                        fil.open("studentdata.bin",ios::in|ios::binary);
                        cout<<"Roll.N\t  Name\t\t\tMarks\t\tGrade"<<endl;
                        cout<<"-----------------------------------------------------"<<endl;
                        while(fil.read((char*)&s,sizeof(s)))
                        {
                            s.read_info();
                        }
                        fil.close();
                        break;
                    }
                case 2:
                    {
                        system("cls");
                        fil.open("studentdata.bin",ios::in|ios::out|ios::binary|ios::app);
                        ch = 'y';
                        do{
                            s.write_info();
                            fil.write((char*)&s,sizeof(s));
                            cout<<"Do you want to enter more records?: ";
                            cin>>ch;
                        }
                        while(ch == 'y');
                        fil.close();
                        break;
                    }
                case 3:
                    {
                        int found = 0;
                        fil.open("studentdata.bin",ios::in|ios::binary);
                        cout<<"Enter the roll number of the student: ";
                        cin>>search_rn;
                        while(fil.read((char*)&s,sizeof(s)))
                              {
                                  if(search_rn == s.return_roll())
                                  {
                                      cout<<"Roll.N\t\tName\t\tMarks\t\tGrade"<<endl;
                                      cout<<"-----------------------------------------------------"<<endl;
                                      s.read_info();
                                      found = 1;
                                      break;
                                  }
                              }
                        if(found != 1)
                            cout<<"Student not found"<<endl;
                        fil.close();
                        break;
                    }
                case 4:
                    {
                        float highest_marks = 0;
                        int roll_high;
                        fil.open("studentdata.bin",ios::in|ios::binary);
                        while(fil.read((char*)&s,sizeof(s)))
                            {
                                if(s.return_marks()>= highest_marks)
                                    {
                                            highest_marks = s.return_marks();
                                            roll_high = s.return_roll();
                                    }
                            }
                        fil.close();
                        fil.open("studentdata.bin",ios::in|ios::binary);
                        while(fil.read((char*)&s,sizeof(s)))
                              {
                                  if(roll_high == s.return_roll())
                                  {
                                      cout<<"Roll.N\t\tName\t\tMarks\t\tGrade"<<endl;
                                      cout<<"-----------------------------------------------------"<<endl;
                                      s.read_info();
                                      break;
                                  }
                              }
                        fil.close();
                        break;
                    }

                }//switch end
            }// Do while loop end
            while(start_swit>=1 && start_swit<=4);
        return 0;
    }// main() end

這是一種方法,

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

int deleteAtLine(const std::string file_name, std::vector::size_type lineNumber){
    //the memory storage medium
    std::vector<std::string> lines;
    //Reading the file to the storage
    {
        //opening the file for reading from it
        std::ifstream file(file_name);
        //checking if the file has been opened correctly
        if (not file.is_open()) {
            std::cerr << "can't open the file " << file_name << std::endl;
            return -1;
        }
        //Reading
        for (std::string one_line; std::getline(file, one_line);lines.push_back(one_line));
    }
    //Writing the storage to the file
    {
        //opening the file for writing to it
        std::ofstream file(file_name);
        //checking if the file has been opened correctly
        if (not file.is_open()) {
            std::cerr << "can't open the file " << file_name << std::endl;
            return -1;
        }
        //finding out the number of the lines
        const auto lines_count = lines.size();
        //writing
        for (std::string::size_type lines_counter(0); lines_counter < lines_count;){
            //checking the line number and writing the extra line if it is needed
            if(lines_counter != lineNumber) file << lines[lines_counter++] << std::endl;
        }
    }
    //returning 0 if there was no error to this stage 
    return 0;
}

首先打開文件進行閱讀:

        //opening the file for reading from it
        std::ifstream file(file_name);
        //checking if the file has been opened correctly
        if (not file.is_open()) {
            std::cerr << "can't open the file " << file_name << std::endl;
            return -1;
        }

然后讀取所有文件行並將其存儲在向量中:

        //Reading
        for (std::string one_line; std::getline(file, one_line);lines.push_back(one_line));

關閉文件的先前(只讀)版本后,再次打開它進行寫入,這次:

        //opening the file for writing to it
        std::ofstream file(file_name);
        //checking if the file has been opened correctly
        if (not file.is_open()) {
            std::cerr << "can't open the file " << file_name << std::endl;
            return -1;
        }

然后放回除所需行之外的所有行:

        for (std::string::size_type lines_counter(0); lines_counter < lines_count;){
            //checking the line number and writing the extra line if it is needed
            if(lines_counter != lineNumber) file << lines[lines_counter++] << std::endl;
}

你可以使用這個 function 像:

int main(int argc, char* argv[]) {

    std::string file_name;
    std::string::size_type lineNumber;

    std::cin >> file_name;
    std::cin >> lineNumber;

    return deleteAtLine(file_name, lineNumber);
}

祝你好運!

如果您想就地編輯文件,即不將整個文件加載到 memory 中,對其進行編輯,然后覆蓋舊文件,您可以使用隨機訪問方法用虛擬信息覆蓋已刪除的學生信息,這不會被閱讀。 這會讓你的文件有點混亂。 這段代碼我沒有測試過,但大體思路是使用fstream的seekg和tellg成員函數。

case 5:
    {
        int found = 0;
        long pos;   //stores file pointer position
        fil.open("studentdata.bin",ios::in|ios::binary);
        cout<<"Enter the roll number of the student to delete: ";
        cin>>search_rn;
        while(fil.read((char*)&s,sizeof(s)))
              {
                  if(search_rn == s.return_roll())
                  {
                      //returns file's write position
                      pos = fil.tellp();
                      //rewind the file pointer (sizeof type????)
                      fil.seekg((pos - sizeof(s)), ios::cur); //not ios::beg);
                      s.delete_info();
                      //overwrite the old date with dummy data
                      fil.write((char*)&s,sizeof(s));
                      fil.close();
                      found = 1;
                      break;
                  }
              }
        if(found != 1)
            cout<<"Student not found"<<endl;
        fil.close();
        break;
    }

//add this class method:
void delete_info() 
{
    roll_number = -1;
    name = "deleted";
    marks = 0.0;
    grade = ' ';
}

同樣,這段代碼沒有經過測試,但我認為偏移量是正確的,只要 sizeof(s) 返回一個 long。 但是,如上述答案所示,執行完整的文件讀入內存、編輯和覆蓋操作可能會更干凈。

這些類型的作業希望您能夠做幾件事:

  • 創建一個結構來存儲 <student> 信息
  • 將學生從文件讀入向量/數組/等
  • 查找並刪除所需的元素
  • 將修改后的向量/數組/ <student> 的任何內容寫回文件

這個是正常的。 使用其他方法修改文件的努力不會幫助您了解您應該學習的內容。

事實上,這是您通常應該處理所有文件 I/O 的方式。 文件之間的唯一區別是用於存儲文件數據的結構。

瀏覽一下您的代碼,您正在將單個記錄與它們的完整數據庫(向量/數組/列表/其他)混合存儲。 讓自己成為一個結構 / class / 任何一個學生,以及從 stream 讀取和寫入單個學生的方法。

然后添加讀取整個文件的功能。 它總是看起來像:

std::vector <Student> students;
Student student;
while (f >> student)  // or whatever function you create to read a student
{
  students.push_back( student );
}

Arrays(如果您使用的是 C 或尚未允許使用向量)的工作方式類似:

Student students[MAX_STUDENTS];
int num_students = 0;
while ((num_students < MAX_STUDENTS) and (f >> students[num_students]))
{
  num_students += 1;
}

訣竅是創建將讀取單個學生的函數。 使用提取運算符(如我上面的示例):

std::istream & operator >> ( std::istream & ins, Student & student )
{
  // use whatever method you think best to get a line from
  // 'ins' and parse it into the 'student' object. When 
  // done, return the stream:
  return ins;
}

你的 function 寫一個學生數據同樣簡單:

std::ostream & operator << ( std::ostream & outs, const Student & student )
{
  outs << student.roll_number;
  outs << student.name;
  outs << student.grade;
  outs << "\n";
  return outs;
}

這是如何做到的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM