Reputation: 4887
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
FILE *fp;
fp=fopen("mydata.txt","r");
if(fp==NULL)
{
perror("Error while opening");
exit(0);
}
char *s=(char*)malloc(100);
while(feof(fp)!=EOF)
{
fscanf(fp,"%[^\n]",s);
printf("%s",s);
}
return 0;
}
I am trying to read a file line by line.I am getting infinite loop.Where it has gone wrong ?
Upvotes: 2
Views: 9878
Reputation: 108988
If the contents of the file are
"foo\nbar\n"
after reading "foo" into s
the first time through the loop, what will the fscanf do next?
Always check the return value of scanf
if (fscanf(fp,"%[^\n]",s) == 1) {
/* fscanf "worked" */
} else {
/* fscanf "didn't work" */
}
Edit: example usage of scanf
return value
int suminputs() {
unsigned a, b, c, d
int sum = 0;
switch (scanf("%u%u%u%u", &a, &b, &c, &d)) {
case 4: sum += d; /* fall through */ /* 4 inputs converted */
case 3: sum += c; /* fall through */ /* 3 inputs converted */
case 2: sum += b; /* fall through */ /* 2 inputs converted */
case 1: sum += a; /* fall through */ /* 1 inputs converted */
case 0: break; /* no inputs converted */
default: sum = -1; /* input error */
}
return sum;
}
Upvotes: 3
Reputation: 363567
Use
while (!feof(fp))
feof
returns a non-zero value at EOF, not necessarily EOF
. Then, your call to fscanf
reads up to a newline. After the first call, the fp
points to the first newline in your file, so you have to "swallow" that, else fscanf
doesn't read anything:
fscanf(fp,"%[^\n]\n",s);
Note that this also shallows space and tab characters. You may use getc(fp)
instead, but then add another check to see if that fails, since otherwise you'll be printing the last line twice.
(Finally, you might want to print the newline back out with printf("%s\n", s);
)
Upvotes: 1
Reputation: 881453
You can use the following code to do it.
Your problems were that you weren't checking the return from fscanf
and that you weren't actually reading the newline (so the next time you read, you wouldn't go to the next line).
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main (void) {
FILE *fp;
int x;
fp=fopen("mydata.txt","r");
if(fp==NULL) {
perror("Error while opening");
exit(0);
}
char *s=(char*)malloc(100);
while(!feof(fp)) {
x = fscanf(fp,"%[^\n]",s);
fgetc(fp);
if (x == 1)
printf("%s\n",s);
}
return 0;
}
However, if all you're after is the ability to input and process lines, fgets
is a better solution than fscanf
since there's no chance of buffer overflow:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// 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;
}
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
printf ("No input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long\n");
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
Sample runs with 'hello', CTRLD, and a string that's too big:
pax> ./qq
Enter string> hello
OK [hello]
pax> ./qq
Enter string>
No input
pax> ./qq
Enter string> dfgdfgjdjgdfhggh
Input too long
pax> _
Upvotes: 0
Reputation: 1868
It should work by !feof(fp) if that still doesn't work, try fgets()
Upvotes: -1