Disclaimer this is for a homework question. Not asking for a full solution to the program I am writing, just asking for better understanding of what is happening. Thanks in advance.
The provided function is reading from a file that looks like this.
foo;bar
foo;bar
And I would like to modify the function to read from a file that looks like
foo;bar;foobar
foo;bar;foobar
The provided function looks like
void EntryList::loadfile(const char filefoo[])
{
ifstream in;
char foo[MAX_CHAR];
char bar[MAX_CHAR];
AddressEntry anEntry;
in.open (filefoo);
if(!in)
{
in.clear();
cerr << endl << "Fail to open " << filefoo << " for input!" << endl << endl;
exit(1);
}
in.get(foo, MAX_CHAR, ';');
while (!in.eof())
{
in.get(); //remove field seperator ';'
in.get(bar, MAX_CHAR, '\n');
in.ignore(100, '\n'); //remove record seperator '\n'
anEntry.setfoo(foo);
anEntry.setbar(bar);
addEntry(anEntry);
in.get(foo, MAX_CHAR, ';'); //start the next record
}
in.close();
}
The function that I modified looks like
void EntryList::loadfile(const char fileName[])
{
ifstream in;
char foo[MAX_CHAR];
char bar[MAX_CHAR];
char foobar[MAX_CHAR];
TaskList theEntry;
in.open(fileName);
if (!in) {
in.clear();
cerr << endl
<< "Failed to open "
<< fileName
<< " for input!" << endl << endl;
exit(1);
}
in.get(foo, MAX_CHAR, ';');
while (!in.eof())
{
in.get(); // rm ;
in.get(bar, MAX_CHAR, ';');
in.get(foobar, MAX_CHAR, '\n'); // rm '\n'
in.ignore(100, '\n');
theEntry.setfoo(foo);
theEntry.setbar(bar);
theEntry.setfoobar(foobar);
addEntry(theEntry);
in.get(foo, MAX_CHAR, ';');
}
in.close();
}
I am in the middle of rewriting this program for at least the 4 time. and I have modified the file how I (humanly) think I should to this. I have had issues in the past, doing it this way. (still working on the other parts of the program so I cannot be too specific right now, but I know my results were unexpected ) So my question is does the function that I modified look correct for what I am trying to do? Am I off by one? I guess I am struggling with understanding how the original function is working. (step by step systematically.) hence my confusion about my modified function.
I can also provide any other functions you would like to take look at, my setters and getters. Also if you have any questions or feedback I would appreciate it greatly.
Both the orginal and the modified functions are wrong: you alway need to check for successful input after trying to read something (I guess, if I eventually pass away my headstone will have that engraved...). Using in.eof()
to control an input loop in general does not work!
If the line ends in a string with less than MAX_CHAR
characters, the next line get ignored: you need to check if the input ends in a newline character and, if not, ignore the remaining character. If the last input ends with a newline character, you don't want to ignore characters. Also, if the line happens to end in a string with more than 100 characters, it also doesn't work. The magical constant for std::istream::ignore()
to ignore as many characters as necessary is, inconveniently, spelled std::numeric_limits<std::streamsize>::max()
and is declared in the header <limits
>.
Basically, your loop should start with
while (in.getline(foo, MAX_CHAR, ';')
.getline(bar, MAX_CHAR, ';')
.get(foobar, MAX_CHAR, '\n')) {
if (foobar[in.gcount() - 1] == '\n') {
foobar[in.gcount() - 1] = '\0';
}
else {
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
// process the inputs
}
The code uses std::istream::getline()
for the first two components to avoid the separate to be stored: it is sufficient if the separator is extracted and the input is stopped. For the last component std::istream::get()
is used because it is necessary to verify if the last character stored was a newline. The last character stored is access using std::istream::gcount()
which contains the number of characters stored by the last unformatted input function. Since the input succeeded and it would stop either when storing a newline or after storing MAX_CHAR
characters, in.gcount() - 1
is always a valid index. Note, however, that the code is not tested...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.