使用C++当我同时具有整数和字符数组时,如何将.txt文件中的数据作为链表的一部分访问

Using C++ how do I access data from a .txt file as part of a linked list when I have both integers and character arrays?

本文关键字:文件 txt 数据 访问 一部分 链表 C++ 整数 使用 数组 字符      更新时间:2023-10-16

我的问题是我在.txt文件中有许多文件类型int以及长度为50的char数组。我有一个链表(队列结构)程序,它本质上是一个事件日历,具有用于搜索特定条目、星期几、日期和消息(有关事件的信息)的索引。无需从文件中读取,我可以创建事件、删除事件、修改事件、显示所有事件或显示单个事件。我需要补充的是:1.程序终止时保存所有事件的能力。2.然后下次打开它时,我需要能够从.txt文件中读取您的信息,并为.txt文件中的每个事件创建一个新事件。我的文本文件条目.txt显示在代码的正上方。每行如下:1.索引,2.星期几(星期日=1),3。日, 4.月, 5.年, 6.消息。在下面,它在一行上显示每个事件,但在我的.txt文件中,每个数字/字符都是一个新行。

142242015
Baseball_game_at_7231332015
This_event_is_for_nothing351762015生日

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;
class Event{
protected:
    int index;
    enum DAY{Sunday=1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
    int date[3];
    char msg[50];
public:
    Event *next;
    Event *prev;
    Event(){
        next=NULL;
        prev=NULL;
    }
    int a;
    int day, day1;
    virtual void getindex(int b){   
        index=b;
    }
    virtual int getindex2(){
        a=index;
        return a;
    }
    virtual void getindex3(int c){
        index=c;
    }
    virtual void getday2(int d){
        day=d;
    }
    virtual void getdate2(int e, int f, int g){
        date[0]=e;
        date[1]=f;
        date[2]=g;
    }
    virtual void getmessage2(char h[50]){
        msg=h;
    }
        virtual void getdate(){
        cout<<"nOptions:n1. Sundayn2. Mondayn3. Tuesdayn4. Wednesdayn5. Thursdayn6. Fridayn7. SaturdaynWhich day would you like to select (enter the day): ";
        cin>>day;   
        cout<<"Please enter the date you would like to use (In the form of dd mm yyyy): ";
        cin>>date[0];
        cin>>date[1];
        cin>>date[2];
    }
    virtual void getcurrentdate(){
        time_t now=time(0);
        tm *local=localtime(&now);
        time_t y=1900+local->tm_year;
        time_t m=1+local->tm_mon;
        time_t d=local->tm_mday;
        time_t day1=local->tm_wday;
        day=day1+1;
        date[0]=d;
        date[1]=m;
        date[2]=y;
        }
    virtual void getmessage(){
        cout<<"Please enter your message (Use _ for any spaces): ";
        cin>>msg;
    }
    virtual void display(){
        cout<<"nThe index is: "<<index<<endl;
        switch(day){
        case Sunday:
            cout<<"The day of the week is: Sunday"<<endl;
            break;
        case Monday:
            cout<<"The day of the week is: Monday"<<endl;
            break;
        case Tuesday:
            cout<<"The day of the week is: Tuesday"<<endl;
            break;
        case Wednesday:
            cout<<"The day of the week is: Wednesday"<<endl;
            break;
        case Thursday:
            cout<<"The day of the week is: Thursday"<<endl;
            break;
        case Friday:
            cout<<"The day of the week is: Friday"<<endl;
            break;
        case Saturday:
            cout<<"The day of the week is: Saturday"<<endl;
            break;
        }
        cout<<"The date is: "<<date[0]<<"/"<<date[1]<<"/"<<date[2]<<endl;
        cout<<"The message is: "<<msg<<endl;
    }
};
 class Queue{
Event *Front, *Rear;
public:
Queue(){
        Front=NULL;
        Rear=NULL;
    }
int index;
int input4;
void newevent(int x){
        Event *temp;
        temp=new Event;
        if(Front==NULL){
                Front=temp;
                Rear=Front;
        temp->prev=NULL;
        }else{
                Rear->next=temp;
                temp->next=NULL;
        temp->prev=Rear;
        Rear=temp;
        }
    index=x;
    temp->getindex(index);
    cout<<"nOptions:n1. Enter a date manuallyn2. Use the current system date and timenWhat would you like to do: ";
    cin>>input4;
    switch(input4){
    case 1: // Get date manually
        temp->getdate();
        break;
    case 2: // Get current date
        temp->getcurrentdate();
        break;
    }
    temp->getmessage();
    temp->display();
    temp=NULL;
    }
int p;
Event *temp2;
void deleteevent(){
    Event *temp=Front;
    Front=temp->next;
    delete temp;
}
int c,d, input1, input3;
void modifyevent(int z){
    d=z;
    Event *temp=Front;
    while(temp!=NULL){
        for(c=1;c<d;c++){
            temp=temp->next;
        }
        input1=0;
        while(input1!=3){
            cout<<"nOptions:n1. Change the daten2. Change the messagen3. exitnWhat would you like to update: ";
            cin>>input1;
            switch(input1){
            case 1: // Change date
                cout<<"Options:n1. Enter a date manuallyn2. Use the current system date and timenWhat would you like to do: ";
                cin>>input3;
                switch(input3){
                case 1: // Get date manually
                    temp->getdate();
                    break;
                case 2: // Get current date
                    temp->getcurrentdate();
                    break;
                }
                break;
            case 2: // Change message
                temp->getmessage();
                break;
            case 3: // Exit
                break;
            default:
                cout<<"You entered an invalid number!";
            }
        }
        temp=NULL;
    }
}
int e,f;
void display(int z){
    f=z;
    Event *temp=Front;
    while(temp!=NULL){
        for(e=1;e<f;e++){
            temp=temp->next;
        }
        temp->display();
        temp->next;
        temp=NULL;
    }
}

void displayall(){
        Event *temp=Front;
        while(temp!=NULL){
                temp->display();
                cout<<"n";
                temp=temp->next;
        }
    }
int end;
int x;
int y;
int a;
int b;
int g[3];
char h[50];
void readfromfile(){ // This was my attempt at the problem
    ifstream fin;
    fin.open("entries.txt");
    Event *temp;
    x=1;
    y=1;
    end=1;
    while(fin>>y){
        end++;          
    }
    for(x;x<end;x++) {  // till end-of-file
        a=fin>>x;
        x++;
        b=fin>>x;
        x++;
        g[0]=fin>>x;
        x++;
        g[1]=fin>>x;
        x++;
        g[2]=fin>>x;
        x++;
        h=fin.getline(x);
        temp=new Event;
            if(Front==NULL){
                    Front=temp;
                    Rear=Front;
            temp->prev=NULL;
            }else{
                    Rear->next=temp;
                    temp->next=NULL;
            temp->prev=Rear;
            Rear=temp;
            }
        temp->getindex3(a);
        temp->getday2(b);
        temp->getdate2(g[0],g[1],g[2]);
        temp->getmessage2(h);
        temp=NULL;
    }
    fin.close();
}
void writetofile(){ //I understand this is blank, I havn't made it this far
}
};

int main(){
ofstream myfile;
myfile.open("entries.txt", ios::app);

cout<<"nWELCOME TO YOUR EVENT PLANNERn";
Queue a;
a.readfromfile();
int inp=0;
    int i=0;
int num=4;
    int type;
int counter=0;
int displayevent, modifyevent;
while(inp!=6){
        cout<<"nOptions:n1. Create new eventn2. Delete the oldest eventn3. Modify an eventn4. Display all eventsn5. Display a specific eventn6. Exit event plannernWhat do you want to do: ";
        cin>>inp;
        switch(inp){
        case 1: // New event
        a.newevent(num);
        num++;
        counter++;
            break;
        case 2: // Delete event
        a.deleteevent();
        counter--;
            break;
    case 3: // Modify event
        cout<<"nEnter the index of the event you would like to modify: ";
        cin>>modifyevent;
        a.modifyevent(modifyevent);
        break;
    case 4: // Display all events
        a.displayall();
            break;
        case 5: //Display single event
        cout<<"nEnter the index of the event you would like to display: ";
        cin>>displayevent;
        a.display(displayevent);
        break;
    case 6: // Exit event planner
        break;
    default:
        cout<<"You entered an invalid number"; 
        break;
        }
    }   
cout<<"The current number of events is "<<counter<<endl;
myfile.close();

return 0;
}

Queue.readfromfile() 是我读取文件并将文件中的每个事件作为新事件输入的尝试。我需要知道如何将文本文件的每一行保存为不同的内容,以便将其发送到上面类中的函数。Queue.writetofile() 被故意留空,因为我甚至还没有做到那么远。我应该能够很容易弄清楚。我想先读完文件。

由于您没有搜索StackOverflow,因此我将为您提供有关如何输入内容的内容的概要。

让对象读取其数据成员。

有几种方法可以做到这一点,但我们将坚持重载提取运算符。

class Event
{
private:
  int index;
  int day_of_week;
  unsigned int day;
  unsigned int month;
  unsigned int year;
  std::string message;  // Don't use char array here.
public:
  friend std::istream& operator>>(std::istream& inp, Event& e);
};
std::istream&
operator>>(std::istream& inp, Event& e)
{
  inp >> e.index;
  inp >> e.day_of_week >> e.day >> e.month >> e.year;
  std::getline(inp, e.message);
  return inp;
}

要读取Event代码片段,如下所示:

  Event e;
  my_input_file >> e;

读取和存储多个对象

您在许多Event中读取的循环如下所示:

  std::vector<Event> event_container;
  Event single_event;
  while (my_input_file >> single_event)
  {
    event_container.push_back(single_event);
  }

事件链表

链表是一个容器,可以重用于不同的对象。
要创建事件的链接列表,您应该使用 std::list

  std::list<Event> event_container;
  Event            single_event;
  while (my_input_file >> single_event)
  {
    event_container.push_back(single_event);
  }  

链表类赋值

如果你碰巧因为类作业而需要编写链表,你应该将列表的实现与数据隔离开来:

struct Node
{
  Node(Element * p_data = NULL)
  : p_element(p_data), next(NULL)
  { ; }
  Element * p_element;
  Node *    next;
};
struct Element_Linked_List
{
  Node *  p_head;
  Node *  p_tail;
  Element_Linked_List()
    : p_head(NULL), p_tail(NULL)
  { ; }
};

通过松散耦合容器中的数据(Element),您将能够在即将到来的其他作业中使用此链表。

扩展封装 -- 日期类

我建议你更进一步,将一些工作负载和复杂性转移到Date类中。

struct Date_DoW
{
  static const char dow_names[] =
  {
    "Day Of Rest", "Monday", "Tuesday", "Wednesday",
    "Thursday",    "Friday", "Saturday", "Sunday",
  }
  enum Day_Of_Week {Monday = 1, Tuesday, Wednesday,
                    Thursday, Friday, Saturday, Sunday};
private:
  void print_dow_name(Day_Of_Week dow, std::ostream& out)
  {
    out << dow_names(dow);
  }
  // etc...
};

你会把上面的课程增加几天、几个月和几年。

将日期重构为单独对象的一个优点是,您可以单独测试它,使其正常工作,而不必重新编译它。 您还可以在其他作业中重复使用它。

我会通过使用内置的 getline() 函数将文件的每一行转换为字符串,然后单独解析每个字符串来做到这一点。您可能还需要考虑在输入文件中使用分隔符来帮助解析过程。

编辑:这是我几个月前编写的程序的一个例子。该程序可以找到在一张或多张 LP 唱片上排列歌曲列表的所有可能方式。这是解析输入文件的程序部分:

vector<song> songs;
string input, title, min, sec, infile;
ifstream inputStream;
cout << endl << "Enter input file name:" << endl;
getline(cin, infile);
inputStream.open(infile, ios::in);
while (inputStream.good() && !inputStream.eof())
{
    getline(inputStream, input);
    input = regex_replace(input, regex("^\s+"), "");
    input = regex_replace(input, regex("\s+"), " ");
    if (input != "" && input[0]!='#') // # symbol can be used to comment out lines in the input file
    {
        title = input.substr(0, input.find_last_of(" "));
        min = input.substr(title.length() + 1, input.find_last_of(":") - input.find_last_of(" ") - 1);
        sec = input.substr(title.length() + min.length() + 2, input.length() - (title.length() + min.length() + 2));
        songs.push_back(song(title, stoi(min), stoi(sec)));
    }
}
inputStream.close();

对regex_replace的调用只是为了从数据中删除任何无意的空格填充(如果保证输入文件没有多余的填充,则无关紧要)。重要的部分是我使用 getline(inputStream, input) 一次一行地检索文件中的数据,然后使用 std::string 的 .substr() 函数来解析分隔符上的数据(如果您知道正在解析的数据的确切长度,则不需要)。

作为参考,以下是输入文件的格式设置方式:

Custard Pie 4:13
The Rover 5:37
In My Time of Dying 11:04
Houses of the Holy 4:02
Trampled Under Foot 5:37
Kashmir 8:32
In the Light 8:46
Bron-Yr-Aur 2:06
Down by the Seaside 5:13
Ten Years Gone 6:32
Night Flight 3:36
The Wanton Song 4:10
Boogie with Stu 3:53
Black Country Woman 4:24
Sick Again 4:42