簡體   English   中英

從C中讀取和打印文件時的奇數輸出

[英]Odd output when reading and printing from file in C

我寫了一個程序,它將讀取並輸出自己的源文件的內容。 我的目的主要是學習如何使用I / O流和“FILE”類型。 我在Linux Ubuntu 14.04上的純文本文檔中編寫了程序,並使用終端編譯和運行程序。 這是從編譯到完成的終端內容:

joseph@ubuntu:~/Desktop$ gcc test.c
joseph@ubuntu:~/Desktop$ ./a.out

File Opened

#include<stdio.h>
#define fileLocation ("/home/joseph/Desktop/test.c")
#define MAXREAD 1000

int main(void)
{
    char fileContents[MAXREAD];
    int i;

    FILE *tf;
    tf = fopen(fileLocation, "r");

    printf("File Opened\n");
    for(i=0;fileContents[i] != EOF; i++)
    {
        fileContents[i] = fgetc(tf);
        printf("%c", fileContents[i]);
    }
    fclose(tf);
    printf("\nFile Closed\n");
    return 0;
}
************************************************************

File Closed

*符號實際上是Unicode(0 + FFFD:替換字符),但我似乎無法輸入。

我的問題是,為什么它不會在最后的結束大括號結束程序而是打印一堆替換字符?

循環中的順序不正確。 存儲和打印字符值之前,您應該檢查EOF。 您還應該確保不會超越數組邊界。

int main(void)
{
    char fileContents[MAXREAD];
    int i, c;

    FILE *tf = fopen(fileLocation, "r");
    if (tf == NULL)
    {
        perror(fileLocation);
        return EXIT_FAILURE;
    }

    printf("File Opened\n");
    for (i=0; i < MAXREAD && (c = fgetc(tf)) != EOF; ++i)
    {
        fileContents[i] = c;
        fputc(fileContents[i], stdout);
    }
    fclose(tf);
    printf("\nFile Closed\n");
    return 0;
}

您的代碼版本包括在char打印錯誤存儲的EOF(這本身就是另一個問題,但首先不存儲它可以避免)。 但這遠遠不是你困境的結束。 用於繼續for循環的條件邏輯是錯誤的。 實際上,由於你從不初始化fileContents[] ,它實際上會調用未定義的行為 每次迭代,您都要檢查一個尚未編寫的數組槽,也不會進行初始化。 繼續閱讀如何/為什么

為什么要繼續打印

在每次循環迭代之前計算控制表達式fileContents[i] != EOF 增量表達式i++ 每次迭代之后但在下一次控制條件評估之前執行。 從標准:

該聲明

for ( clause-1 ; expression-2 ; expression-3 ) statement

行為如下:表達式expression-2是在每次執行循環體之前計算的控制表達式。 在每次執行循環體之后, expression-3被評估為void表達式。 如果clause-1是一個聲明,它聲明的任何標識符的范圍是聲明的剩余部分和整個循環,包括其他兩個表達式; 它是在控制表達式的第一次評估之前按執行順序到達的。 如果clause-1是表達式,則在第一次控制表達式求值之前將其計算為void表達式。

坦率地說,你剛剛保存在fileContents[i]的EOF永遠不會被檢查,因為i在下一次評估之前會增加。 根據以上描述,這是有意義的。 這就是簡單循環的原因:

for (i=0; i<N; ++i)
    dostuff;

退出時i < N 除非在dostuff無法預料的修改, dostuff循環將以i = N結束。

同樣,eval在增量步驟之后完成,因此在您的情況下:

for(i=0; fileContents[i] != EOF; i++)

在每次進入循環體之前評估控制表達式fileContents[i] != EOF 循環體增量表達發生,但控制表達的接下來的評測之前 在循環體內,您將EOF存儲在以當前值i索引的槽中。 然后身體完成, i會增加,然后才會檢查你沒有寫任何東西的插槽(還)。 這一直持續到某一點,如果你(非)幸運,你會在新更新的i索引中發現EOF等值。 因此你終止(但很可能,你在此之前已經很久就崩潰了)。

暫無
暫無

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

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