how to stop reading from file in C - c

I am just trying to read each character of the file and print it out but when the file finishes reading, but I am getting a bunch of ? after it finishes reading. How do I fix it?
#include <stdio.h>
int main(void){
FILE *fr; /* declare the file pointer */
fr = fopen ("some.txt", "r"); /* open the file for reading */
/* elapsed.dta is the name of the file */
/* "rt" means open the file for reading text */
char c;
while((c = getc(fr)) != NULL)
{
printf("%c", c);
}
fclose(fr); /* close the file prior to exiting the routine */
/*of main*/
return 0;
}

In spite of its name, getc returns an int, not a char, so that it can represent all of the possible char values and, in addition, EOF (end of file). If getc returned a char, there would be no way to indicate the end of file without using one of the values that could possibly be in the file.
So, to fix your code, you must first change the declaration char c; to int c; so that it can hold the EOF marker when it is returned. Then, you must also change the while loop condition to check for EOF instead of NULL.
You could also call feof(fr) to test end of file separately from reading the character. If you did that, you could leave c as a char, but you would have to call feof() after you read the character but before you printed it out, and use a break to get out of the loop.

If unsuccessful, fgetc() returns EOF.
int c;
while ((c = getc(fr)) != EOF)
{
printf("%c", c);
}

Change this
char c;
while((c = getc(fr)) != NULL)
{
printf("%c", c);
}
to
char c;
int charAsInt;
while((charAsInt = getc(fr)) != EOF)
{
c = (char) charAsInt;
printf("%c", c);
}
In other words: You need to compare against EOF, not NULL. You also need to use an int variable to receive the return value from fgetc. If you use a char, the comparison with EOF may fail, and you'll be back where you started.

fgetc() returns EOF on end-of-file, not NULL.

Replace "NULL" with "EOF".

Others have already addressed the issue you're having, but rather than using printf("%c", c); it is probably much more efficient to use putchar(c);. There is quite a bit of overhead involved when you ask printf to print just one character.

getc returns an int.
change char c, to int c.
also getc returns EOF,
change your test against NULL to a test against EOF

Related

Can someone please explain why I'm getting infinite loop in this code?

#include<stdio.h>
int main()
{
char name[20];
FILE *fptr=fopen("Student1.txt","w");
fputc('J',fptr);
fclose(fptr);
FILE *ptr=fopen("Student1.txt","r");
char ch;
// ch=fgetc(ptr);
fscanf(ptr,"%c",&ch);
while(ch!=EOF)
{
printf("%c",ch);
fscanf(ptr,"%c",&ch);
}
printf("\n");
fclose(ptr);
return 0;
}
I have been getting an infinite loop when I run this code.
I'm stuck at this code for so long now.
Please try to help.
An infinite loop typically means that the loop condition ch != EOF remains true forever. The only way you set ch is via the two calls to fscanf(ptr,"%c",&ch);. fscanf() returns EOF when the end of a file is reached which is different than setting the (out) argument ch. Here is how I would write it:
#include <stdio.h>
int main() {
FILE *fptr=fopen("Student1.txt","w");
if(!fptr) {
printf("fopen failed\n");
return 1;
}
fputc('J',fptr);
fclose(fptr);
FILE *ptr=fopen("Student1.txt","r");
if(!ptr) {
printf("fopen failed\n");
return 1;
}
for(;;) {
char ch;
int r = fscanf(ptr,"%c",&ch);
if(r == EOF)
break;
if(r != 1) {
printf("fscanf failed\n");
return 1;
}
printf("%c",ch);
}
printf("\n");
fclose(ptr);
return 0;
}
Consider refactoring the two fopen() calls into a single FILE * fptr = fopen(..., "rw") then truncate the file with ftruncate(fileno(fptr), 0).
The problem is that fgetch() and fscanf() have different interfaces.
fgetch() returns an int value to designate all the possible character values (from 0 to 255) and also EOF (which is none of them, generally implemented as -1). fgetch() returns EOF to indicate the end of file condition (which is not a character, but merely a situation)
fscanf() stores a representation of the char just read in the variable pointed to. But it will never store EOF in the variable (indeed, it will store nothing at all, in the case of an end of file condition), as EOF doesn't represent a character, it is not worth storing it in a char variable.
fscanf() returns the number of format specifiers that it could satisfy, so in this case
// ch=fgetc(ptr);
fscanf(ptr,"%c",&ch);
while(ch!=EOF)
{
printf("%c",ch);
fscanf(ptr,"%c",&ch);
}
that will never happen (It will, in case you enter a char value that could be converted as a signed integer into the value EOF has, just try to enter the character value 0xff (in case you can do that from the keyboard). But that is completely incorrect, as the character stored in the variable would be a true character (that happens to convert to -1 when converted to an int) and it can happen in the middle of a file. The infinite loop happens because on an end of file, nothing is stored on the char variable, and so ch never changes again, if it was not the magic character described above, it will never satisfy the condition to get out of the loop.
The actual behaviour of fscanf() is that it will return 1 for all the characters actually read, and 0, on satisfying the end of file condition. A good working example would be:
while (fscanf(ptr, "%c", &ch) == 1) {
printf("%c",ch);
fscanf(ptr,"%c",&ch);
}

In C, is it possible to read a char from getchar's current buffer position without moving the buffer's pointer?

I have a file that's been passed as stdin in my program. Every iteration of a very large loop, a method "get_next" calls getchar, and gets the next char in stdin and assigns it to a variable named nchar.
The problem is, I have an instance where I have to look at the char after the current nchar without changing what the next call to get_next does. Meaning, I have to call getchar() without it changing the buffer's state.
Is there a way to do this? Is there a method like "getcharStatic" that returns the next char without changing the buffer, à la peek vs pop for a stack?
Alternatively, is there a way to read the char normally with getchar and then insert the char right where I took it from, thereby artificially conserving the buffer's state?
I tried googling for a while, and I think the problem involves too vague terms and tags. Thanks for any help!
You can use ungetc() to push the character back into stdin. Here's a blurb from the doc:
int ungetc( int ch, FILE *stream );
If ch does not equal EOF, pushes the character ch (reinterpreted as unsigned char) into the input
buffer associated with the stream stream in such a manner that
subsequent read operation from stream will retrieve that character.
You can use ungetc(), maybe like this:
int fpeekc(FILE *fp)
{
int c = getc(fp);
if (c != EOF)
ungetc(c, fp);
return c;
}
Careful reading of the POSIX specification indicates that you could call ungetc() with EOF and the call would be ignored, so it isn't 100% necessary to make the test in the fpeekc() function, but it does make ungetc() fail and return EOF. If you like living — dangerously, or compactly; take your choice — you could use:
int fpeekc(FILE *fp)
{
return ungetc(getc(fp), fp);
}
And if you desired, you could make that an inline function. If you are on POSIX and need to be thread-safe, you can use:
int fpeekc(FILE *fp)
{
flockfile(fp);
int c = getc_unlocked(fp); // Legitimate because of flockfile(); getc(fp) works too
if (c != EOF)
{
// ungetc_unlocked() is not defined by POSIX but is available on
// some but not all POSIX-like systems. See comments below.
ungetc(c, fp);
}
funlockfile(fp);
return c;
}
That prevents another thread from interfering with the stream while you're working on it. See also the discussion with Nominal Animal in the comments below.
And you could use:
static inline int peekc(void) { return fpeekc(stdin); }
if you want to do it for standard input.
I think you want int ungetc(int char, FILE *stream).
You could have a method:
char fgetputbackc(file *f){
int c = fgetc(f);
ungetc(c, f);
return c;
}

Understanding fgetc program

I'm reading a book about c programming and don't understand a shown example. Or more precisely I don't understand why it works because I would think it shouldn't.
The code is simple, it reads the content of a text file and outputs it in output area. As far as I understand it, I would think that the
ch = fgetc(stream);
ought to be inside the while loop, because it only reads one int a time? and needs to read the next int after the current one has been outputted. Well, it turns out that this code indeed works fine so I hope someone could explain my fallacy to me. Thanks!
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *stream;
char filename[67];
int ch;
printf("Please enter the filename?\n");
gets(filename);
if((stream = fopen(filename, "r")) == NULL) {
printf("Error opening the file\n");
exit(1);
}
ch = fgetc(stream);
while (!feof(stream)) {
putchar(ch);
ch = fgetc(stream);
}
fclose(stream);
}
I think you are confuse because of feof():
Doc: int feof ( FILE * stream );
Checks whether the end-of-File indicator associated with stream is
set, returning a value different from zero if it is.
This indicator is generally set by a previous operation on the stream
that attempted to read at or past the end-of-file.
ch = fgetc(stream); <---"Read current symbol from file"
while (!feof(stream)) { <---"Check EOF read/returned by last fgetc() call"
putchar(ch); <---"Output lasts read symbol, that was not EOF"
ch = fgetc(stream); <---"Read next symbols from file"
}
<-- control reach here when EOF found
A much better way is to write your loop like:
while((ch = fgetc(stream))!= EOF){ <--" Read while EOF not found"
putchar(ch); <-- "inside loop print a symbol that is not EOF"
}
Additionally, Note: int fgetc ( FILE * stream );
Returns the character currently pointed by the internal file position
indicator of the specified stream. The internal file position
indicator is then advanced to the next character.
If the stream is at the end-of-file when called, the function returns
EOF and sets the end-of-file indicator for the stream (feof).
If a read error occurs, the function returns EOF and sets the error
indicator for the stream (ferror).
If the fgetc outside while is removed, like this:
while (!feof(stream)) {
putchar(ch);
ch = fgetc(stream);
}
ch will be un-initialized the first time putchar(ch) is called.
By the way, don't use gets, because it may cause buffer overflow. Use fgets or gets_s instead. gets is removed in C11.
The code you have provided has 'ch =fgetc(stream);' before the While loop and also
'ch = fgetc(stream);' within the body of the loop.
It would be logical that the statement within the loop is retrieving the ch from the stream one at a time as you correctly state.
It is inside and outside as you see. The one outside is responsible for reading the first character (which may be already the end of file, then the while wouldn't be entered anyway and nothing is printed), then it enters the loop, puts the character and reads the next one.. as long as the read character is not the end of file, the loop continues.
This is because of second fgetc which is getting call upto while (!feof(stream)).
fgetc() reads a char(byte) and return that byte,The reading of byte value depends on where the read pointer is available.
Once fgetc() successfully read one byte the read file pointer moves to the next byte .so if you read the file the next byte will be the output and it will continue upto it find the end of the file where it return EOF.
Actually this part here:
while (!feof(stream)) {
putchar(ch);
ch = fgetc(stream);
}
is pretty unsafe and you should avoid checking EOF like that (here why).
The way you should read a file using fgetc is like so:
int ch;
while ((ch = fgetc(stream)) != EOF)
{
printf("%c", ch)
}
This is non functional code. Last character from file is never outputted. fgetc will read last character and pointer will be at end of file. So, when while is checked, !feof will return false, and read character will not be outputed.
feofis not preventing reading after end of file: for empty files fgetc will be called before feof!
Unless there is some benefit in console handling, two better options exist:
Using feof:
while (!feof(stream)) {
ch=fgetc(stream);
putchar(ch);
}
Without using feof - because fgetc returns EOF when there are no more characters:
while ((ch=fgetc(stream))!=EOF) putchar(ch);

While (( c = getc(file)) != EOF) loop won't stop executing

I can't figure out why my while loop won't work. The code works fine without it... The purpose of the code is to find a secret message in a bin file. So I got the code to find the letters, but now when I try to get it to loop until the end of the file, it doesn't work. I'm new at this. What am I doing wrong?
main(){
FILE* message;
int i, start;
long int size;
char keep[1];
message = fopen("c:\\myFiles\\Message.dat", "rb");
if(message == NULL){
printf("There was a problem reading the file. \n");
exit(-1);
}
//the first 4 bytes contain an int that tells how many subsequent bytes you can throw away
fread(&start, sizeof(int), 1, message);
printf("%i \n", start); //#of first 4 bytes was 280
fseek(message, start, SEEK_CUR); //skip 280 bytes
keep[0] = fgetc(message); //get next character, keep it
printf("%c", keep[0]); //print character
while( (keep[0] = getc(message)) != EOF) {
fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);
keep[0] = fgetc(message);
printf("%c", keep[0]);
}
fclose(message);
system("pause");
}
EDIT:
After looking at my code in the debugger, it looks like having "getc" in the while loop threw everything off. I fixed it by creating a new char called letter, and then replacing my code with this:
fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);
while( (letter = getc(message)) != EOF) {
printf("%c", letter);
fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);
}
It works like a charm now. Any more suggestions are certainly welcome. Thanks everyone.
The return value from getc() and its relatives is an int, not a char.
If you assign the result of getc() to a char, one of two things happens when it returns EOF:
If plain char is unsigned, then EOF is converted to 0xFF, and 0xFF != EOF, so the loop never terminates.
If plain char is signed, then EOF is equivalent to a valid character (in the 8859-1 code set, that's ÿ, y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS), and your loop may terminate early.
Given the problem you face, we can tentatively guess you have plain char as an unsigned type.
The reason that getc() et al return an int is that they have to return every possible value that can fit in a char and also a distinct value, EOF. In the C standard, it says:
ISO/IEC 9899:2011 §7.21.7.1 The fgetc() function
int fgetc(FILE *stream);
If the end-of-file indicator for the input stream pointed to by stream is not set and a
next character is present, the fgetc function obtains that character as an unsigned char converted to an int ...
If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-
file indicator for the stream is set and the fgetc function returns EOF.
Similar wording applies to the getc() function and the getchar() function: they are defined to behave like the fgetc() function except that if getc() is implemented as a macro, it may take liberties with the file stream argument that are not normally granted to standard macros — specifically, the stream argument expression may be evaluated more than once, so calling getc() with side-effects (getc(fp++)) is very silly (but change to fgetc() and it would be safe, but still eccentric).
In your loop, you could use:
int c;
while ((c = getc(message)) != EOF) {
keep[0] = c;
This preserves the assignment to keep[0]; I'm not sure you truly need it.
You should be checking the other calls to fgets(), getc(), fread() to make sure you are getting what you expect as input. Especially on input, you cannot really afford to skip those checks. Sooner, rather than later, something will go wrong and if you aren't religiously checking the return statuses, your code is likely to crash, or simply 'go wrong'.
There are 256 different char values that might be returned by getc() and stored in a char variable like keep[0] (yes, I'm oversummarising wildly). To detect end-of-file reliably, EOF has to have a value different from all of them. That's why getc() returns int rather than char: because a 257th distinct value for EOF wouldn't fit into a char.
Thus you need to store the value returned by getc() in an int at least until you check it against EOF:
int tmpc;
while( (tmpc = getc(message)) != EOF) {
keep[0] = tmpc;
...

Unknown Logical Error Using the getc() Function in C

I'm attempting to use the getc() function to copy the contents of one file into another. But I'm making an unknown logical error because the output of the following program is a bunch of garbage.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *f;
FILE *write;
f = fopen("nums.csv","r");
write = fopen("numsWrite.dat","w");
char tempChar;
int i;
for(i = 0; (tempChar = getc(f)) != EOF; i++)
{
tempChar = getc(f);
fprintf(write,"%c",tempChar);
}
fprintf(write,"\n");
fclose(f);
fclose(write);
return 0;
}
content of nums.csv is:
1256,2548,35151,15,56,38
program returns:
2624,55,55,8
There are several problems with your code.
int main() should be int main(void); this is a minor issue that almost certainly won't hurt anything, but the latter is more correct.
You don't check whether the fopen() calls succeed.
You're using i to count the characters you read, but you never do anything with its value.
The getc() function returns a result of type int, so you should definitely make tempChar an int. The reason for this is that it can return either a valid character value (which will fit in a char object) or the value EOF which is typically -1. By storing the result of getc() in a char object, either you'll never see EOF (if plain char is unsigned), or you won't be able to distinguish EOF from a valid input character.
In a comment on Razvan's answer, you said you changed the test to tempChar != EOF. Apart from the problem I explained above, on the first iteration of the loop tempChar has not been initialized, and the result of the comparison is unpredictable.
The conventional way to write an input loop using getc() is:
int c;
while ((c = getc(f)) != EOF) {
/* do something with c */
}
As a matter of style, write is not a very good name for a FILE*. For one thing, there's a function of that name (defined by POSIX, not by C, but it's still potentially confusing). You might call the FILE* objects in and out instead.
You call getc two times: once in the for condition and once in the for body. Delete this line: tempChar = getc(f); and try again.

Resources