2017-04-02 53 views
2

我曾經使用get,但後來我聽說它已從c11中刪除,並且它的整體非常危險。 所以我做了一些搜索,發現你可以使用fgets()來做同樣的事情。替代獲取?

問題是,當我使用fgets()時,它似乎也複製了行的末尾,最終導致了額外的不需要的行。

要告訴你我是什麼意思:

//if I have 
char key[30]; 
fgets(key, sizeof(key), stdin); 

//now if ender for instance: Doggo and do: 
printf("The key is:%s|hozaah!\n", key); 

//I expect it to print: 
The key is:Doggo|hozaah! 

//Instead it prints: 
The key is:Doggo 
|hozaah! 

有沒有辦法來解決這個問題?還是有另一個功能,我可以使用呢?

+1

發現密鑰[strcspn(key,「\ n」)] = 0;像魅力一樣工作,謝謝! – Mathue24

+0

@Kerrek冷酷的傢伙,他只是想幫忙,不需要如此自大大聲笑 – Mathue24

+0

@ Mathue24:是的,道歉,夠公平。我對C字符串周圍的糟糕貨物查詢有些過於敏感,因爲大多數軟件漏洞都來自對字符串的理解不足和錯誤理解。這是我想讓人們仔細思考的問題。 –

回答

4

沒有標準的直接替換gets(),但有很多簡單的方法,如果存在的話擺脫換行符:

  • 使用strcspn最簡單的(在<string.h>聲明):

    if (fgets(buf, sizeof buf, fp)) { 
        buf[strcspn(buf, "\n")] = '\0'; 
    } 
    
  • 經典使用strlen

    if (fgets(buf, sizeof buf, fp)) { 
        size_t len = strlen(buf); 
        if (len > 0 && buf[len - 1] == '\n') 
         buf[--len] = '\0'; 
    } 
    
  • strchr另一個經典:

    if (fgets(buf, sizeof buf, fp)) { 
        char *p = strchr(buf, '\n'); 
        if (p != NULL) 
         *p = '\0'; 
    } 
    

另一種是POSIX功能getline()這可能是您的系統上:

#include <stdio.h> 
ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

的緩衝區分配或malloc()和重新分配其大小更新爲*n。初始值應該是lineptr = NULLn = 0

1

答案就在於這樣一個事實:fgets讀取儘可能多的字符裝入緩衝區,包括空終止,但最多隻能到文件結尾或換行符的,它會店換行符字符串中,太:man 3 fgets

所以,如果你在終端輸入輸入,換行符也傳輸到標準輸入,並通過fgets讀取。這與舊的gets不同,後者用空字節替換換行符。

因此,如果您正在閱讀各行並且不想要潛在的換行符,請將其刪除。不幸的是,fgets不會告訴你有多少個字符中讀取,所以你必須重新掃描串去解決它:

char* p = fgets(key, sizeof(key), stdin); 

if (!p) { /* error */ } 

size_t n = strlen(key); 

if (n > 0 && key[n - 1] == '\n') { 
    key[n - 1] = '\0'; 
} else { 
    /* buffer too short or EOF reached without newline */ 
} 

printf("The line was: '%s'\n", key); 

這可能是值得考慮的選擇:如果你只需要一個輸入,不首先輸入換行符。如果您需要很多線路,請使用fread進入固定大小的緩衝區並自行掃描換行符。

+0

[Demo](https://wandbox.org/permlink/AwlDxatyy7fnSuXF),試着用和不用輸入換行符。 –