我正在为图书馆管理编写程序。我有一个文件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
问题是您覆盖了您阅读的文件。因此,如果一行变长,则会覆盖下一行的字符。
由于002
变成02
而不是2
,我会假设文件中的No
后跟一个空格。因此,如果我以可见的方式显示LineFeed,则文件的以下内容如下:
...NO <LF>002...
将被覆盖:
...1001<LF>02...
^ (end of the write, remaining chars unchanged)
所以3个字符No
被100
覆盖,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)。
最后,如果重新定位的目标是覆盖最后一行,请阅读(并找到),您应该不时更新它。