how to do this

G

Gernot Frisch

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
int main(int argc, char** argv) {printf
("%silto%c%cf%cgl%ssic%ccom%c", "ma", 58, 'g', 64, "ba", 46, 10);}

________________________________________
Looking for a good game? Do it yourself!
GLBasic - you can do
www.GLBasic.com
 
K

Karl Heinz Buchegger

Gernot said:
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))

a loop like that is allmost always wrong. The reason
is that eof gets true only until you try and *failed* to
read data from the file.

In C++ (and C++) the way to write such a loop is:


while( data_can_be_read )
process_data

// while loop terminated. But why? If it was
// because of eof, then everything is ok - the
// file was read correctly till the end

if( !feof( .. ) )
output_error_message( "Failure during read from file" );

Note, that this construction also correctly and easily accounts
for all possible things that can go wrong during reading of a file:
Someone took out the floppy disk, the disk had a hardware error, etc.

Is for the part:
while( data_can_be_read )

look at all the read functions C++ (and C) has. All of them
return a value that can easily be used for checking if the
function performed successfully or if something happend.
{
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

for the last read data chunk, yes.
Is there any better way of doing this?

Well. Put the processing into a function of its own and simply
call it from 2 places.
once inside the loop
once after the loop to process the rest (if there is any).

No big deal.
 
G

Gernot Frisch

Well. Put the processing into a function of its own and simply
call it from 2 places.
once inside the loop
once after the loop to process the rest (if there is any).

No big deal.

That's the way I'm doing it now. I was just wondering, if there is a
way of calling this function only once in such a situation...
 
R

rossum

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()

//-------------------------------------
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Staff online

Members online

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,498
Latest member
log5Sshell/alfa5

Latest Threads

Top