fscanf() returns negative value - c

I am using fscanf() function to read data line by line from a text file. It was functioning fine but suddenly I don't know what mistake I made and now the function returns a negative value.
below is my code snippet:
FILE *fp;
char ip[16];
int port;
fp = fopen("ClientInformation.txt", "r");
int size = -1;
while (!feof(fp))
{
fgetc(fp);
size++;
}
char buff[1000];
sprintf(buff,"%i",size);
MessageBox(NULL,
buff,
"Size",
MB_ICONINFORMATION);
if(size > 0)
{
while (fscanf(fp, " %s %d", ip, &port) > 0)
{
MessageBox(NULL,"fscanf() Successful","SUCCESS!", MB_ICONINFORMATION);
}
}

You might like to add this call
rewind(fp);
just before
while (fscanf(fp, " %s %d", ip, &port) > 0)
{
Also one should always check the result of system calls. In your case mainly whether fopen() really did return something different from NULL.
Addtionally the while(!feof(fp)) construct mostly likely wouldn't always behave as expected (Why is “while ( !feof (file) )” always wrong?). You'd be better off going the way proposed by WhozCraig in the comment(s) below.

You don't need to determine the file size in advance. Just fscanf() the file and check the return value:
int ret;
while ((ret = fscanf(fp, " %s %d", ip, &port)) == 2) {
MessageBox(NULL,"fscanf() Successful","SUCCESS!", MB_ICONINFORMATION);
}
switch (ret) {
case EOF:
/* EOF or error, check errno */
break;
case 0:
case 1:
/* bogus file contents */
break;
default:
fprintf(stderr, "Philip says this cannot happen, but it did.\n");
exit(EXIT_FAILURE);
}
Also: always check the return value of function calls.

Related

using EOF instead of feof

#include <stdio.h>
int main() {
FILE *fp1, *fp2, *fp3;
int n, i, num, flag = 0;
/* open files to write even, odd seperately */
fp1 = fopen("data.txt", "r");
fp2 = fopen("even.txt", "w");
fp3 = fopen("odd.txt", "w");
fprintf(fp2, "Even Numbers:\n");
fprintf(fp3, "Odd Numbers:\n");
/* print even, odd and prime numbers in separate files */
while (!feof(fp1)) {
fscanf(fp1, "%d", &num);
if (num % 2 == 0) {
fprintf(fp2, "%d ", num);
} else {
if (num > 1) {
for (i = 2; i < num; i++) {
if (num % i == 0) {
flag = 1;
break;
}
}
}
fprintf(fp3, "%d ", num);
flag = 0;
}
}
fprintf(fp2, "\n");
fprintf(fp3, "\n");
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
I want to use EOF instead of feof. I have tried !EOF = fp1 but it doesn't work and gives an error. I just want to replace feof with EOF. can anyone indicate what is the problem in my code?
fscanf returns EOF when the end-of-file is reached:
man fscanf
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
[...]
The scanf() function reads input from the standard input stream stdin, fscanf() reads input from the stream pointer stream, and
sscanf() reads its input from the character string pointed to by str.
[...]
RETURN VALUE
On success, these functions return the number of input items successfully matched and assigned; this can be fewer than provided for, or
even zero, in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs.
EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set
to indicate the error.
A solution would be to read save the return value of fscanf in a int
variable and check it agains 0 and EOF, like this:
If you want to keep using fscanf:
int ret;
while((ret = fscanf(fp1, "%d, &num)) != EOF)
{
if(ret == 0)
{
// fscanf failed to convert the input
// let it consume a charatcer and try again.
getc(fp1);
continue;
}
if(num % 2 == 0)
...
}
edit
Avoid using feof to control looping on a file like this while(!feof(fp), see Why is “while ( !feof (file) )” always wrong? for more
information about that.
edit 2
This was my original idea, but as Jonathan Leffler pointed out in the comments:
Jonathan Leffler wrote:
Your first solution demands a single number per line, which the code in the question does not
He's right, I didn't see that.
me from the past
One option would be to read the input line by line using fgets and then use
sscanf to parse the line:
char buffer[1024];
while(fgets(buffer, sizeof buffer, fp1))
{
if(sscanf(buffer, "%d", &num) != 1)
{
fprintf(stderr, "Could not read an integer, ignoring line\n");
continue;
}
if (num % 2 == 0)
...
}
Your condition for the while loop should be the fscanf() statement itself. EOF is always an integer. See the manual page for fscanf():
Return Value
The fscanf() function returns the number of fields that it successfully converted and assigned. The return value does not include fields that the fscanf() function read but did not assign.
The return value is EOF if an input failure occurs before any conversion, or the number of input items assigned if successful.
And, like everyone else I will refer you to Why is while ( !feof (file) ) always wrong?. This is essential reading on Stack Overflow for new C programmers.
#include <stdio.h>
int main(void) {
FILE *fp1, *fp2, *fp3;
int n, i, num, flag = 0, ret;
/* fopen files */
while ((ret = fscanf(fp1, "%d", &num)) != EOF) {
if (ret == 0) {
getc(fp1);
continue;
}
if (num % 2 == 0) {
fprintf(fp2, "%d ", num);
}
/* rest of the loop here */
}
/* fclose files */
}
If fscanf() fails to read a character, but does not return EOF, it can often solve things to getc(), to advance the buffer by one character. This method also works when using getchar() to advance stdin, after getting user input from scanf().

fprint doesn't work in loop

I am trying to repeatedly read a string from the command line and print it to a file. This is my code:
int main ()
{
FILE* fp=fopen("test.txt","w");
char* tofile[10];
while(1){
printf("cat: ");
scanf("%s",tofile);
fprintf(fp,"%s\n",tofile);
}
return 0;
}
It works just fine outside the loop. But inside, it just doesn't print.
The fprintf function returns the correct amount of characters it has to print.
Note: I know there's a similar question out there, but it hasn't been answered yet, and I hope my code can help in this matter since it's simpler.
Well first it doesn't seem that what you want is reading on the command line.
The command line what you write right when you execute your program such as:
./main things that are on the command line
What it seems you want to do is to read on the standard input.
What you should consider is to use the fgets function, as it has a limit of characters to be read, so that you can store them "safely" into a buffer, like your tofile.
As you want to read on the standard input you can use the stdin stream (which is a FILE* that is automatically created for every program)
The line goes
fgets(tofile, 10, stdin);
Your loop becoming :
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
meaning: as long as we can read on the standard input, print "cat :" and store what we just read in the file controlled by the stream pointer fp.
Some important stuff
When you try to open a stream it may fail and you should test it:
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
Right before exiting your main, you should also close the file and check if it has succeeded, like that for example:
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
The whole thing becomes:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
char tofile[10];
printf("cat: ");
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Improvements
I don't know if it is just a little program or it aspires to become a greater program.
In the last case you should consider using defines and not a magical number such as
#define BUFFER_MAX_SIZE 10
char tofile[BUFFER_MAX_SIZE];
while (fgets(tofile, BUFFER_MAX_SIZE, stdin) != NULL) { ... }
This helps for readability and makes the program less apt to debug when modifying such a size. Because with the define all the part of the code needing the size will still be fully functional without modifying them.
Please also keep in mind that your tofile acts as a buffer, and it's really a small buffer that can easily be overflowed.
This will work. fgets() returns the string it reads from the specified file pointer. If this string returns only a newline ("\n"), that means nothing was entered at stdin.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp = fopen("test.txt","w");
// always check if fopen() == null
if (!fp) {
fprintf(stderr, "Could not write to file\n");
return 1;
}
char tofile[30];
printf("cat: ");
while (fgets(tofile, 30, stdin)) {
if (strcmp(tofile, "\n") == 0)
break;
fprintf(fp, "%s", tofile);
printf("cat: ");
}
// always fclose()
fclose(fp);
return 0;
}
Edited code.

Reading and writing to a file at the same time in C

Supposed to swap every two lines in a file until just one line remains or all lines are exhausted. I don't want to use another file in doing so.
Here's my code:
#include <stdio.h>
int main() {
FILE *fp = fopen("this.txt", "r+");
int i = 0;
char line1[100], line2[100];
fpos_t pos;
fgetpos(fp, &pos);
//to get the total line count
while (!feof(fp)) {
fgets(line1, 100, fp);
i++;
}
i /= 2; //no. of times to run the loop
rewind(fp);
while (i-- > 0) { //trying to use !feof(fp) condition to break the loop results in an infinite loop
fgets(line1, 100, fp);
fgets(line2, 100, fp);
fsetpos(fp, &pos);
fputs(line2, fp);
fputs(line1, fp);
fgetpos(fp, &pos);
}
fclose(fp);
return 0;
}
content in this.txt:
aaa
b
cc
ddd
ee
ffff
gg
hhhh
i
jj
content after running the program
b
aaa
ddd
cc
ddd
c
c
c
i
jj
I've even tried using fseek in place of fgetpos just to get the same wrong result.
From what I figured, after the second while loop has run two times (i.e the first four lines have been processed), the cursor is rightfully at 17th byte where it is supposed to be (as returned by the call to ftell(fp)) and even the file contents after the 4th line are unchanged and somehow for some reason when fgets is called when the loop is running for the third time, the contents read into arrays line1 and line2 are "c\n" and "ddd\n" respectively.
AGAIN, I don't want to use another file to accomplish this, I just need to figure out what exactly is going wrong behind the screen
Any leads would be appreciated. Thank you.
There are multiple problems in your code:
You do not check if fopen() succeeds, risking undefined behavior.
The loop to determine the total number of lines is incorrect.Learn why here: Why is “while ( !feof (file) )” always wrong?
You do not actually need to compute the total number of lines.
You should call fflush() to write the contents back to the file before changing from writing back to reading.
The C Standard specifies this restriction for files open in update mode:
7.21.5.3 The fopen function
[...] output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
This explains why just reading the file position after writing the lines in reverse order causes problems. Calling fflush() should solve this issue.
Here is a corrected version:
#include <stdio.h>
int main(void) {
FILE *fp;
char line1[100], line2[100];
fpos_t pos;
fp = fopen("this.txt", "r+");
if (fp == NULL) {
fprintf(stderr, "cannot open this.txt\n");
return 1;
}
while (fgetpos(fp, &pos) == 0 &&
fgets(line1, sizeof line1, fp) != NULL &&
fgets(line2, sizeof line2, fp) != NULL) {
fsetpos(fp, &pos);
fputs(line2, fp);
fputs(line1, fp);
fflush(fp);
}
fclose(fp);
return 0;
}
The buffer may not necessarily be flushed when changing the current position of the file. So it must be explicitly flushed.
E.g Use fflush(fp);
Change
fputs(line2,fp);
fputs(line1,fp);
to
fputs(line2,fp);
fputs(line1,fp);
fflush(fp);
Why not use two file pointers, both pointing to the same file, one to read and one to write? No need to keep track of the file position, no need to seek around, no need to flush then.
This approach spares you a lot of complicated stuff. Those unnecessary efforts are better invested in some sophisticated error checking/logging like below ;-):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
int result = EXIT_SUCCESS;
size_t blocks = 0;
int l1_done = 0;
int l2_done = 0;
FILE *fpin = fopen("this.txt", "r");
FILE *fpout = fopen("this.txt", "r+");
if (NULL == fpin)
{
result = EXIT_FAILURE;
perror("fopen() to for reading failed");
}
if (NULL == fpout)
{
result = EXIT_FAILURE;
perror("fopen() for writing failed");
}
while (EXIT_SUCCESS == result && !l1_done && !l2_done)
{
result = EXIT_FAILURE;
char line1[100];
char line2[100];
if ((l1_done = (NULL == fgets(line1, sizeof line1, fpin))))
{
if (ferror(fpin))
{
fprintf(stderr, "Reading line %zu failed.\n", 2*blocks);
break;
}
}
if ((l2_done = (NULL == fgets(line2, sizeof line2, fpin))))
{
if (ferror(fpin))
{
fprintf(stderr, "Reading line %zu failed.\n", 2*blocks + 1);
break;
}
}
{
size_t len = strlen(line1);
if (((sizeof line1 - 1) == len) && ('\n' != line1[len]))
{
fprintf(stderr, "Line %zu too long or new-line missing.\n", 2*blocks);
break;
}
}
{
size_t len = strlen(line2);
if (((sizeof line2 - 1) == len) && ('\n' != line2[len]))
{
fprintf(stderr, "Line %zu too long or new-line missing.\n", 2*blocks + 1);
break;
}
}
if (!l2_done)
{
if (EOF == fputs(line2, fpout))
{
fprintf(stderr, "Writing line %zu as line %zu failed.\n", 2*blocks + 1, 2*blocks);
break;
}
}
if (!l1_done)
{
if (EOF == fputs(line1, fpout))
{
fprintf(stderr, "Writing line %zu as line %zu failed.\n", 2*blocks, 2*blocks + 1);
break;
}
}
++blocks;
result = EXIT_SUCCESS;
}
if (EXIT_SUCCESS == result && !ll_done && l2_done)
{
fprintf(stderr, "Odd number of lines.\n");
}
fclose(fpin); /* Perhaps add error checking here as well ... */
fclose(fpout); /* Perhaps add error checking here as well ... */
return result;
}

Basic C Questions. fprintf and fgets failures

I've got some basic c questions that are driving me insane. Let me post my code, and I'll tell you about what's going wrong.
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
static int GetLine();
int main() {
char* sourceFile;
char* destinationFile;
int error, bytesRead;
char* sourceFD;
char* destinationFD;
char buffer[100];
error = GetLine("Please enter a source file name: \n", sourceFile, 100);
if (error == 1) {
printf("A source file was not inputted.\n");
return 0;
}
else if (error == 2) {
printf("Source file is too long.\n");
return 0;
}
error = GetLine("Please enter a destination file name: \n", destinationFile, 100);
if (error == 1) {
printf("A destination file was not inputted.\n");
return 0;
}
else if (error == 2) {
printf("Destination file is too long.\n");
return 0;
}
}
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int GetLine (char *prmpt, char *buff, unsigned int sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf("%s", prmpt);
fflush(stdout);
}
}
if (fgets (buff, sz, stdin) == NULL) {
fprintf(stderr, "fgets returned NULL");
return NO_INPUT;
}
printf("logging input: %s", buff);
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
The errors are occurring in the the GetLine function, which was largely provided by another StackOverflow post. Here are my issues.
No matter what I do, I cannot get debug print statements to work properly. basic printf will often fail. Calling fflush(stdout) immediately after does not help, nor does setbuf(stdout, NULL). Right now I am trying fprintf(stderr), also to no avail. The LOC that continually fails (regardless of the method I try) is fprintf(stderr, "fgets returned NULL"). Note that the application still gives me the error that "A source file was not inputted." It doesn't matter if I target stdout or stderr.
fgets is returning NULL every time. I have no idea why. No, the input I'm providing is not large.
EDIT: I just noticed the missing brackets on that if statement (the fgets one). let me see what that fixes.
if (fgets (buff, sz, stdin) == NULL)
fprintf(stderr, "fgets returned NULL");
return NO_INPUT;
Here return NO_INPUT; is always executed no matter what fgets() returns. Use {} to enclose the two statements.
if (prmpt != NULL) {
printf("%s", prmpt);
fflush(stdout);
}
}
Here you are closing GetLine but your code continues

Printing out each line of an input file twice?

I am writing code which very simply reads in a file and prints out what was in the file appropriately.
I have always struggled with getting such a program to terminate upon end of file and think I've found the appropriate solution, however each line is printing twice in my output, for a reason beyond me.
Here is my main file:
int main(int argc, char *argv[]) {
// insure 2 arguments given, one for a.out and one for the test file
if (argc != 2) {
// result if request fails
printf("Requires 2 arguments. Be sure to include test file location\n");
return 0;
}
FILE *fp; //open the file
fp = fopen(argv[1], "r");
char option;
int key;
int i = 0;
while (fscanf(fp, "%c %d", &option, &key) != EOF) {
printf("%d\n", key);
}
}
The key is printing twice!
Hopefully this is a simple error I'm just overlooking due to overexposure to the problem.
You probably want:
fscanf(fp, "%c %d\n", &option, &key);
And you also want to check the return value of fscanf to make sure it equals 2.
In the first iteration of your loop, the newline is not being consumed.
In the second iteration, the newline is consumed and put in option, and the %d does not match, and fscanf returns 1. key is unchanged which is why it gets printed again.
In the third iteration, fscanf finally returns EOF.
General rule: Always check return values to ensure they are what you expect. (You also violate this rule by failing to check the return from fopen.) At worst it does nothing; at best, it helps you debug problems like this.
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Requires 1 argument - a file name\n");
return 1;
}
FILE *fp; //open the file
if ((fp = fopen(argv[1], "r")) == 0)
{
fprintf(stderr, "Failed to open file %s\n", argv[1]);
return 1;
}
char option;
int key;
while (fscanf(fp, "%c %d", &option, &key) == 2)
printf("%d\n", key);
return 0;
}
Note the changes in error reporting, and in the file reading process. The code is still probably not quite what you want; you might get the newline after the number after the first line of input stored in option after the first line. Fixing that requires fgets() and sscanf():
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Requires 1 argument - a file name\n");
return 1;
}
FILE *fp; //open the file
if ((fp = fopen(argv[1], "r")) == 0)
{
fprintf(stderr, "Failed to open file %s\n", argv[1]);
return 1;
}
char buffer[1024];
while (fgets(buffer, sizeof(buffer), fp) != 0)
{
char option;
int key;
if (fscanf(fp, "%c %d", &option, &key) == 2)
printf("%d\n", key);
else
{
fprintf(stderr, "Format mismatch on %s", buffer);
fclose(fp); // Not 100% necessary here, but tidiness is important
return 1;
}
}
fclose(fp); // Not 100% necessary here, but tidiness is important.
return 0;
}
Although I closed fp before the end, it is not crucial when the program is about to exit, and return from main() is pretty much equivalent to exit(). If it was in a function other than main() though, it is very important to ensure that you free any resource you allocate, such as the file stream fp.
Warning: uncompiled code. Caveat Lector.

Resources