Чтение файлов в разных компиляторах C++

РЕДАКТИРОВАТЬ: первоначально я думал, что это из-за различных IDE, на которых я тестировал программу. Проблема, похоже, сужена до отдельных компиляторов, которые использует каждая IDE.

Для выполнения задания в моем введении в класс C++ мне нужно было написать программу, которая считывает дубликаты из файла и оценивает их, выводит содержимое в другой файл.txt.

Я написал программу с использованием Visual Studio 2012, и она читает файл, как я ожидал, и исполняется, как и ожидалось

Я считаю, что мой учитель использует Dev C++, поэтому я скомпилировал тот же код в этой IDE, а также в Code::Blocks.

Что я заметил, так это то, что указатель get ведет себя по-другому, и я считаю, что это связано с компилятором. В Code::Blocks и Dev C++ после считывания первого double (6.0) inFile.tellg() возвращает 15. В VS2012 возвращает 3.

Что я могу сделать с этой программой, чтобы она работала во всех IDE?

Файл для чтения:
Первые 3 числа каждой строки - это размеры коробки, следующие 2 - диаметр и высота банки, чтобы поместиться в коробку.

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

Ожидаемый результат (Выполнено в 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
===========================================================

Выход из Code::Blocks и 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
===========================================================

И наконец программа:

#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;   
}

Я прошу прощения за дамп кода, но я искал и не могу найти надежное объяснение этого или как это исправить.

3 ответа

Решение

В то время как я ценю помощь каждого в выяснении источника проблемы, мой учитель смог найти решение проблемы.

Оригинальный код:

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;   
}

Код замены:

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;   
}

Я слышал, что использование ifstream.good() - нет, нет для чтения конца файла, но в этом простом примере это было самое быстрое решение.

Я не вижу ничего плохого в коде как таковом.

Глядя на входные данные и сравнивая их с числами, которые вы получаете, становится ясно, что после считывания набора из пяти чисел чтение пропускается на девять символов. Это очевидно из-за вызова hasDouble() в конце цикла while - вы уже показали, что на Tellg нельзя положиться, и hasDouble нуждается в его работе.

Итак, чтобы заставить код работать на всех IDE, вам нужно заменить использование hasDouble в цикле другим способом определения того, что вы достигли конца файла.

Я действительно не могу сказать, почему TellG ведет себя по-другому, но мне кажется, что он сломан в Code::Blocks и Dev C++. Возможно, мы ожидаем, что он будет вести себя лучше, чем он есть.

Может быть входной файл P4Boxes.txt отличается? Действительно неясно, какой каталог будет текущим рабочим каталогом со всеми этими IDE и что там за файл P4Boxes.txt... Иначе это ошибка...

Другие вопросы по тегам