Обработка файлов в C ++: обновление строки - PullRequest
0 голосов
/ 16 сентября 2018

Я пишу программу для управления библиотекой.У меня есть файл 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

1 Ответ

0 голосов
/ 16 сентября 2018

Проблема в том, что вы перезаписываете файл, который читаете.Таким образом, если бы одна строка стала длиннее, вы бы перезаписали символы следующей строки.

Поскольку 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() для выходных потоков.К счастью, для двунаправленных файловых потоков существует только одна позиция для чтения и записи.Но для других типов двунаправленных строк это не гарантируется (см. этот вопрос ).

Наконец, если ваша цель - перезаписать последнюю строку, прочитайте (и нашли), что вы должны время от времени обновлять ее.

...