C ++中的文件处理:更新一行

问题描述 投票:1回答:1

我正在为图书馆管理编写程序。我有一个文件Student.dat,它有四列。最初,当没有发行书籍时,它看起来像这样。

     ---------------Students List ----------------
Roll No.                Name                    Book Issued        Issued Book No.
001                     Abhi                    0                  No
002                     Ashu                    0                  No

发出书到'001'后。

 ---------------Students List ----------------
Roll No.                Name                    Book Issued             Issued Book No.
001                     Abhi                    1                       1001
02                      Ashu                    0                       No

第二名学生的掷骰数变为“02”。

这是library.cpp中的完整问题函数

    void Library::book_issue()
    {
        //Some code
        fp.open("Students.dat", std::ios::in | std::ios::out);
        fp1.open("Books.dat", std::ios::in | std::ios::out);
//////////////////////////////////////////////////////////////////////
        int oldPos = fp.tellg();
        while (std::getline(fp, line) && !found_stu)
        {
            std::stringstream ss(line);
            ss >> roll_n >> s_name >> tkn >> issued_b_num;
               ////////////
            std::getline(ss, line);
            if (boost::iequals(roll_n, r_num))
            {
                found_stu = true;
                if (tkn == 0)
                {
                    std::cout << "Enter Book No. : ";
                    std::getline(std::cin, b_num);
                    while (fp1 >> book_n >> b_name >> a_name && !found_book)
                    {
                        if (boost::iequals(book_n, b_num))
                        {
                            Book::show_book(book_n, b_name, a_name);
                            found_book = true;
                            tkn = 1;
                            Student::reset_issued_book_num();
                            issued_b_num = book_n;
//////////////////////////////////////////////////////////////////
                            fp.seekg(oldPos);
                           fp << roll_n << " " << s_name << " " << tkn << " " << issued_b_num << '\n';
                            std::cout << "Book Issued Successfully\n";
                            break;
                        }
                    }
                    if (!found_book)
                    {
                        std::cerr << "Book does not exist\n";
                    }
                }
            }
        }
        if (!found_stu)
        {
            std::cout << "Student record does not exist\n";
        }
        fp.close();
        fp1.close();
    }

我想知道我是否正确使用了oldPos变量?

编辑:在指定Issued Book No.的长度作为书号的长度后,我得到重复记录。

 ---------------Students List ----------------
Roll No.                Name                    Book Issued             Issued Book No.
001                     Abhi                    1                       1001
001                     Abhi                    1                       1001
002                     Ashu                    0                       No
c++ fstream file-handling
1个回答
2
投票

问题是您覆盖了您阅读的文件。因此,如果一行变长,则会覆盖下一行的字符。

由于002变成02而不是2,我会假设文件中的No后跟一个空格。因此,如果我以可见的方式显示LineFeed,则文件的以下内容如下:

...NO <LF>002...

将被覆盖:

...1001<LF>02...
          ^         (end of the write, remaining chars unchanged)  

所以3个字符No100覆盖,LineFeed被1覆盖,而0被新的LineFeed覆盖。

如果您想在此处尝试就地编写,则必须确保每行的大小在所有情况下都保持固定。所以“否”之后应该是匹配书号长度所需的空格数。

其他言论

这不是错误的原因,但tellg()返回std::streampos,可能比int大得多。所以我建议更喜欢:

auto oldPos = fp.tellg();   // here you're sure it's the right type

另请注意,tellg() / seekg()用于输入流和tellp() / seekp()for输出流。幸运的是,对于双向文件流,只有一个位置可供读写。但是对于其他类型的双向字符串,这是不能保证的(参见this question)。

最后,如果重新定位的目标是覆盖最后一行,请阅读(并找到),您应该不时更新它。

© www.soinside.com 2019 - 2024. All rights reserved.