簡體   English   中英

文件末尾沒有新行時,fgets無法正確讀取

[英]fgets cannot read correctly when there is no new line at the end of file

問題是,如果文件末尾沒有新行,則fgets顯示錯誤。 假設我有以下兩個文本文件,

text1.txt的內容:

German Hoy
43
68
Jesse Boster
88
29
  • 請注意,文件在29之后完全結束。29之后沒有行。

text2.txt的內容:

German Hoy
43
68
Jesse Boster
88
29
  • 請注意,在29之后還有一行。

我的問題:

文件末尾多一行時,程序對於text2.txt正確運行。 但是,如果我的文件末尾沒有像text1.txt這樣的另一行,則不會。 我怎樣才能解決這個問題? 無論文件末尾有沒有一行,我都希望得到相同的結果。 (在兩種情況下,它應該輸出相同的結果)

以下是與問題相關的部分源代碼:

while( fgets (s, 60, file)!=NULL )  {
        s[strlen(s)-1] = '\0';
        strcpy(tempName, s);

        fgets(s, 60, file);
        s[strlen(s)-1] = '\0';
        sscanf(s, "%d", &tempMid);

        fgets(s, 60, file);
        s[strlen(s)-1] = '\0';
        sscanf(s, "%d", &tempFinal);

        setup(tempName, tempMid, tempFinal);
    }

使用的系統是LINUX

可選地刪除新行:

while( fgets (s, 60, file)!=NULL )  {
  s[strcspn(s, "\n")] = '\0';

不要使用s[strlen(s)-1] = '\\0'; 因為它可以被黑客利用。 fgets()與其他任何非換行符一樣讀取空字符。 行中的第一個字符可以是'\\0' ,然后OP的代碼調用未定義的行為。

此外,在OP代碼中,甚至不需要斷開潛在的換行符。

    fgets(s, 60, file);
    // s[strlen(s)-1] = '\0';
    sscanf(s, "%d", &tempMid);

同樣,最好測試sccanf()的返回值或使用strtol()

您可以在s緩沖區的末尾添加額外的新行,而不管自己

fgets(s, 60, file);
length = strlen(s);
s[length] = '\n';
s[length+1] = '\0';
sscanf(s, "%d", &tempFinal);

重要的提示:

您必須確保緩沖區的長度至少為61個字節以適應新行。

該代碼大約是一個MCVE:

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

int main(void)
{
    char s[60];
    char tempName[60];
    int tempMid;
    int tempFinal;
    FILE *file = stdin;

    while (fgets(s, 60, file) != NULL)
    {
        s[strlen(s) - 1] = '\0';
        strcpy(tempName, s);

        if (fgets(s, 60, file) == NULL)
            break;
        s[strlen(s) - 1] = '\0';
        sscanf(s, "%d", &tempMid);

        if (fgets(s, 60, file) == NULL)
            break;
        s[strlen(s) - 1] = '\0';
        sscanf(s, "%d", &tempFinal);

        printf("[%s] %d %d\n", tempName, tempMid, tempFinal);
    }

    return 0;
}

它采用您編寫的片段,將其包裝在具有兩個標頭的main() ,使其適應於從標准輸入中讀取的內容,並檢查fgets()調用是否全部成功。

我調用了程序fg17 在您的兩個數據文件上運行時,我得到:

$ fg17 < text1.txt
[German Hoy] 43 68
[Jesse Boster] 88 2
$ fg17 <text2.txt
[German Hoy] 43 68
[Jesse Boster] 88 29
$

這是我所期望的,因為您的代碼將換行最后一行的最后一個字符,而不管它是否是換行符。 如果希望輸出包含299 ,則必須更加小心:

s[strcspn(s, "\n")] = '\0';

部署該更改3次后,兩個程序的輸出相同。

有什么不同? strcspn()返回在字符串參數中找不到的字符數,或者返回空字節的字符數。 如果沒有換行符,它將報告空字節,並且賦值操作將用另一個空字節(一個空操作)覆蓋該空字節。 但這是可靠和安全的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM