fscanf returns 3 instead of -1 (EOF) at the end of the file
So there's a file I'm using fscanf() in. I've set a condition in my code that when (fscanf(...) == EOF, the program needs to break out of the function I'm currently in. The thing is, this condition is never satisfied in any of the cases where there's no more lines of text in the file. EOF is always -1, whereas fscanf(...) returns 4 each time there's a line of code, and 3 when there's nothing left for it to search through (instead of -1). If I add a line of code similar to the other ones, I will simply get one more instance of fscanf() returning 4, and then again, it'll give me a 3.
What could possibly be the issue? Thank you in advance!
Sample text file content:
CHRISTOU GIORGOS,140,VAS. OLGAS 112
MALAKOU MALAKOS,150,DRAS. BAGAS 12
TSIKOU GIJRAN,140,JABS. DRALGAS 1
TSIKOU BIRBAN,140,JABS. DRALGAS 1
DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62
FOX SIN,40,BAN. NINJA 1
Code:
#include <stdio.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents);
int main()
{
char inputfilename[30];
FILE* infile;
while (1) {
printf("Input file name :");
gets(inputfilename);
infile = fopen(inputfilename, "r");
if (infile != NULL) break;
printf("Cannot open input file %s. Try again.n", inputfilename);
}
studentT students[M];
int numberOfStudents = 0, numberOfApousies = 0;
readInput(infile, students, &numberOfApousies, &numberOfStudents);
fclose(infile);
return 0;
}
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents)
{
int nscan, apousies, studcount, apouscount, line;
char name[30], comments[68], termch;
line = 0;
while (1)
{
nscan = fscanf(infile, "%30[^,], %d, %68[^n]%c", name, &apousies, comments, &termch);
/* printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
printf("%dn", nscan);
printf("%dn", EOF);*/
if (nscan == EOF) break;
line++;
if (nscan != 4 || termch != 'n')
{
printf("Error in line %d. Program terminationn", line);
exit(1);
}
}
}
c scanf eof
|
show 2 more comments
So there's a file I'm using fscanf() in. I've set a condition in my code that when (fscanf(...) == EOF, the program needs to break out of the function I'm currently in. The thing is, this condition is never satisfied in any of the cases where there's no more lines of text in the file. EOF is always -1, whereas fscanf(...) returns 4 each time there's a line of code, and 3 when there's nothing left for it to search through (instead of -1). If I add a line of code similar to the other ones, I will simply get one more instance of fscanf() returning 4, and then again, it'll give me a 3.
What could possibly be the issue? Thank you in advance!
Sample text file content:
CHRISTOU GIORGOS,140,VAS. OLGAS 112
MALAKOU MALAKOS,150,DRAS. BAGAS 12
TSIKOU GIJRAN,140,JABS. DRALGAS 1
TSIKOU BIRBAN,140,JABS. DRALGAS 1
DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62
FOX SIN,40,BAN. NINJA 1
Code:
#include <stdio.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents);
int main()
{
char inputfilename[30];
FILE* infile;
while (1) {
printf("Input file name :");
gets(inputfilename);
infile = fopen(inputfilename, "r");
if (infile != NULL) break;
printf("Cannot open input file %s. Try again.n", inputfilename);
}
studentT students[M];
int numberOfStudents = 0, numberOfApousies = 0;
readInput(infile, students, &numberOfApousies, &numberOfStudents);
fclose(infile);
return 0;
}
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents)
{
int nscan, apousies, studcount, apouscount, line;
char name[30], comments[68], termch;
line = 0;
while (1)
{
nscan = fscanf(infile, "%30[^,], %d, %68[^n]%c", name, &apousies, comments, &termch);
/* printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
printf("%dn", nscan);
printf("%dn", EOF);*/
if (nscan == EOF) break;
line++;
if (nscan != 4 || termch != 'n')
{
printf("Error in line %d. Program terminationn", line);
exit(1);
}
}
}
c scanf eof
2
(fscanf(...) == EOFthe program needs to break out of the function --> That is a weak test. Better to test against the one desired return - perhaps like(fscanf(...) != 4. Please post a Minimal, Complete, and Verifiable example.
– chux
Jan 2 at 23:42
Post definition ofstudentT. The post is better, yet not complete enough to compile.
– chux
Jan 2 at 23:44
I wasn't sure as to which parts of the code were relevant to the question. I hope this helps. Thanks again.
– Leet
Jan 2 at 23:49
1
Please provide a Minimal, Complete, and Verifiable example showing exactly how you are usingfscanf(), particularly your actual format string
– Remy Lebeau
Jan 2 at 23:51
Note that your code is strange. You passpApousiesas a parameter to the functionreadInput, and don't use it. The you declare a local variableapousiesand use it in the call to fscanf. Your test ofnscan == EOFlooks ok to me.
– bruceg
Jan 3 at 0:05
|
show 2 more comments
So there's a file I'm using fscanf() in. I've set a condition in my code that when (fscanf(...) == EOF, the program needs to break out of the function I'm currently in. The thing is, this condition is never satisfied in any of the cases where there's no more lines of text in the file. EOF is always -1, whereas fscanf(...) returns 4 each time there's a line of code, and 3 when there's nothing left for it to search through (instead of -1). If I add a line of code similar to the other ones, I will simply get one more instance of fscanf() returning 4, and then again, it'll give me a 3.
What could possibly be the issue? Thank you in advance!
Sample text file content:
CHRISTOU GIORGOS,140,VAS. OLGAS 112
MALAKOU MALAKOS,150,DRAS. BAGAS 12
TSIKOU GIJRAN,140,JABS. DRALGAS 1
TSIKOU BIRBAN,140,JABS. DRALGAS 1
DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62
FOX SIN,40,BAN. NINJA 1
Code:
#include <stdio.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents);
int main()
{
char inputfilename[30];
FILE* infile;
while (1) {
printf("Input file name :");
gets(inputfilename);
infile = fopen(inputfilename, "r");
if (infile != NULL) break;
printf("Cannot open input file %s. Try again.n", inputfilename);
}
studentT students[M];
int numberOfStudents = 0, numberOfApousies = 0;
readInput(infile, students, &numberOfApousies, &numberOfStudents);
fclose(infile);
return 0;
}
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents)
{
int nscan, apousies, studcount, apouscount, line;
char name[30], comments[68], termch;
line = 0;
while (1)
{
nscan = fscanf(infile, "%30[^,], %d, %68[^n]%c", name, &apousies, comments, &termch);
/* printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
printf("%dn", nscan);
printf("%dn", EOF);*/
if (nscan == EOF) break;
line++;
if (nscan != 4 || termch != 'n')
{
printf("Error in line %d. Program terminationn", line);
exit(1);
}
}
}
c scanf eof
So there's a file I'm using fscanf() in. I've set a condition in my code that when (fscanf(...) == EOF, the program needs to break out of the function I'm currently in. The thing is, this condition is never satisfied in any of the cases where there's no more lines of text in the file. EOF is always -1, whereas fscanf(...) returns 4 each time there's a line of code, and 3 when there's nothing left for it to search through (instead of -1). If I add a line of code similar to the other ones, I will simply get one more instance of fscanf() returning 4, and then again, it'll give me a 3.
What could possibly be the issue? Thank you in advance!
Sample text file content:
CHRISTOU GIORGOS,140,VAS. OLGAS 112
MALAKOU MALAKOS,150,DRAS. BAGAS 12
TSIKOU GIJRAN,140,JABS. DRALGAS 1
TSIKOU BIRBAN,140,JABS. DRALGAS 1
DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62
FOX SIN,40,BAN. NINJA 1
Code:
#include <stdio.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents);
int main()
{
char inputfilename[30];
FILE* infile;
while (1) {
printf("Input file name :");
gets(inputfilename);
infile = fopen(inputfilename, "r");
if (infile != NULL) break;
printf("Cannot open input file %s. Try again.n", inputfilename);
}
studentT students[M];
int numberOfStudents = 0, numberOfApousies = 0;
readInput(infile, students, &numberOfApousies, &numberOfStudents);
fclose(infile);
return 0;
}
void readInput (FILE* infile, studentT students, int *pApousies, int *pStudents)
{
int nscan, apousies, studcount, apouscount, line;
char name[30], comments[68], termch;
line = 0;
while (1)
{
nscan = fscanf(infile, "%30[^,], %d, %68[^n]%c", name, &apousies, comments, &termch);
/* printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
printf("%dn", nscan);
printf("%dn", EOF);*/
if (nscan == EOF) break;
line++;
if (nscan != 4 || termch != 'n')
{
printf("Error in line %d. Program terminationn", line);
exit(1);
}
}
}
c scanf eof
c scanf eof
edited Jan 3 at 0:34
chux
84.3k874154
84.3k874154
asked Jan 2 at 23:35
LeetLeet
387
387
2
(fscanf(...) == EOFthe program needs to break out of the function --> That is a weak test. Better to test against the one desired return - perhaps like(fscanf(...) != 4. Please post a Minimal, Complete, and Verifiable example.
– chux
Jan 2 at 23:42
Post definition ofstudentT. The post is better, yet not complete enough to compile.
– chux
Jan 2 at 23:44
I wasn't sure as to which parts of the code were relevant to the question. I hope this helps. Thanks again.
– Leet
Jan 2 at 23:49
1
Please provide a Minimal, Complete, and Verifiable example showing exactly how you are usingfscanf(), particularly your actual format string
– Remy Lebeau
Jan 2 at 23:51
Note that your code is strange. You passpApousiesas a parameter to the functionreadInput, and don't use it. The you declare a local variableapousiesand use it in the call to fscanf. Your test ofnscan == EOFlooks ok to me.
– bruceg
Jan 3 at 0:05
|
show 2 more comments
2
(fscanf(...) == EOFthe program needs to break out of the function --> That is a weak test. Better to test against the one desired return - perhaps like(fscanf(...) != 4. Please post a Minimal, Complete, and Verifiable example.
– chux
Jan 2 at 23:42
Post definition ofstudentT. The post is better, yet not complete enough to compile.
– chux
Jan 2 at 23:44
I wasn't sure as to which parts of the code were relevant to the question. I hope this helps. Thanks again.
– Leet
Jan 2 at 23:49
1
Please provide a Minimal, Complete, and Verifiable example showing exactly how you are usingfscanf(), particularly your actual format string
– Remy Lebeau
Jan 2 at 23:51
Note that your code is strange. You passpApousiesas a parameter to the functionreadInput, and don't use it. The you declare a local variableapousiesand use it in the call to fscanf. Your test ofnscan == EOFlooks ok to me.
– bruceg
Jan 3 at 0:05
2
2
(fscanf(...) == EOF the program needs to break out of the function --> That is a weak test. Better to test against the one desired return - perhaps like (fscanf(...) != 4. Please post a Minimal, Complete, and Verifiable example.– chux
Jan 2 at 23:42
(fscanf(...) == EOF the program needs to break out of the function --> That is a weak test. Better to test against the one desired return - perhaps like (fscanf(...) != 4. Please post a Minimal, Complete, and Verifiable example.– chux
Jan 2 at 23:42
Post definition of
studentT. The post is better, yet not complete enough to compile.– chux
Jan 2 at 23:44
Post definition of
studentT. The post is better, yet not complete enough to compile.– chux
Jan 2 at 23:44
I wasn't sure as to which parts of the code were relevant to the question. I hope this helps. Thanks again.
– Leet
Jan 2 at 23:49
I wasn't sure as to which parts of the code were relevant to the question. I hope this helps. Thanks again.
– Leet
Jan 2 at 23:49
1
1
Please provide a Minimal, Complete, and Verifiable example showing exactly how you are using
fscanf(), particularly your actual format string– Remy Lebeau
Jan 2 at 23:51
Please provide a Minimal, Complete, and Verifiable example showing exactly how you are using
fscanf(), particularly your actual format string– Remy Lebeau
Jan 2 at 23:51
Note that your code is strange. You pass
pApousies as a parameter to the function readInput, and don't use it. The you declare a local variable apousies and use it in the call to fscanf. Your test of nscan == EOF looks ok to me.– bruceg
Jan 3 at 0:05
Note that your code is strange. You pass
pApousies as a parameter to the function readInput, and don't use it. The you declare a local variable apousies and use it in the call to fscanf. Your test of nscan == EOF looks ok to me.– bruceg
Jan 3 at 0:05
|
show 2 more comments
1 Answer
1
active
oldest
votes
fscanf returns 3 instead of -1 (EOF) at the end of the file
Because the last line lacks a 'n'.
OP's code "works" with the "tmp.txt" the below code makes.
fscanf() is hard to use right. Easier to code and debug with fgets(). Discussion follows.
"%30[^,]" allows too much for char name[30]. Use char name[30+1] or "%29[^,]"
OP's approach can readily fail with seemingly minor parsing problems such as a missing 'n' on the last line. After such a failure, recovery is extraordinary difficult with fscanf()
Debug: Importantly, the below print should not be attempted until code insures nscan >= 4
if (nscan >= 4) // add
printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
Instead, use fgets(). With line orientated data, this really is the best first step.
fscanf() is challenging to use and cope with errors. Far simpler to read a line with fgets() and then parse.
Using " %n" is a nice way to detect if all the line parsed.
#include <stdio.h>
#include <stdlib.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput(FILE* infile, studentT students, int *pApousies,
int *pStudents) {
(void) students;
(void) pApousies;
(void) pStudents;
int line = 0;
char buf[200];
while (fgets(buf, sizeof buf, infile)) {
int apousies;
char name[30], comments[68];
int n = 0;
line++;
sscanf(buf, " %29[^,],%d , %67[^n] %n", name, &apousies, comments, &n);
if (n == 0 || buf[n]) {
fprintf(stderr, "Error in line %d <%s>. Program terminationn", line, buf);
exit(1);
}
printf("Success %d <%s> %d <%s>n", line, name, apousies, comments);
}
}
Sample use
int main() {
FILE *f = fopen("tmp.txt", "w");
fputs("CHRISTOU GIORGOS,140,VAS. OLGAS 112n"
"MALAKOU MALAKOS,150,DRAS. BAGAS 12n"
"TSIKOU GIJRAN,140,JABS. DRALGAS 1n"
"TSIKOU BIRBAN,140,JABS. DRALGAS 1n"
"DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62n"
"FOX SIN,40,BAN. NINJA 1n", f);
fclose(f);
f = fopen("tmp.txt", "r");
studentT st[M];
readInput(f, st, NULL, NULL);
fclose(f);
}
Output
Success 1 <CHRISTOU GIORGOS> 140 <VAS. OLGAS 112>
Success 2 <MALAKOU MALAKOS> 150 <DRAS. BAGAS 12>
Success 3 <TSIKOU GIJRAN> 140 <JABS. DRALGAS 1>
Success 4 <TSIKOU BIRBAN> 140 <JABS. DRALGAS 1>
Success 5 <DELHDHMHTRIOU SPYROS> 50 <SPEED. BAGAS 62>
Success 6 <FOX SIN> 40 <BAN. NINJA 1>
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%2f54014577%2ffscanf-returns-3-instead-of-1-eof-at-the-end-of-the-file%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
fscanf returns 3 instead of -1 (EOF) at the end of the file
Because the last line lacks a 'n'.
OP's code "works" with the "tmp.txt" the below code makes.
fscanf() is hard to use right. Easier to code and debug with fgets(). Discussion follows.
"%30[^,]" allows too much for char name[30]. Use char name[30+1] or "%29[^,]"
OP's approach can readily fail with seemingly minor parsing problems such as a missing 'n' on the last line. After such a failure, recovery is extraordinary difficult with fscanf()
Debug: Importantly, the below print should not be attempted until code insures nscan >= 4
if (nscan >= 4) // add
printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
Instead, use fgets(). With line orientated data, this really is the best first step.
fscanf() is challenging to use and cope with errors. Far simpler to read a line with fgets() and then parse.
Using " %n" is a nice way to detect if all the line parsed.
#include <stdio.h>
#include <stdlib.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput(FILE* infile, studentT students, int *pApousies,
int *pStudents) {
(void) students;
(void) pApousies;
(void) pStudents;
int line = 0;
char buf[200];
while (fgets(buf, sizeof buf, infile)) {
int apousies;
char name[30], comments[68];
int n = 0;
line++;
sscanf(buf, " %29[^,],%d , %67[^n] %n", name, &apousies, comments, &n);
if (n == 0 || buf[n]) {
fprintf(stderr, "Error in line %d <%s>. Program terminationn", line, buf);
exit(1);
}
printf("Success %d <%s> %d <%s>n", line, name, apousies, comments);
}
}
Sample use
int main() {
FILE *f = fopen("tmp.txt", "w");
fputs("CHRISTOU GIORGOS,140,VAS. OLGAS 112n"
"MALAKOU MALAKOS,150,DRAS. BAGAS 12n"
"TSIKOU GIJRAN,140,JABS. DRALGAS 1n"
"TSIKOU BIRBAN,140,JABS. DRALGAS 1n"
"DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62n"
"FOX SIN,40,BAN. NINJA 1n", f);
fclose(f);
f = fopen("tmp.txt", "r");
studentT st[M];
readInput(f, st, NULL, NULL);
fclose(f);
}
Output
Success 1 <CHRISTOU GIORGOS> 140 <VAS. OLGAS 112>
Success 2 <MALAKOU MALAKOS> 150 <DRAS. BAGAS 12>
Success 3 <TSIKOU GIJRAN> 140 <JABS. DRALGAS 1>
Success 4 <TSIKOU BIRBAN> 140 <JABS. DRALGAS 1>
Success 5 <DELHDHMHTRIOU SPYROS> 50 <SPEED. BAGAS 62>
Success 6 <FOX SIN> 40 <BAN. NINJA 1>
add a comment |
fscanf returns 3 instead of -1 (EOF) at the end of the file
Because the last line lacks a 'n'.
OP's code "works" with the "tmp.txt" the below code makes.
fscanf() is hard to use right. Easier to code and debug with fgets(). Discussion follows.
"%30[^,]" allows too much for char name[30]. Use char name[30+1] or "%29[^,]"
OP's approach can readily fail with seemingly minor parsing problems such as a missing 'n' on the last line. After such a failure, recovery is extraordinary difficult with fscanf()
Debug: Importantly, the below print should not be attempted until code insures nscan >= 4
if (nscan >= 4) // add
printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
Instead, use fgets(). With line orientated data, this really is the best first step.
fscanf() is challenging to use and cope with errors. Far simpler to read a line with fgets() and then parse.
Using " %n" is a nice way to detect if all the line parsed.
#include <stdio.h>
#include <stdlib.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput(FILE* infile, studentT students, int *pApousies,
int *pStudents) {
(void) students;
(void) pApousies;
(void) pStudents;
int line = 0;
char buf[200];
while (fgets(buf, sizeof buf, infile)) {
int apousies;
char name[30], comments[68];
int n = 0;
line++;
sscanf(buf, " %29[^,],%d , %67[^n] %n", name, &apousies, comments, &n);
if (n == 0 || buf[n]) {
fprintf(stderr, "Error in line %d <%s>. Program terminationn", line, buf);
exit(1);
}
printf("Success %d <%s> %d <%s>n", line, name, apousies, comments);
}
}
Sample use
int main() {
FILE *f = fopen("tmp.txt", "w");
fputs("CHRISTOU GIORGOS,140,VAS. OLGAS 112n"
"MALAKOU MALAKOS,150,DRAS. BAGAS 12n"
"TSIKOU GIJRAN,140,JABS. DRALGAS 1n"
"TSIKOU BIRBAN,140,JABS. DRALGAS 1n"
"DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62n"
"FOX SIN,40,BAN. NINJA 1n", f);
fclose(f);
f = fopen("tmp.txt", "r");
studentT st[M];
readInput(f, st, NULL, NULL);
fclose(f);
}
Output
Success 1 <CHRISTOU GIORGOS> 140 <VAS. OLGAS 112>
Success 2 <MALAKOU MALAKOS> 150 <DRAS. BAGAS 12>
Success 3 <TSIKOU GIJRAN> 140 <JABS. DRALGAS 1>
Success 4 <TSIKOU BIRBAN> 140 <JABS. DRALGAS 1>
Success 5 <DELHDHMHTRIOU SPYROS> 50 <SPEED. BAGAS 62>
Success 6 <FOX SIN> 40 <BAN. NINJA 1>
add a comment |
fscanf returns 3 instead of -1 (EOF) at the end of the file
Because the last line lacks a 'n'.
OP's code "works" with the "tmp.txt" the below code makes.
fscanf() is hard to use right. Easier to code and debug with fgets(). Discussion follows.
"%30[^,]" allows too much for char name[30]. Use char name[30+1] or "%29[^,]"
OP's approach can readily fail with seemingly minor parsing problems such as a missing 'n' on the last line. After such a failure, recovery is extraordinary difficult with fscanf()
Debug: Importantly, the below print should not be attempted until code insures nscan >= 4
if (nscan >= 4) // add
printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
Instead, use fgets(). With line orientated data, this really is the best first step.
fscanf() is challenging to use and cope with errors. Far simpler to read a line with fgets() and then parse.
Using " %n" is a nice way to detect if all the line parsed.
#include <stdio.h>
#include <stdlib.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput(FILE* infile, studentT students, int *pApousies,
int *pStudents) {
(void) students;
(void) pApousies;
(void) pStudents;
int line = 0;
char buf[200];
while (fgets(buf, sizeof buf, infile)) {
int apousies;
char name[30], comments[68];
int n = 0;
line++;
sscanf(buf, " %29[^,],%d , %67[^n] %n", name, &apousies, comments, &n);
if (n == 0 || buf[n]) {
fprintf(stderr, "Error in line %d <%s>. Program terminationn", line, buf);
exit(1);
}
printf("Success %d <%s> %d <%s>n", line, name, apousies, comments);
}
}
Sample use
int main() {
FILE *f = fopen("tmp.txt", "w");
fputs("CHRISTOU GIORGOS,140,VAS. OLGAS 112n"
"MALAKOU MALAKOS,150,DRAS. BAGAS 12n"
"TSIKOU GIJRAN,140,JABS. DRALGAS 1n"
"TSIKOU BIRBAN,140,JABS. DRALGAS 1n"
"DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62n"
"FOX SIN,40,BAN. NINJA 1n", f);
fclose(f);
f = fopen("tmp.txt", "r");
studentT st[M];
readInput(f, st, NULL, NULL);
fclose(f);
}
Output
Success 1 <CHRISTOU GIORGOS> 140 <VAS. OLGAS 112>
Success 2 <MALAKOU MALAKOS> 150 <DRAS. BAGAS 12>
Success 3 <TSIKOU GIJRAN> 140 <JABS. DRALGAS 1>
Success 4 <TSIKOU BIRBAN> 140 <JABS. DRALGAS 1>
Success 5 <DELHDHMHTRIOU SPYROS> 50 <SPEED. BAGAS 62>
Success 6 <FOX SIN> 40 <BAN. NINJA 1>
fscanf returns 3 instead of -1 (EOF) at the end of the file
Because the last line lacks a 'n'.
OP's code "works" with the "tmp.txt" the below code makes.
fscanf() is hard to use right. Easier to code and debug with fgets(). Discussion follows.
"%30[^,]" allows too much for char name[30]. Use char name[30+1] or "%29[^,]"
OP's approach can readily fail with seemingly minor parsing problems such as a missing 'n' on the last line. After such a failure, recovery is extraordinary difficult with fscanf()
Debug: Importantly, the below print should not be attempted until code insures nscan >= 4
if (nscan >= 4) // add
printf("onoma: %s apousies: %d sxolia: %s terma: %cn", name, apousies, comments, termch);
Instead, use fgets(). With line orientated data, this really is the best first step.
fscanf() is challenging to use and cope with errors. Far simpler to read a line with fgets() and then parse.
Using " %n" is a nice way to detect if all the line parsed.
#include <stdio.h>
#include <stdlib.h>
#define M 100
typedef struct {
char name[30];
int apousies;
} studentT;
void readInput(FILE* infile, studentT students, int *pApousies,
int *pStudents) {
(void) students;
(void) pApousies;
(void) pStudents;
int line = 0;
char buf[200];
while (fgets(buf, sizeof buf, infile)) {
int apousies;
char name[30], comments[68];
int n = 0;
line++;
sscanf(buf, " %29[^,],%d , %67[^n] %n", name, &apousies, comments, &n);
if (n == 0 || buf[n]) {
fprintf(stderr, "Error in line %d <%s>. Program terminationn", line, buf);
exit(1);
}
printf("Success %d <%s> %d <%s>n", line, name, apousies, comments);
}
}
Sample use
int main() {
FILE *f = fopen("tmp.txt", "w");
fputs("CHRISTOU GIORGOS,140,VAS. OLGAS 112n"
"MALAKOU MALAKOS,150,DRAS. BAGAS 12n"
"TSIKOU GIJRAN,140,JABS. DRALGAS 1n"
"TSIKOU BIRBAN,140,JABS. DRALGAS 1n"
"DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62n"
"FOX SIN,40,BAN. NINJA 1n", f);
fclose(f);
f = fopen("tmp.txt", "r");
studentT st[M];
readInput(f, st, NULL, NULL);
fclose(f);
}
Output
Success 1 <CHRISTOU GIORGOS> 140 <VAS. OLGAS 112>
Success 2 <MALAKOU MALAKOS> 150 <DRAS. BAGAS 12>
Success 3 <TSIKOU GIJRAN> 140 <JABS. DRALGAS 1>
Success 4 <TSIKOU BIRBAN> 140 <JABS. DRALGAS 1>
Success 5 <DELHDHMHTRIOU SPYROS> 50 <SPEED. BAGAS 62>
Success 6 <FOX SIN> 40 <BAN. NINJA 1>
edited Jan 3 at 4:23
answered Jan 3 at 0:10
chuxchux
84.3k874154
84.3k874154
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%2f54014577%2ffscanf-returns-3-instead-of-1-eof-at-the-end-of-the-file%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
2
(fscanf(...) == EOFthe program needs to break out of the function --> That is a weak test. Better to test against the one desired return - perhaps like(fscanf(...) != 4. Please post a Minimal, Complete, and Verifiable example.– chux
Jan 2 at 23:42
Post definition of
studentT. The post is better, yet not complete enough to compile.– chux
Jan 2 at 23:44
I wasn't sure as to which parts of the code were relevant to the question. I hope this helps. Thanks again.
– Leet
Jan 2 at 23:49
1
Please provide a Minimal, Complete, and Verifiable example showing exactly how you are using
fscanf(), particularly your actual format string– Remy Lebeau
Jan 2 at 23:51
Note that your code is strange. You pass
pApousiesas a parameter to the functionreadInput, and don't use it. The you declare a local variableapousiesand use it in the call to fscanf. Your test ofnscan == EOFlooks ok to me.– bruceg
Jan 3 at 0:05