Any idea why my print function prints and then runs forever? - c

Any idea why my print function prints and then runs forever before crashing?
void readDataFile(){
FILE* fp = fopen("text.txt","r");
int t=0;
while(fp !=EOF){
text[t] = fgetc(fp);
printf("%c",text[t]);
t++;
}
fclose(fp);
}

Check compiler warnings (e.g.: gcc -Wall file.c). You should get a warning on the line "while(fp !=EOF){" that you are comparing a pointer to an integer. The function works if you rewrite the while statement as:
while ((text[t] = fgetc(fp)) != EOF){
printf("%c",text[t]);
t++;
}
Notice that you need to look for EOF in the character retrieved by fgetc, not in the file pointer fp.

You need to start the loop with a condition that is true and then end it when it becomes false. Otherwise the loop does not know when the condition becomes false i.e. it is always true and therefore it continues to loop. My obs.

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);
}

Read every character from file

I want to read each element of my text file which includes new lines and also spaces. Here is my code
void test3()
{
char a;
FILE *csv;
csv=fopen64("C:\\Users\\Md. Akash\\Desktop\\csv\\Book1.csv","r");
int i;
for(i=0;;i++)
{
if(fgetc(csv)==EOF)
break;
a=fgetc(csv);
printf("%c",a);
}
}
This code skips one character.
You're calling fgetc twice in every iteration of the for loop. And you are not printing what you get the first time.
Change:
if(fgetc(csv)==EOF)
break;
a=fgetc(csv);
printf("%c",a);
to:
if((a = fgetc(csv))==EOF)
break;
printf("%c",a);
Note: fgetc returns an int. So a should be defined as an int.
Try replacing for loop by the following:
/*
Note:
a = fgetc(csv) returns a character from the file pointed to by **csv** o returns **EOF** if the End Of File is reached.
Therefore, it is probably a good idea to read every character from the file until the EOF is reached.
The following **while** loop demonstrate just that.
*/
while((a =fgetc(csv)) != EOF){
printf("%c", a)
}

Segmentation fault when opening file in C?

I'm very new to programming and I'm trying to write code that reads "numbers.tsv4" (.tsv4 means tab separated values, 4 to a line) and puts the numbers into an array. Right now I'm just focusing on counting the amount of numbers in a file, so I can initialize the array size.
int main(void)
{
int cur;
FILE* spData;
int size=1;
spData = fopen("numbers.tsv4", "r");
while ((cur = fgetc(spData)) != EOF) {
if ((cur = fgetc(spData)) == '\t') {
size++;}
}
fclose(spData);
printf("%d", size);
return;
}
I keep getting a segmentation fault and I've changed so many things to try to figure it out. Could someone give me a hand? Thanks!
The structure with your while statement is the problem. At the beginning of each iteration, you are already getting the next character with fgetc() and assigning it to cur. Then inside the loop, in the if(...) statement, you discard the cur by calling a new fgetc() and assigning the result to cur. So, change it in the following way:
while ((cur = fgetc(spData)) != EOF) {
if (cur == '\t') {
size++;}
}
You see, when you try to invoke the fgetc() twice (both in while(...) and if(...)), you probably get the EOF in the if(...) statement. Then in the next iteration with the while(...) statement, you try to access somewhere out of file, which gives you the segmentation fault.

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);

how to stop reading from file in 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

Resources