我正在编写图书馆管理程序。我有一个文件 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
答案 0 :(得分:2)
问题是您覆盖了读取的文件。因此,如果一行变长,则您将覆盖下一行的字符。
当002
变成02
而不是2
时,我假设文件中的No
后跟一个空格。因此,如果我习惯于以可见的方式显示LineFeed,即文件的以下内容:
...NO <LF>002...
将被以下内容覆盖:
...1001<LF>02...
^ (end of the write, remaining chars unchanged)
因此,三个字符No
被100
覆盖,LineFeed被1
覆盖,而0
被新的LineFeed
覆盖。
如果要像在此处尝试一样就地编写,则必须确保在任何情况下每行的大小均保持固定。因此,“ No”后应跟与书号长度匹配的空格数。
这不是导致错误的原因,但是tellg()
返回std::streampos
,它可能比int
大得多。因此,我建议您选择:
auto oldPos = fp.tellg(); // here you're sure it's the right type
还要注意,tellg()
/ seekg()
用于输入流,tellp()
/ seekp()
用于输出流。幸运的是,对于双向文件流,只有一个位置可以读写。但是对于其他类型的双向字符串,则无法保证(请参见this question)。
最后,如果重新定位的目标是覆盖最后一行,请阅读(发现)您应不时对其进行更新。