Linux C getline, gets, fgets 函數區別


getline, gets, fgets都支持從標准輸入讀取一行字符串,那么它們有什么區別呢?
解答:

  1. gets 不推薦使用,gets(s) 等價於 fgets(s, INT_MAX, stdin),因為沒有對緩沖區溢出做處理,不安全;
  2. getline 碰到EOF返回-1,fgets返回NULL;
  3. 傳入getline的buffer指針如果為NULL,函數會分配緩沖區用於存儲行字符串,並由調用者釋放。如果傳入buffer空間不足以存放一行,那么函數會自動擴增緩沖區空間,同時更新其指針及緩沖區大小。
    傳入fgets的buffer空間如果不足以存放一行,fgets提前返回,並在末尾添加null byte('\0')。

getline

getline有2個版本:getline和getdelim。

getline原型

#include <stdio.h>

ssize_t getline(char **lineptr, size_t *n, FILE *stream);
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);

getline從stream(流)讀取一整行字符串,存放到緩沖區buffer,並將buffer地址存儲到指針lineptr。其中,buffer以空字符('\0')結尾,並且包含換行符。
如果在調用getline之前,
lineptr被設置為NULL,n被設置為0,getline()將會分配(new/malloc)一個buffer用於存儲一行文本。該buffer應該由調用者釋放,即使getline調用失敗。
如果在調用getline之前,buffer不夠大,getline()會用realloc重新分配其大小,同時更新
lineptr和*n。

也就是說,getline存放一行字符串的buffer可以由調用者提供,也可以由函數分配;然而,釋放都是由調用者進行。

DESCRIPTION
       getline()  reads  an entire line from stream, storing the address of the buffer containing the text
       into *lineptr.  The buffer is null-terminated and includes the newline character, if one was found.

       If *lineptr is set to NULL and *n is set 0 before the call, then getline() will allocate  a  buffer
       for storing the line.  This buffer should be freed by the user program even if getline() failed.

       Alternatively,  before  calling  getline(), *lineptr can contain a pointer to a malloc(3)-allocated
       buffer *n bytes in size.  If the buffer is not large enough to hold the line, getline() resizes  it
       with realloc(3), updating *lineptr and *n as necessary.

       In either case, on a successful call, *lineptr and *n will be updated to reflect the buffer address
       and allocated size respectively.

       getdelim() works like getline(), except that a line delimiter other than newline can  be  specified
       as  the  delimiter  argument.  As with getline(), a delimiter character is not added if one was not
       present in the input before end of file was reached.

RETURN VALUE
       On success, getline() and getdelim() return the number of characters read, including the  delimiter
       character,  but  not  including the terminating null byte ('\0').  This value can be used to handle
       embedded null bytes in the line read.

       Both functions return -1 on failure to read a line (including end-of-file condition).  In the event
       of an error, errno is set to indicate the cause.

getline使用示例

來自getline page

int
main(int argc, char *argv[])
{
    FILE *stream;
    char *line = NULL;
    size_t len = 0;
    ssize_t nread;

    printf("hello main\n");

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <file>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    stream = fopen(argv[1], "r");
    if (stream == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    while ((nread = getline(&line, &len, stream)) != -1) {
        printf("Retrieved line of length %zu:\n", nread);
        fwrite(line, nread, 1, stdout);
    }

    free(line);
    fclose(stream);
    exit(EXIT_SUCCESS);
}

gets

符合C89, C99, POSIX.1-2001.,不過目前已經棄用,推薦使用fgets
gets(s)相當於fgets(s, INT_MAX, stdin) + 替換末尾換行符為'\0'。不過,這樣並不不安全,因為gets不會檢查s是否會溢出。

fgets

fgets原型

#include <stdio.h>

char *fgets(char *s, int size, FILE *stream);

fgets最多從指定stream流讀取 size-1個字符,並且存儲到s指向的buffer中。讀取遇到EOF或換行符停止。每讀取一行,buffer末尾會自動添加'\0'。

fgets() reads in at most one less than size characters from stream and
stores them into the buffer pointed to by s. Reading stops after an
EOF or a newline. If a newline is read, it is stored into the buffer.
A terminating null byte ('\0') is stored after the last character in
the buffer.

也就是說,fgets存放一行字符串的buffer必須是由調用者提供,fgets不會分配任何存儲字符串的空間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM