Behaviour of fstream in C++
I have made the following script, that is supposed to read from a file:
char match = "match";
int a;
int b;
inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;
inp >> lin;
inp.close();
return num_atm;
}
It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.
My input file is this:
match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6
It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.
I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.
It goes back to the match in the fourth line which it already read, and reads it again. Why is this?
c++ fstream
|
show 1 more comment
I have made the following script, that is supposed to read from a file:
char match = "match";
int a;
int b;
inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;
inp >> lin;
inp.close();
return num_atm;
}
It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.
My input file is this:
match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6
It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.
I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.
It goes back to the match in the fourth line which it already read, and reads it again. Why is this?
c++ fstream
eofwithin loop: Have a look at here (more important aspect: you do not catch fail in given case).
– Aconcagua
Nov 13 '18 at 19:11
Stepping through the code with a debugger should solve this for you in short order.
– user4581301
Nov 13 '18 at 19:11
Simplify your life and usestd::stringandstd::getline.
– Thomas Matthews
Nov 13 '18 at 19:15
@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.
– PenguinHook
Nov 13 '18 at 19:19
linis not defined
– M.M
Nov 14 '18 at 0:16
|
show 1 more comment
I have made the following script, that is supposed to read from a file:
char match = "match";
int a;
int b;
inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;
inp >> lin;
inp.close();
return num_atm;
}
It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.
My input file is this:
match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6
It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.
I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.
It goes back to the match in the fourth line which it already read, and reads it again. Why is this?
c++ fstream
I have made the following script, that is supposed to read from a file:
char match = "match";
int a;
int b;
inp >> lin;
while(!inp.eof())
if(!strcmp(lin, match))
inp >> a >> b;
cout << a << " " << b <<endl;
inp >> lin;
inp.close();
return num_atm;
}
It is supposed to read all words, and if a line starts with match, it should then also print the rest of the line.
My input file is this:
match 1 2 //1
match 5 2 //2
nope 3 6 //3
match 5 //4
match 1 4 //5
match 5 9 //6
It will correctly print 1 2, 5 2, and skip 3 6. But then, it will get stuck and keep printing 5 0 and continue printing 5 0 for ever. I get that match is put into b, which is an integer, but I don't get why this is looped. Shouldn't the input read match 4 once, try to read/write 5 and match, and then be done with line 4 and the match from line 5? Then it should next read the number 1 and 4 and then match from number 6.
I would also understand that due to the word not fitting into the integer, it would read match in the fifth line again, but that's not what it does.
It goes back to the match in the fourth line which it already read, and reads it again. Why is this?
c++ fstream
c++ fstream
asked Nov 13 '18 at 19:08
PenguinHookPenguinHook
1
1
eofwithin loop: Have a look at here (more important aspect: you do not catch fail in given case).
– Aconcagua
Nov 13 '18 at 19:11
Stepping through the code with a debugger should solve this for you in short order.
– user4581301
Nov 13 '18 at 19:11
Simplify your life and usestd::stringandstd::getline.
– Thomas Matthews
Nov 13 '18 at 19:15
@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.
– PenguinHook
Nov 13 '18 at 19:19
linis not defined
– M.M
Nov 14 '18 at 0:16
|
show 1 more comment
eofwithin loop: Have a look at here (more important aspect: you do not catch fail in given case).
– Aconcagua
Nov 13 '18 at 19:11
Stepping through the code with a debugger should solve this for you in short order.
– user4581301
Nov 13 '18 at 19:11
Simplify your life and usestd::stringandstd::getline.
– Thomas Matthews
Nov 13 '18 at 19:15
@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.
– PenguinHook
Nov 13 '18 at 19:19
linis not defined
– M.M
Nov 14 '18 at 0:16
eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).– Aconcagua
Nov 13 '18 at 19:11
eof within loop: Have a look at here (more important aspect: you do not catch fail in given case).– Aconcagua
Nov 13 '18 at 19:11
Stepping through the code with a debugger should solve this for you in short order.
– user4581301
Nov 13 '18 at 19:11
Stepping through the code with a debugger should solve this for you in short order.
– user4581301
Nov 13 '18 at 19:11
Simplify your life and use
std::string and std::getline.– Thomas Matthews
Nov 13 '18 at 19:15
Simplify your life and use
std::string and std::getline.– Thomas Matthews
Nov 13 '18 at 19:15
@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.
– PenguinHook
Nov 13 '18 at 19:19
@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.
– PenguinHook
Nov 13 '18 at 19:19
lin is not defined– M.M
Nov 14 '18 at 0:16
lin is not defined– M.M
Nov 14 '18 at 0:16
|
show 1 more comment
1 Answer
1
active
oldest
votes
When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see
match 1 2
match 5 2
nope 3 6
match 5
match 1 4
match 5 9
But the program sees
match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9
Let's fast forward to where things go south
Contents of stream:
nope 3 6 match 5 match 1 4 match 5 9
Processing
inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // nope != match skip body
inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 3 != match skip body
inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 6 != match skip body
inp >> lin; // reads match stream: 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads 5 and fails to parse match into an integer.
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints 5 and garbage because b was not read
inp >> lin; // reads nothing. Stream failed
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads nothing. Stream failed
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints g and garbage because b was not read
Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.
Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like
std::string line;
while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.
std::istringstream strm(line);
std::string lin;
if(strm >> lin && lin == match) // enters if lin was read and lin == match
// if lin can't be read, it doesn't matter.
// strm is disposable
int a;
int b;
if (strm >> a >> b) // enters if both a and b were read
cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.
Output from this should be something like
1 2
5 2
1 4
5 9
If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287933%2fbehaviour-of-fstream-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see
match 1 2
match 5 2
nope 3 6
match 5
match 1 4
match 5 9
But the program sees
match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9
Let's fast forward to where things go south
Contents of stream:
nope 3 6 match 5 match 1 4 match 5 9
Processing
inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // nope != match skip body
inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 3 != match skip body
inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 6 != match skip body
inp >> lin; // reads match stream: 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads 5 and fails to parse match into an integer.
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints 5 and garbage because b was not read
inp >> lin; // reads nothing. Stream failed
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads nothing. Stream failed
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints g and garbage because b was not read
Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.
Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like
std::string line;
while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.
std::istringstream strm(line);
std::string lin;
if(strm >> lin && lin == match) // enters if lin was read and lin == match
// if lin can't be read, it doesn't matter.
// strm is disposable
int a;
int b;
if (strm >> a >> b) // enters if both a and b were read
cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.
Output from this should be something like
1 2
5 2
1 4
5 9
If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.
add a comment |
When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see
match 1 2
match 5 2
nope 3 6
match 5
match 1 4
match 5 9
But the program sees
match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9
Let's fast forward to where things go south
Contents of stream:
nope 3 6 match 5 match 1 4 match 5 9
Processing
inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // nope != match skip body
inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 3 != match skip body
inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 6 != match skip body
inp >> lin; // reads match stream: 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads 5 and fails to parse match into an integer.
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints 5 and garbage because b was not read
inp >> lin; // reads nothing. Stream failed
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads nothing. Stream failed
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints g and garbage because b was not read
Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.
Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like
std::string line;
while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.
std::istringstream strm(line);
std::string lin;
if(strm >> lin && lin == match) // enters if lin was read and lin == match
// if lin can't be read, it doesn't matter.
// strm is disposable
int a;
int b;
if (strm >> a >> b) // enters if both a and b were read
cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.
Output from this should be something like
1 2
5 2
1 4
5 9
If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.
add a comment |
When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see
match 1 2
match 5 2
nope 3 6
match 5
match 1 4
match 5 9
But the program sees
match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9
Let's fast forward to where things go south
Contents of stream:
nope 3 6 match 5 match 1 4 match 5 9
Processing
inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // nope != match skip body
inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 3 != match skip body
inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 6 != match skip body
inp >> lin; // reads match stream: 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads 5 and fails to parse match into an integer.
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints 5 and garbage because b was not read
inp >> lin; // reads nothing. Stream failed
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads nothing. Stream failed
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints g and garbage because b was not read
Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.
Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like
std::string line;
while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.
std::istringstream strm(line);
std::string lin;
if(strm >> lin && lin == match) // enters if lin was read and lin == match
// if lin can't be read, it doesn't matter.
// strm is disposable
int a;
int b;
if (strm >> a >> b) // enters if both a and b were read
cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.
Output from this should be something like
1 2
5 2
1 4
5 9
If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.
When you are reading with >> line enndings are handled the same as spaces: They are just more whitespace that is skipped. That means you see
match 1 2
match 5 2
nope 3 6
match 5
match 1 4
match 5 9
But the program sees
match 1 2 match 5 2 nope 3 6 match 5 match 1 4 match 5 9
Let's fast forward to where things go south
Contents of stream:
nope 3 6 match 5 match 1 4 match 5 9
Processing
inp >> lin; // reads nope stream: 3 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // nope != match skip body
inp >> lin; // reads 3 stream: 6 match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 3 != match skip body
inp >> lin; // reads 6 stream: match 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // 6 != match skip body
inp >> lin; // reads match stream: 5 match 1 4 match 5 9
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads 5 and fails to parse match into an integer.
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints 5 and garbage because b was not read
inp >> lin; // reads nothing. Stream failed
if(!strcmp(lin, match)) // match != match Enter body
inp >> a >> b; // reads nothing. Stream failed
// stream: match 1 4 match 5 9
// stream now in failure state
cout << a << " " << b <<endl; // prints g and garbage because b was not read
Because nothing is ever read, while(!inp.eof()) is utterly worthless. The end of the file can never be reached. The program will loop forever, probably printing whatever it last read. Successfully read.
Fixing this depends entirely on what you want to do if you have a match line without 2 numbers on it, but a typical framework looks something like
std::string line;
while(std::getline(inp, line) // get a whole line. Exit if line can't be read for any reason.
std::istringstream strm(line);
std::string lin;
if(strm >> lin && lin == match) // enters if lin was read and lin == match
// if lin can't be read, it doesn't matter.
// strm is disposable
int a;
int b;
if (strm >> a >> b) // enters if both a and b were read
cout << a << " " << b <<"n"; // endl flushes. Very expensive. just use a newline.
Output from this should be something like
1 2
5 2
1 4
5 9
If you want to make some use of match 5... Well it's up to you what you want to put in b if there is no b in the file.
answered Nov 13 '18 at 23:49
user4581301user4581301
19.8k51831
19.8k51831
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287933%2fbehaviour-of-fstream-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
eofwithin loop: Have a look at here (more important aspect: you do not catch fail in given case).– Aconcagua
Nov 13 '18 at 19:11
Stepping through the code with a debugger should solve this for you in short order.
– user4581301
Nov 13 '18 at 19:11
Simplify your life and use
std::stringandstd::getline.– Thomas Matthews
Nov 13 '18 at 19:15
@Aconcagua I see! I know how to fix it, but I don't understand why data gets re-read when fail is set to true.
– PenguinHook
Nov 13 '18 at 19:19
linis not defined– M.M
Nov 14 '18 at 0:16