Pregunta

EDIT: originally I thought that this was due to the different IDE's I tested the program on. The problem seems to be narrowed down to the separate compilers that each IDE uses.

For an assignment in my introduction to C++ class, I needed to write a program that reads doubles from a file, and evaluates them, the outputs the contents to another .txt file

I wrote the program using Visual Studio 2012, and it reads the file as I would expect, and executes as expected

I believe my teacher uses Dev C++ so I compiled the same code in that IDE as well as Code::Blocks.

What I have noticed is that the get pointer behaves differently, and I believe this is due to the compiler. In Code::Blocks and Dev C++, after the first double (6.0) is read, inFile.tellg() returns 15. In VS2012, it returns 3.

What could I do to this program so that it will work in all IDE's?

The file to be read:
The first 3 numbers of each line are dimensions of a box, the next 2 are the diameter and height of a jar to fit in the box.

6.0 6.0 10.3 5.0 10.0
6.0 5.0 10.3 5.0 10.0
12.0 3.3 4.0 3.0 11.0
12.0 3.2 4.0 3.0 11.0
9.5 6.5 7.5 6.0 9.5
9.5 6.5 7.5 6.0 9.0
4.5 8.0 4.5 4.0 7.5
4.0 8.0 4.5 4.0 7.5
7.3 7.3 17.0 7.0 16.0
6.8 7.3 17.0 7.0 16.0
7.3 7.3 16.2 7.0 16.0
7.2 7.3 16.3 7.0 16.0

The expected output (Executed in VS2012):

           BOX                                 JAR
   L        W        H                 D        H     FITS?
===========================================================
  6.0      6.0     10.3               5.0     10.0     YES
  6.0      5.0     10.3               5.0     10.0      NO
 12.0      3.3      4.0               3.0     11.0     YES
 12.0      3.2      4.0               3.0     11.0      NO
  9.5      6.5      7.5               6.0      9.5      NO
  9.5      6.5      7.5               6.0      9.0     YES
  4.5      8.0      4.5               4.0      7.5     YES
  4.0      8.0      4.5               4.0      7.5      NO
  7.3      7.3     17.0               7.0     16.0     YES
  6.8      7.3     17.0               7.0     16.0      NO
  7.3      7.3     16.2               7.0     16.0      NO
  7.2      7.3     16.3               7.0     16.0      NO
===========================================================

The Output from Code::Blocks and Dev C++:

               BOX                                 JAR
   L        W        H                 D        H     FITS?
===========================================================
  6.0      6.0     10.3               5.0     10.0     YES
  0.3      5.0     10.0              12.0      3.3      NO
  1.0     12.0      3.2               4.0      3.0      NO
  5.0      6.5      7.5               6.0      9.5      NO
  5.0      7.5      6.0               9.0      4.5      NO
  0.5      4.0      7.5               4.0      8.0      NO
  4.0      7.5      7.3               7.3     17.0      NO
 16.0      6.8      7.3              17.0      7.0      NO
  0.0      7.3      7.3              16.2      7.0      NO
  6.0      7.2      7.3              16.3      7.0      NO
 16.0     16.0     16.0              16.6      7.2      NO
===========================================================

And finally the program:

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
bool hasDouble(ifstream&);  // prototype

int main()
{
    // initialize constants
    // MAX_BOX_LENGTH must be modified to evaluate boxes with one or more sides >= 100.
    const double ACCEPTABLE_CLEARANCE = 0.25, MAX_BOX_LENGTH = 100;
    const int WID = 9;

    // initialize variables
    ifstream inFile;
    ofstream outFile;
    bool data_In_File = true;
    bool jar_Fits = false;
double large_Box_Dim = 0, small_Box_Dim = 0, jar_D = 0, jar_H = 0, focus = 0;       

// Welcome User to Program
cout << "Welcome to the \"Jar Fit?\" utility.\n\n\nThis program will open the     \"P4Boxes.txt\" file"
    << " located in the same\ndirectory, and read the data from within it. The     program will "
    << "then\ndetermine if the jar provided will fit in the box provided,     with\nthe allowed "
    << "clearance. This data will be entered into the     file\n\"NCBoxesOutput.txt\" in the same "
    << "directory.\n" << endl;
system("PAUSE");

inFile.open("P4Boxes.txt"); // Open input file

// Check for errors opening file by looking for a double
if(!hasDouble(inFile))
{
    cout << endl << "There was an error opening the file.\n\nThe program will     now terminate."
        << endl;
    system("PAUSE");
    return 1;   
}
outFile.open("NCBoxesOutput.txt");  // Open output file

// Make output file header
outFile << setprecision(1) << fixed << showpoint << boolalpha << setw(WID * 2) << "BOX"
    << setw((WID * 4) + 1) << "JAR\n" << setw(WID) << "L " << setw(WID) << "W " << setw(WID) 
    << "H " << setw(WID * 2) << "D " << setw(WID) << "H " << setw(WID) << "FITS?" << "\n" 
    << setfill('=') << setw(WID * 7) << left << "    " << right << setfill(' ') << endl;

// Main program loop
while(data_In_File)
{
    jar_Fits = false;   // Reset variables for each iteration
    large_Box_Dim = 0;
    small_Box_Dim = MAX_BOX_LENGTH;
    for(int i = 0; i < 3; i++)  // Get box dimensions.
    {
        inFile >> focus;
        cout << "The read number is " << focus << " and the pointer is at " << inFile.tellg() << endl;
        system("PAUSE");
        if(focus > large_Box_Dim)
            large_Box_Dim = focus;  // For jar height comparison
        if(focus < small_Box_Dim)
            small_Box_Dim = focus;  // For jar width comparison
        outFile << setw(WID) << focus;
    }
    inFile >> jar_D >> jar_H;   // Get jar Dimensions
    outFile << setw(WID * 2) << jar_D << setw(WID) << jar_H;
    jar_D += ACCEPTABLE_CLEARANCE;  // Account for needed clearance
    jar_H += ACCEPTABLE_CLEARANCE;
    if((jar_D <= small_Box_Dim) && (jar_H <= large_Box_Dim))    // Does jar fit?
        outFile << setw(WID) << "YES\n" << endl;
    else
        outFile << setw(WID) << "NO\n" << endl;
    data_In_File = hasDouble(inFile);   // is there another double in file?
}
outFile << setfill('=') << setw(WID * 7) << left << "    " << right << setfill(' ') << endl;
cout << "\nThe program has executed successfully.\n" << endl;   // Inform user
system("PAUSE");
return 0;   
}

bool hasDouble(ifstream& inFile) // This function checks the file for for a double
{
    double test = 0;
int place = 0;  
place = inFile.tellg();     //This records the location of the get pointer  
if(inFile >> test)
{
    inFile.seekg(place);    // If a double is found, the point is returned to previous location.
    return true;
}
else
    return false;   
}

I apologize for the code dump, but I have been looking and cannot find a solid explanation for this or for how to fix it.

¿Fue útil?

Solución 3

While I appriciate everyone's help in finding what the source of the issue was, my teacher was able to provide a solution to the problem.

Original Code:

bool hasDouble(ifstream& inFile) // This function checks the file for for a double
{
    double test = 0;
    int place = 0;  
    place = inFile.tellg();     //This records the location of the get pointer  
    if(inFile >> test)
    {
        inFile.seekg(place);    // If a double is found, the point is returned to previous location.
        return true;
    }
    else
        return false;   
}

Replacement code:

bool hasDouble(ifstream& inFile) // This function checks the file for for a double
{
    double test = inFile.get();
    if(inFile.good())
    {
        inFile.unget();
        return true;
    }
    else
        return false;   
}

I've heard that using ifstream.good() is a no no for reading the end of a file, but in this simple example, it was the quickest solution.

Otros consejos

I cannot see anything wrong with the code as such.

Looking at the input data and comparing it with the numbers you get, it seems clear that after a set of five numbers have been read in, the read skips on by nine characters. This is clearly because of the call to hasDouble() at the end of the while loop - you have already shown that tellg cannot be relied upon and hasDouble needs it to work.

So, to make the code work on all IDEs you need to replace the use of hasDouble in the loop with some other way of detecting that you have reached the end of the file.

I really cannot say why tellg is behaving differently, but it looks to me like it's broken in Code::Blocks and Dev C++. It may be that we are expecting it to behave better than it is.

May be the input file P4Boxes.txt differs? It is really unclear what directory will be current working directory with all those IDEs and what P4Boxes.txt are there... Else it is a bug ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top