1

I am writing program for Library Management. I have a file Student.dat which have four columns. Initially when no book is issued it looks like this.

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

After issuing book to '001'.

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

The roll number of second student becomes '02'.

This is complete issue function in 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();
    }

I want to know whether I have used oldPos variable correctly?

Edit: After assigning length of Issued Book No. as length of book number, I get repeated record.

 ---------------Students List ----------------
Roll No.                Name                    Book Issued             Issued Book No.
001                     Abhi                    1                       1001
001                     Abhi                    1                       1001
002                     Ashu                    0                       No
Christophe
  • 68,716
  • 7
  • 72
  • 138
coder
  • 143
  • 10

1 Answers1

2

The problem is that you overwrite the file that you read. So if one line would become longer, you'd overwrite characters of the next line(s).

As 002 becomes 02 and not 2, I'll assume that No in the file is followed by a whitespace. So if I use to show in a visible manner the LineFeed, the following content of your file:

...NO <LF>002...

will be overwriten with:

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

So the 3 chars No are overwritten with 100, the LineFeed is overwritten with 1 and the 0 is overwritten with the new LineFeed.

If you want to write in-place like you try here, you must ensure that the size of each line remains fixed in all circumstances. So "No" should be followed by the number of space needed to match the length of a book number.

Other remarks

It's not the cause of the error, but tellg() returns a std::streampos, which can be much larger than an int. So I'd recommend to prefer:

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

Note also that tellg()/seekg() are meant for input stream and tellp()/seekp()for output streams. Fortunately, for bidirectional file streams, there is only one position for reading and writing. But for other kind of bidirectional strings, this is not guaranteed (see this question).

Finally, if the goal of your repositionning is to overwrite the last line, read (and found) you should update it from time to time.

Community
  • 1
  • 1
Christophe
  • 68,716
  • 7
  • 72
  • 138