Hi Zaldy, et al, On Sun, 2004-08-29 at 06:12 -0400, wrote: > Hi Zaldy > > The error I think is in while loop: > > > while(fin.eof() == false) { > > fin >> rn >> spl; > > } That is definitely an error. However, it's not what G++ complains about. What G++ complains about is that `std::ifstream' has only been forward declared, like namespace std { struct ifstream; } And not fully specified. My guess is, that you're using an older G++ (at least pre-3.3), and I don't have that, so I cannot reproduce your error, so the below comments refers only to the ISO/IEC standard. > > I am using root Version 3.10/01 28 November 2003 > > with gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5) Ah, as I guessed (sorry didn't see this one) > > Thanks in advance. > > Zaldy > > > > > > ===========================Compilation error message > > g++ -O -Wall -fPIC -Wno-deprecated -D_REENTRANT > > -I/CERN_SOFT/myroot/include/root -c -o HitInfo.o HitInfo.cc > > In file included from HitInfo.cc:3: > > HitInfo.hh:37:39: warning: no newline at end of file > > HitInfo.cc: In member function `void HitInfo::Write_To_RootFile(char*)': > > HitInfo.cc:19: aggregate `std::ifstream fin' has incomplete type and > > cannot be > > defined As you can see, this really has nothing to do with whether you're using ROOT or not. > > make: *** [HitInfo.o] Error 1 > > > > > > > > ============================Sample code > > #include <fstream.h> This header `fstream.h' is not in the C++ standard. It's an old obsolete header that is in G++ 3.x for backward compatibility. You should use #include <fstream> instead. > > #include <ifstream.h> This header `ifstream.h' does not exist in the C++ standard. It was a implementation specific header in the older G++ compiler, and should not be used. > > ..... > > ..... > > > > ifstream in; > > in.open("Filename.dat",ios::in); You do not need the second argument, unless you're using an older G++ on Digital Unix. Also, the two lines can be written as one: std::ifstream in("Filename.dat"); That simple. > > Int_t rn, spl; > > > > while(fin.eof() == false) { > > fin >> rn >> spl; > > } You do know this is wrong, as I can see from the code in your tar-ball. For those who do not know this, the above code will read in the last line of the input file twice (actually, it will not read the physical line twice, but it will assign the last two values of rn and spl twice). The reason for this, is that you test `ios_base::eof' _before_ reading from the file. One should always test for end-of-file and error conditions _after_ reading from the file. So the code should be 1' while (true) { 2' in >> rn >> spl; 3' if (in.eof()) break; 4' if (in.fail()) 5' throw std::runtime_error("Error while reading from file"); 6' } Why this is so, is a bit tricky at first. The old code was 1 while (!in.eof()) 2 in >> rn >> spl; The first time the program executes line 1, it is obviously false, as the `ifstream::open' merely checks if the file exists, and if so opens it. It has not read anything at that point, not even the EOF mark if the file is empty. The first time it executes line 2, it tries to read in two integers, skipping over whitespace. After execution of line 2, the cursor stands immediately after the last character of the last read integer. It has not read the next character, even if it's a new line, EOF mark, or similar. So on subsequent executions of line 1, the curser will stand just after the last character of the last integer, and has no idea what comes after that character. Hence, when the program reads the final numbers in the file in line 2, it will not know that the next character is the EOF mark, and the test in line 1 will evaluate to true. Therefor, the program merely executes line 2 once again. However, this time, when it tries to read in the first integer, it will encounter the EOF mark, and will do nothing to the variables subsequently, and execution of line 2 is stopped, while the variables rn and spl retains their old values. When line 1 is executed next, the test evaluates to false, and the loop is stopped. However, the body of the while loop was executed one too many times with the old values of rn and spl. To prevent this, one should _always_ check for EOF _immediately_ after reading in data, and take appropriate action if EOF is seen (for example, break out of a loop before pushing back some values in a container or similar). The C++ I/O library is very powerful, but one has to be careful to use it properly (like most of the C++ Standard Library :-) Oh, and the failure in line 4' and the subsequent exception thrown in line 5' is an excellent example of possible misuse of exceptions, unless we surround code with some thing like std::ifstream in("FileName.dat"); std::map<int,int> data; try { if (!in) throw std::runtime_error("Couldn't open file"); int rn, spl; while (true) { in >> rn >> spl; if (in.eof()) break; if (in.fail()) throw std::runtime_error("Error while reading from file"); data[rn] = spl; } } catch (std::exception& e) { in.close(); throw; } making sure that the program is in a good state after an error. Of course, the istream& operator>> and map::operator[](key_type), may throw too, so we have to be careful how we deal with the exceptions (whether it's re-thrown or not). Yours, -- ___ | Christian Holm Christensen |_| | ------------------------------------------------------------- | | Address: Sankt Hansgade 23, 1. th. Phone: (+45) 35 35 96 91 _| DK-2200 Copenhagen N Cell: (+45) 24 61 85 91 _| Denmark Office: (+45) 353 25 404 ____| Email: cholm@nbi.dk Web: www.nbi.dk/~cholm | |
This archive was generated by hypermail 2b29 : Sun Jan 02 2005 - 05:50:09 MET