Click to See Complete Forum and Search --> : Reading data from file


kaftab
June 26th, 2002, 03:27 PM
Hi Gurus,

I have this problem. I am reading data from a file, simple text lines. The program works fine on windows, however, on unix, it reads the last line twice ... I am perplexed.

Here's the code:


while(!(dataFile.eof() || dataFile.bad() || dataFile.fail()))
{
char buffer[HPGL_TOOL_MAX_LINE_LENGTH+1];

dataFile.getline(buffer, HPGL_TOOL_MAX_LINE_LENGTH);

cout << "buffer = " << buffer << endl;

// Add to the part list

partNameList.push_back(buffer);
}


The output (on unix) is:

buffer = /if/21174/2117400-1.prt
buffer = /if/21378/2137813-0.prt
buffer = /if/21378/2137813-0.prt

The data file is:

/if/21174/2117400-1.prt
/if/21378/2137813-0.prt

Please help!
Kamran

PaulWendt
June 26th, 2002, 04:54 PM
What OS and compiler are you using? I've run the thing on Windows NT 4.0 SP6a, HP-UX 10.20 with gcc 3.1, and some digital unix box with gcc 3.0 and the output is the same on each. I'm guessing it's your compiler's implementation of getline().

UX1:/data/pwendt_ux1/test/exe>./str_block
buffer = /if/21174/2117400-1.prt
buffer = /if/21378/2137813-0.prt

UX1:/data/pwendt_ux1/test/exe>gcc --version
gcc (GCC) 3.1
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

--Paul

Axter
June 26th, 2002, 10:12 PM
You should use the global getline function instead.
The global getline function works with an std::string.

Example:

while(!(dataFile.eof() || dataFile.bad() || dataFile.fail()))
{
std::string MyStrBuffer;
std::getline(dataFile, MyStrBuffer);
cout << "MyStrBuffer= " << MyStrBuffer<< endl;

// Add to the part list

partNameList.push_back(MyStrBuffer);
}

Bob Davis
June 27th, 2002, 08:09 AM
I think the problem in your code is due to how your loop works. The .eof() condition is not triggered until after you try to read past the end of the file. For instance, when you read the last line of the file, .eof() is not triggered, so the loop continues for one more iteration. You try to get another line from the stream, but it finds that there is no more data, leaves your buffer intact, and sets the eof bit. The only strange thing is that the buffer remains holding the same value between loop iterations. I'm guessing that your compiler found a simple optimization to make, and did not reallocate the buffer every iteration through your loop, like it is in your code. Just an efficiency thing, but it's best to put things like that, where you're allocating an object or array, outside the loop so they don't get done every time through. Anyway, I digress. Try this:

char buffer[HPGL_TOOL_MAX_LINE_LENGTH+1];
dataFile.getline(buffer, HPGL_TOOL_MAX_LINE_LENGTH);

while(!(dataFile.eof() || dataFile.bad() || dataFile.fail()))
{
// If we're in here, then we know we got good data last time
cout << "buffer = " << buffer << endl;

// Add to the part list

partNameList.push_back(buffer);

// Get the next set of data, but make sure it's good before we do anything with it
dataFile.getline(buffer, HPGL_TOOL_MAX_LINE_LENGTH);
}


This should work fine, I think. If I'm totally off, someone please correct me, it's entirely possible that I am. :)

kaftab
June 27th, 2002, 08:44 AM
Thanks for your replies.

I am using windows 2000 with VC++ 6.0, and hpux 10.20 with aCC compiler.

Bob, I tried the algorithm that you provided, and it works fine on both OSs.

Thanks much!

Kamran

kaftab
June 28th, 2002, 08:58 AM
Actually, still not working! :(

The above algorithm works for unix, but now reads one line less on windows!

Axter, I tried your suggestion, works on unix, but fails on windows, here's the code


while(!(dataFile.eof() || dataFile.bad() || dataFile.fail()))
{
string buffer; // string is already using the std namespace

#ifdef _MSC_VER
std::getline(dataFile, buffer);
#else
getline(dataFile, buffer);
#endif


if (buffer.size() <= 0)
continue;

// Add to the part list
partNameList.push_back(buffer);

}



It works on unix, but get compile error on windows as follows:

error C2780: 'class std::basic_istream<_E,_Tr> &__cdecl std::getline(class std::basic_istream<_E,_Tr> &,class std::basic_string<_E,_Tr,_A> &,const _E)' : expects 3 arguments - 2 provided
D:\Program Files\Microsoft Visual Studio\VC98\INCLUDE\string(149) : see declaration of 'getline'

I tried with 3 arguments

std::getline(dataFile, buffer, ' ');

Still compile error:

error C2784: 'class std::basic_istream<_E,_Tr> &__cdecl std::getline(class std::basic_istream<_E,_Tr> &,class std::basic_string<_E,_Tr,_A> &,const _E)' : could not deduce template argument for 'class std::ba
sic_istream<_E,_Tr> &' from 'class ifstream'

Philip Nicoletti
June 28th, 2002, 09:26 AM
The following worked under :

Windows/VC++
Irix/GNU g++
Linux/pgCC (Portland Group C++ compiler)



#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
ifstream infile("input.txt");
if (!infile)
{
cout << "Problem openning file" << endl;
return 1;
}

string buffer;

while (getline(infile,buffer))
{
cout << buffer << endl;
}

return 0;

}

PaulWendt
June 28th, 2002, 09:32 AM
I've tried your original code on Visual Studio 6.0 SP5, gcc 3.0, gcc 3.0.4, and gcc 3.1. I don't think there's a problem with your original code and I'd guess your aCC compiler has "issues". Try to download gcc; it's open-source, but you'll probably have to build it yourself, as there don't seem to be too many 10.20 binaries out there. If you're going to build 3.1, I suggest you get 2.95.2 and build that first; I was unable to build 3.1 out of the box on our hp 10.20 system. Also, make sure you read the platform-specific configuration notes; you'll need gnu's binutils assembler and gnu's make and everything to install it. I'd test your code on aCC myself, but I don't have it on our 10.20 system.