【问题标题】:Reading text file into a linked list C++将文本文件读入链表 C++
【发布时间】:2021-09-25 21:49:16
【问题描述】:

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

我的学生课:

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 个。我在这里做错了什么?

【问题讨论】:

  • 您实际上可以将 head 替换为新节点并将其指向旧节点。或者,如果您关心订单,请跟踪tail,这样您就不必每次都遍历整个列表。
  • 代码是在读取前 13 行时停止,还是在打印前 13 行后停止?
  • 另外,您不要在每个字符数组(即Student::NameStudent::Roll_no)的末尾为null 字符 留出空间,这可能会导致问题。文件中的第 14 行是什么?您是否尝试在读取文件时打印列表的内容?既然只有20行,你能把它的全部内容贴出来吗?我认为文件的标题不是 40 个字符长。
  • @gthanop 代码只读取前 13 行。如果我在阅读文件时打印文件,输出是相同的。增加 Roll No 的大小没有任何改变,但是增加 Name 的大小导致只打印了大约 7 个条目。我已经更新了文本文件。 (名称中还有一些“#”,我需要删除它们,我可以搜索字符,但我应该如何从单词中删除/删除特定字符)

标签: c++ class linked-list file-handling singly-linked-list


【解决方案1】:

除了你没有提供析构函数和内存泄漏,而且你没有使用 STL 可以节省你一些时间并且可能会自己工作之外,我认为算法中没有明显的错误.

我会在这里搜索以发现错误:

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

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

【讨论】:

  • 我还没有学习/研究过 STL。我跳过了第一行(40 个字符),因为它包含序列号、名称等标题,我不想打印它。对于读取名称,只有 get 函数有效。我不能使用 >> 因为名称由 2 个单词组成,并且由于某种原因 getline 函数也失败了。是的,文件是正确的。
【解决方案2】:

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

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

除此之外,您可能仍在错误地读取文件。完成后不要忘记关闭File

编辑1:回答你的first comment

确保您遵循fstreams 上的一些参考信息,例如:

  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 个字符。null 字符 会自动附加到输入序列的末尾(即在 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 的参数(或自己数字符)。

【讨论】:

  • 感谢您指出构造函数的问题。我已经修复了它,但它仍然不能像想象的那样工作。我可能读错了文件,但我不明白。但是,如果我从名称中删除“#”字符,它几乎可以完美运行。知道为什么会这样吗?
  • 请阅读我的编辑 1总结编辑 1 部分。
  • 非常感谢您抽出宝贵时间帮助我解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多