• Reading from a binary file in C++

    Abhey Member

    Reading from a binary file in C++

    I am trying to write a program which display 10 records at a time from the binary quote file. Program starts by displaying the first 10 days from the quote file. The program takes a single character input and responds as follows:

    “n” displays the next 10 days of quotes
    “p” displays the previous 10 days of quotes
    “b” resets the quote display to the first 10 days of the file
    “e” display the last 10 days of the file
    “q” exits the program

    I need to make sure “n” and “p” do not attempt to read before the beginning or after the end of the file data.

    This is how i solved the problem. for user input, ‘q’, ‘b’, and ‘e’ the program works fine. However, I am having program with implementing cases ‘p’ and ‘n’ and will be glad if annoy can help. The number of line in the binary file is 5101. Thanks in advance.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int FLENGTH = 5101;      // maximum length of file
    
    struct Quotes               // structure for quote variables
    {
       char date[11];            // character strings to hold date from quotes
       double open;            // variable to store open price
       double high;            // variable to store high price
       double low;               // variable to store low price
       double close;            // variable to store close price
       long volume;            // variable to store volume price
       double adjusted;         // variable to store adjusted closed price
    };
    
    char getchoice();            // function get which package customer is subscribed to
    void showRec(Quotes record);   // function display quotes for a day
    
    int main()
    {
       Quotes spy;               // create of quote struct
       char choice;            // character for user input
       int current_pos = 0;      // integer to tract current position
    
       ifstream inFile("spy.dat", ios::in | ios::binary);         // open the spy.dat file in binary and read only mode
    
       if (!inFile)                                    // check to see if file exist
       {
          cout << "Error opening file . Program aborting" << endl;
          return 0;
       }
    
       cout << "Displaying first 10 days of quote" << endl << endl;
    
       while (current_pos < 10)
       {
          inFile.seekg(current_pos * sizeof(spy), ios::beg);
    
          inFile.read(reinterpret_cast(&spy), sizeof(spy));
          showRec(spy);
          current_pos++;
       }
       
       do
       {
          cout << endl;
          choice = getchoice();
          cin.clear();
          cout << endl;
    
          switch (choice)
          {
          case 'n':
             cout << "Displaying next 10 days of quote" << endl << endl;
             current_pos = 0;
             while (current_pos < 10)
             {
                if (!inFile.eof())
                {
                   inFile.seekg(sizeof(spy), ios::cur);
                   inFile.read(reinterpret_cast(&spy), sizeof(spy));
                   showRec(spy);
                   current_pos++;
                }
                else if (inFile.eof())
                {
                   cout << "\nCannot read beyond this point" << endl;
                   cout << "Program is terminating\n" << endl;
                   return 0;
                }
                
             }
             cout << endl;
             break;
    
          case 'p':
             cout << "Displaying previous 10 days of quote" << endl << endl;
             current_pos = 0;
             inFile.seekg(-10 * static_cast(sizeof(spy)), ios::cur);
             while (current_pos < 10)
             {
                inFile.seekg(sizeof(spy), ios::cur);
                inFile.read(reinterpret_cast(&spy), sizeof(spy));
                showRec(spy);
                current_pos++;
             }
             cout << endl;
             break;
    
          case 'b':
             cout << "Resetting to first 10 days of quote" << endl << endl;
             inFile.seekg(0 * sizeof(spy), ios::beg);
             current_pos = 0;
             while (current_pos < 10)
             {
                inFile.read(reinterpret_cast(&spy), sizeof(spy));
                showRec(spy);
                current_pos++;
             }
             cout << endl;
             break;
    
          case 'e':
             cout << "Displaying last 10 days of quote" << endl << endl;
             current_pos = 0;
             inFile.seekg(-10 * static_cast(sizeof(spy)), ios::end);
             while (!inFile.eof() && current_pos < 10)
             {
                inFile.read(reinterpret_cast(&spy), sizeof(spy));
                showRec(spy);
                current_pos++;
             }
             cout << endl;
             break;
          }
    
       } while (choice != 'q');
    
       cin.get();
       return 0;
    }
    
    
    char getchoice()      // function get which package customer is subscribed to   // function to get package type
    {
       char choice;      // get package type
    
       while (true)
       {
          cout << "Enter 'n' to display the next 10 days of quotes" << endl;
          cout << "Enter 'p' to display the previous 10 days of quotes" << endl;
          cout << "Enter 'b' to reset the quote display to the first 10 days of the file" << endl;
          cout << "Enter 'e' to display the last 10 days of the file" << endl;
          cout << "Enter 'q' to quit the program" << endl;
          cout << "Input Choice: " << flush; cin.get(choice); cin.clear();                  // get the package type
          cout << endl;
          choice = tolower(choice);                              // convert package character to upper case
    
          if (choice == 'q')
          {
             cout << "Program is terminating" << endl;
             exit(1);
          }
          if ((cin.fail()) && (choice != 'n') && (choice != 'b') && (choice != 'p') && (choice != 'e'))
          {
             cin.clear();                                    // cin.clear() resets any error flags on the stream
             cin.ignore(numeric_limits  ::max(), '\n');      // will flush the input stream of garbage
    
             cout << "\n" "Hey, that's not a valid input for the choice type!\n";   // prompting user for correct package
             cout << endl;
          }
          else // Return a a valid package
          {
             cin.ignore(numeric_limits  ::max(), '\n');
             break;
          }
       }
       return choice;
    }
    
    void showRec(Quotes spy)
    {
       cout << left << spy.date << right << setw(8) << fixed << setprecision(2) << spy.open << setw(10);
       cout << setw(10) << spy.high << setw(10) << spy.low << setw(10) << spy.close << setw(12) << spy.volume;
       cout << setw(10) << spy.adjusted << endl;
    } 
    
  • Fierro Member

    What is the actual structure of the binary file? Because your definition of “Quotes” is odd. First of all, you have an 11-byte date char array. Yet the actual space taken by it will be 16 bytes, since it is followed by a double and by default compiler aligns doubles to a multiple of 8 offset. Another problem is that you use “long” type in your definition, which means that depending on the actual binary structure, it will work either only when compiled in x86 mode or in x64 mode, because long has a different size on those. Although it might still accidentally work due to the double after it being aligned to the same place anyway.

  • Adan Member

    Rather than doing ‘sizeof(spy)’ constantly, initialise a variable or create a constant at the beginning. looking at that might give you a clue as per the previous response.

Viewing 2 reply threads
  • You must be logged in to reply to this topic.