# behavior of fgetln()



## bkouhi (Jun 16, 2013)

Hi,

I can't figure out how fgetln(3)() works. Here is the code:


```
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>

int main(void)
{
        char *line;
        char *fname = "/path/to/input.txt";

        size_t *length;

        FILE *in;

        in = fopen(fname, "r");

        if (in == NULL)
        {
                printf("Error opening the file\n");
                exit(EXIT_FAILURE);
        }

        line = fgetln(in, length);

        printf("bytes read: %zd\n", *length);

        if( line == NULL )
        {
                printf("file is empty\n");
                exit(EXIT_FAILURE);
        }
        else
                printf("strlen(line):  %zd\n", strlen(line));

        printf("The content: \n%s", line);

        fclose(in);

        return 0;
}
```

input.txt:

```
Hello
This is the first line.
And this is the second line.
This one is the last line.
```

The output:

```
[CMD]% ./a.out [/CMD]
bytes read: 6
strlen(line):  86
The content: 
Hello
This is the first line.
And this is the second line.
This one is the last line.
```

Why bytes read and strlen(line) are not equal? I expect that fgetline(3)() just returns a pointer to the first line of the file (although without ending "\0", as described in the manual page), but why the whole content of the file is printed?


----------



## fonz (Jun 16, 2013)

bkouhi said:
			
		

> ```
> size_t *length;
> [...]
> line = fgetln(in, length);
> ...


For starters, I think your code contains an error: I get a segmentation fault while running it. As it turns out, you only declare a _pointer_ to a size_t, not an actual size_t. Why your code doesn't crash on you I don't know,  but I suggest you replace the above lines by

```
size_t length;
[...]
line=fgetln(in,&length);
```

Second: fgetln() indeed merely returns a _pointer to an unterminated string_ that contains the line you read and more. You need to use length to isolate the line in question, for example by using strncpy(3) or snprintf(3) or strndup(3) or memcpy(3) or something. Example:

```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
   char *buf;
   FILE *fp;
   char *fname = "/path/to/input.txt";
   size_t length;
   char *line;

   if(!(fp=fopen(fname, "r")))
   {
     perror("fopen()");
     exit(EXIT_FAILURE);
   }
   while((buf=fgetln(fp,&length)))
   {
     if(!(line=strndup(buf,length)))
     {
       perror("strndup()");
       exit(EXIT_FAILURE);
     }
     (void)printf("%s",line);
   }
   if(ferror(fp))
   {
     perror("fgetln()");
     exit(EXIT_FAILURE);
   }
   (void)fclose(fp);
   return 0;
}
```


----------



## bkouhi (Jun 16, 2013)

fonz said:
			
		

> fgetln() indeed merely returns a pointer to an unterminated string that contains the line you read and more. You need to use length to isolate the line.



Hi. This is exactly what I was looking for. Many thanks. So I should not use printf(3)() to print the line string because it is not null-terminated. Your code has many valuable information for me. I didn't know about perror(3)(), so I can debug my codes easily with that.

Besides the functions that you introduced, this is another method to print the line string with printf():


```
line[length - (size_t)1] = '\0']

Many thanks [USER=414]@fonz[/USER] ;)
```


----------



## fonz (Jun 16, 2013)

bkouhi said:
			
		

> So I should not use printf(3)() to print the line string because it is not null-terminated.
> [snip]
> this is another method to print the line string with printf():
> 
> ...


Or you could do this:

```
(void)printf("%.*s",length,line);
```


----------

