Jagan
Jagan

Reputation: 4887

problem with fscanf inside while loop in c-language

#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

Answers (4)

pmg
pmg

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

Fred Foo
Fred Foo

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

paxdiablo
paxdiablo

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

prap19
prap19

Reputation: 1868

It should work by !feof(fp) if that still doesn't work, try fgets()

Upvotes: -1

Related Questions