|
-
June 26th, 2002, 03:27 PM
#1
Reading data from file
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:
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
-
June 26th, 2002, 04:54 PM
#2
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
-
June 26th, 2002, 10:12 PM
#3
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);
}
-
June 27th, 2002, 08:09 AM
#4
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.
-
June 27th, 2002, 08:44 AM
#5
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
-
June 28th, 2002, 08:58 AM
#6
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
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'
-
June 28th, 2002, 09:26 AM
#7
The following worked under :
- Windows/VC++
- Irix/GNU g++
- Linux/pgCC (Portland Group C++ compiler)
Code:
#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;
}
-
June 28th, 2002, 09:32 AM
#8
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.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|