I read a file. When I get an "*" at the beginnig, I write all the data
I read before to another file.
Code:
while(!feof(file))
{
fgets(file, line);
if (line[0]=='*')
{
... lenghty code here
WriteToFile(data);
data.clear();
}
else
{
data+=line;
}
}
// Now I'm here and still have some data stored in 'data'
Now I must call:
... lenghty code here
Is there any better way of doing this? I hate copy+paste programming.
Gernot,
It is just about possible to avoid calling the lengthy code twice, but
the solution is very ugly, not very maintainable and does not work in
all circumstances. Generally not practical in a real-life situation.
The main problem is that you need to trigger your lengthy code on two
different conditions:
- an asterisk at the start of a line
- EoF with unprocessed data remaining.
It is possible for the last line of the file to cause both of these
conditions at the same time, so you have to call the lengthy piece of
code twice for a single input line. If you can guarantee that the
last line of the file *never* starts with an asterisk then the
solution below will work. That just leaves the problems of low
maintainability and ugliness.
I think that your original code was much better.
rossum
#include <iostream>
#include <sstream>
#include <cstdlib>
//-------------------------------------
int main() {
using std::cout;
// Simulate input file with a stringstream
// std::stringstream in_file(""); // Works OK
std::stringstream in_file("First chunk \n"
"of data.\n"
"*Second chunk \n"
"of data.\n"
"*Last chunk \n"
// "of data.\n"); // Works OK
// "of data."); // Works OK
// "*of data.\n"); // Works OK
"*of data."); // FAILS!
// Process the file
std::string line_buffer;
std::string data_accumulator;
bool process_data;
do {
getline(in_file, line_buffer);
// Decide what we need to do
process_data = (line_buffer.size() > 0 &&
line_buffer[0] == '*');
if (in_file.eof() && !process_data) {
if (line_buffer.size() > 0) {
data_accumulator += line_buffer;
process_data = true;
}
else if (data_accumulator.size() > 0) {
process_data = true;
} // end if
} // end if
// Now do it
if (process_data) {
// Call lengthy_code() here
cout << data_accumulator << '\n';
if (line_buffer.size() > 0) {
line_buffer.erase(line_buffer.begin());
} // end if
data_accumulator = line_buffer;
}
else {
data_accumulator += line_buffer;
} // end if
} while (!in_file.eof());
cout << "\n-- Diagnostics ---------------------\n";
cout << "line-buffer = " << line_buffer << '\n';
cout << "data_accumulator = " << data_accumulator << '\n';
cout << "in_file.eof() = " << in_file.eof() << '\n';
cout << "process_data = " << process_data << '\n';
return EXIT_SUCCESS;
} // end main()
//-------------------------------------