将文本文件读入链表 C++ 编辑 1:回答您的first comment总结编辑 1:

问题描述

我一直在尝试将文本文件读入链接列表。我面临的唯一问题是它不会读取所有条目。

我的学生课:

class Student // Student class which hold student data
{
private:
    char Name[15];
    char Roll_no[8];
    int Serial_no,FSC_marks,Entry_test_marks;
public:
    void Print() // Print student data
    {
        cout << "\n" << Serial_no << "\t"<< Roll_no << " " << Name << "\t" <<  FSC_marks << "\t\t" << Entry_test_marks << endl;
    }

    void Read(fstream &infile)
    {
        infile >> Serial_no;
        infile >> Roll_no ;
        infile.get(Name,15);
        infile >> FSC_marks >> Entry_test_marks; 
    }
}

链表类

class LinkList // Linked List 
{
    struct Node // structure for Node containing Object of Student class
    {
        Student info;
        Node* link;
    };
    Node* head;
    
public:
    
    Linklist() // default constructor
    {
        head = NULL;
    }
};

打印功能如下:

void LinkList::print() // Prints List of Students
{
    Node* temp = head;
        
    if(temp != NULL)
    {
        while(temp != NULL)
        {
            temp->info.Print();
            temp = temp->link;
        }
        
        cout<<endl;
    }
}

这是阅读功能

void LinkList::Readfromfile()
{
    fstream File;
    File.open("Lab_15.txt",ios::in);
    File.seekg(40);
    
    while(File)
    {
        Node* newnode = new Node();
        newnode->info.Read(File);
        newnode->link = NULL;
        
        if(head == NULL)
        {
            head = newnode;
        }
            
        else
        {
            Node* temp = head;
            while(temp->link != NULL)
            {
                temp = temp->link;
            }
                
        temp->link = newnode;
        }
    }
}

这里是文本文件的样子:

Serial_No   Roll_No Name    F.Sc    Entry_Test
1   19I-0777    Jame#s moriarty777  70
2   19I-0789    Sherlock    734 80
3   19I-0860    Holmes      843 88
4   19I-0884    Dave Bautista   732 54
6   20I-1003    Barry Allen#    712 32
7   20I-1004    Clark kent  632 15
8   20I-1015    Adam        658 67
9   20I-1034    Ahmad hussain   734 55
10  20I-1041    Bill ga#tes 811 98
11  20I-1054    Trump       888 45
13  20I-1057    Donald duck 576 67
14  20I-1903    Faiza#n Shahid  789 34
15  20I-1904    Umair Shahid    567 55
16  20I-1909    Abdullah    123 67
17  20I-1915    Ali         300 45

在原始文本文件中,我有大约 20 个条目,但我的代码只读取了大约 13 个。我在这里做错了什么?

解决方法

除了您没有提供析构函数等导致内存泄漏的事实,并且您没有使用可以节省您一些时间并且可能自己工作的 STL,我认为算法中没有明显的错误.

这里是我会搜索以发现错误的地方:

  1. 为什么要跳过文件开头的 40 个字符 (File.seekg(40);)?
  2. 您将运算符 >>get 函数混合使用。我因此产生了错误。
  3. 检查文件是否确实正确,并且您没有输入错误。

另外,正如其他人所指出的那样,当您插入新节点而不是再次遍历列表时,重新分配头部可能会更快。

,

问题在于您的 LinkList 构造函数的名称。

您将(假定的)构造函数命名为 Linklist 而不是 LinkList,这使得它不是构造函数,从而导致 head 指针未初始化。

除此之外,您可能仍然无法正确读取文件。完成后不要忘记关闭 File

编辑 1:回答您的first comment

确保您遵循有关 fstream 的一些参考,例如:

  1. istream::get 方法(fstream 继承 istream)读取直到达到 n - 1 个字符,或者直到找到分隔符(其中不包括分隔符本身)在输出参数中)。如果您不提供分隔符(例如仅使用 2 个参数调用方法:char* 和要读取的字符数,就像您为 Name 所做的那样),则它默认为换行('\n')。这意味着当您调用 infile.get(Name,15); 时,它实际上读取 14 个字符(并且我们不希望名称中有任何新行,因此这意味着它将始终从文本文件中读取 14 个字符),而不是 15 个字符想。因此,您需要将 Name 声明为 16 个字符并调用 infile.get(Name,16);。这样,您将读取 15 个字符而不是 14 个。空字符会自动附加到输入序列的末尾(即在 index 15 处,因为我们知道 15 个字符将是阅读),因此您无需担心。因此,您自己从名称中删除 '#' 字符意味着您会自动使每个名称长度为 14 个字符,而不是 15 个字符,这就解释了为什么 infile.get(Name,15); 在这种情况下会成功。
  2. 另一件需要注意的事情是,您可能应该忽略列 Roll_noName 之间的列分隔符。此字符可能是文本文件中的空格或制表符 ('\t')。使用 istream::ignore 方法(就在读取 Name 之前)忽略单个字符,如下调用:infile.ignore();
  3. 注意您的 skipg 调用和文件编码。你确定是 40 个字符?对我来说是 39,这真的取决于你的文件的内容。您可以尝试使用 istream::getlinegetlineignore 作为忽略第一行的替代方法。

总结编辑 1:

  1. 将每个 Student 的私有属性更改为:
private:
    char Name[16]; //Changed to 16 characters long,instead of 15.
    char Roll_no[9]; //Changed to 9 characters long,instead of 8.
    int Serial_no,FSC_marks,Entry_test_marks;
  1. 将您对文件中每个 Student 的阅读更改为:
void Read(fstream& infile)
{
    infile >> Serial_no;
    infile >> Roll_no; //'\n' is automatically appended.
    infile.ignore(); //Added this line to ignore the column separator between the number Roll_no and the Name.
    infile.get(Name,16); //Changed to read 15 characters instead of 14. '\n' is automatically appended.
    infile >> FSC_marks >> Entry_test_marks;
}
  1. 尝试使用 skipg 的参数(或自己计算字符数)。