I completed a test today that didn't go so well. The last question dealt with binary files. For the review, he told us we had to go over seekg, tellg, and read and write methods.

On the test there was a class that could find a record (with a record number) using methods to search a binary file.

The problem asked us to write a method:
bool Class_name::find_a_record(ifstream& is, string name)
{
}

The class had a private variable: char m_name[25];

I couldn't figure out how to write a method to search for the record with a string name in a binary file! Any help? I put down trash for my answer. Something with is.seekg((char*)Class, sizeof(&variable)) or something like that in some if statement with EOF. I was working on this with 10 min to spare. UGH. The UML diagram took too long. And I still can't figure out what the answer could be. Any takers? I don't get my test back till Monday and it's killing me.

Dani AI

Generated

Short version: 's approach — scan the file record-by-record and compare the stored name to the search string — is exactly what instructors expect on that kind of test. A few practical clarifications that show why it works and what trips people up on exams.

Make sure the record type is safe for raw I/O. If the class contains std::string, virtual functions, or pointers, you cannot read raw bytes into it. Raw binary reads are safe only for a POD-like layout (fixed-size char m_name[25] is fine). Also open the file in binary mode (std::ifstream in("file.bin", std::ios::binary)).

When comparing the fixed-length char m_name[25], do not assume it is null-terminated. Safely build an std::string from the buffer before comparing:

size_t len = 0;
while (len < 25 && rec.m_name[len] != '\0') ++len;
std::string recName(rec.m_name, len);
if (recName == name) { /* found */ }

Using tellg and seekg to get or reposition a record is straightforward once you know where the stream is. After a successful read the stream position is after that record; to get the record start do:

auto after = is.tellg();
auto recSize = static_cast<std::streamoff>(sizeof(Class_name));
auto start = after - recSize;
std::size_t recordNumber = static_cast<std::size_t>(start / recSize);
is.seekg(start); // reposition if you need to overwrite

Quick exam/debug checklist: open with ios::binary; ensure any writes used strncpy (and force m_name[24] = '\0'); check file size (seekg(0, ios::end) then tellg()) is a multiple of record size; use std::fstream (read+write) if you must update a found record. Practicing a tiny program that writes a few fixed records then searches them will make seekg/tellg feel natural.

Recommended Answers

All 2 Replies

Pretty simple, really

bool Class_name::find_a_record(ifstream& is, string name)
{
     Class_name n;
     is.seekg(0, ios::begin); // start at beginning of the file
     // while not end-of-file or error
     while( is.read( (char*)&n, sizeof(Class_name) )
     {
            if( name == n.name) // if found
            {
                  return true;
            }
     }
     return false;
}

Thank you. I understand the code and it looks so easy, but I'm not sure I had enough practice manipulating the methods seekg/tellg and read/write. I knew how they worked, but I never put them in practice (nor did our homework had us put them into intuitive practice). I feel so demoralized. The whole class was in an uproar about this problem, lol.

Pretty simple, really

bool Class_name::find_a_record(ifstream& is, string name)
{
     Class_name n;
     is.seekg(0, ios::begin); // start at beginning of the file
     // while not end-of-file or error
     while( is.read( (char*)&n, sizeof(Class_name) )
     {
            if( name == n.name) // if found
            {
                  return true;
            }
     }
     return false;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.